fix: Change messages.source_id to text column (#12908)

## Summary
Changes `messages.source_id` from `string` (255 char limit) to `text`
(20,000 char limit) to support long email Message-ID headers.

## Changes
- Migration to change column type from string to text
- Added spec tests for source_id length validation

## Related
Fixes
https://linear.app/chatwoot/issue/CW-5961/activerecordrecordinvalid-validation-failed-source-is-too-long-maximum
This commit is contained in:
Vinay Keerthi
2025-11-20 11:41:41 +05:30
committed by GitHub
parent a44192bbe7
commit 9a2136caf1
4 changed files with 54 additions and 3 deletions

View File

@@ -20,7 +20,7 @@
# conversation_id :integer not null
# inbox_id :integer not null
# sender_id :bigint
# source_id :string
# source_id :text
#
# Indexes
#

View File

@@ -0,0 +1,9 @@
class ChangeMessagesSourceIdToText < ActiveRecord::Migration[7.1]
def up
change_column :messages, :source_id, :text
end
def down
change_column :messages, :source_id, :string
end
end

View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2025_11_14_173609) do
ActiveRecord::Schema[7.1].define(version: 2025_11_19_161025) do
# These extensions should be enabled to support this database
enable_extension "pg_stat_statements"
enable_extension "pg_trgm"
@@ -954,7 +954,7 @@ ActiveRecord::Schema[7.1].define(version: 2025_11_14_173609) do
t.datetime "updated_at", precision: nil, null: false
t.boolean "private", default: false, null: false
t.integer "status", default: 0
t.string "source_id"
t.text "source_id"
t.integer "content_type", default: 0, null: false
t.json "content_attributes", default: {}
t.string "sender_type"

View File

@@ -45,6 +45,48 @@ RSpec.describe Message do
end
end
end
context 'when it validates source_id length' do
it 'valid when source_id is within text limit (20000 chars)' do
long_source_id = 'a' * 10_000
message.source_id = long_source_id
expect(message.valid?).to be true
end
it 'valid when source_id is exactly 20000 characters' do
long_source_id = 'a' * 20_000
message.source_id = long_source_id
expect(message.valid?).to be true
end
it 'invalid when source_id exceeds text limit (20000 chars)' do
long_source_id = 'a' * 20_001
message.source_id = long_source_id
message.valid?
expect(message.errors[:source_id]).to include('is too long (maximum is 20000 characters)')
end
it 'handles long email Message-ID headers correctly' do
# Simulate a long Message-ID like some email systems generate
long_message_id = "msg-#{SecureRandom.hex(240)}@verylongdomainname.example.com"[0...500]
message.source_id = long_message_id
message.content_type = 'incoming_email'
expect(message.valid?).to be true
expect(message.source_id.length).to eq(500)
end
it 'allows nil source_id' do
message.source_id = nil
expect(message.valid?).to be true
end
it 'allows empty string source_id' do
message.source_id = ''
expect(message.valid?).to be true
end
end
end
describe 'concerns' do