## Description Fixes CW-5961 where IMAP email processing failed with `ActiveRecord::RecordInvalid: Validation failed: Source is too long (maximum is 255 characters)` error. This changes the `contact_inboxes.source_id` column from `string` (255 character limit) to `text` (unlimited) to accommodate long email message IDs that were causing validation failures. Fixes CW-5961 ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - Added spec test validating `source_id` values longer than 255 characters (300 chars) - All existing `contact_inbox_spec.rb` tests pass (7 examples, 0 failures) - Migration applied successfully with reversible up/down methods - Verified `source_id` column type changed to `text` with `null: false` constraint preserved ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes
80 lines
2.5 KiB
Ruby
80 lines
2.5 KiB
Ruby
# == Schema Information
|
|
#
|
|
# Table name: contact_inboxes
|
|
#
|
|
# id :bigint not null, primary key
|
|
# hmac_verified :boolean default(FALSE)
|
|
# pubsub_token :string
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
# contact_id :bigint
|
|
# inbox_id :bigint
|
|
# source_id :text not null
|
|
#
|
|
# Indexes
|
|
#
|
|
# index_contact_inboxes_on_contact_id (contact_id)
|
|
# index_contact_inboxes_on_inbox_id (inbox_id)
|
|
# index_contact_inboxes_on_inbox_id_and_source_id (inbox_id,source_id) UNIQUE
|
|
# index_contact_inboxes_on_pubsub_token (pubsub_token) UNIQUE
|
|
# index_contact_inboxes_on_source_id (source_id)
|
|
#
|
|
|
|
class ContactInbox < ApplicationRecord
|
|
include Pubsubable
|
|
include RegexHelper
|
|
validates :inbox_id, presence: true
|
|
validates :contact_id, presence: true
|
|
validates :source_id, presence: true
|
|
validate :valid_source_id_format?
|
|
|
|
belongs_to :contact
|
|
belongs_to :inbox
|
|
|
|
has_many :conversations, dependent: :destroy_async
|
|
|
|
# contact_inboxes that are not associated with any conversation
|
|
scope :stale_without_conversations, lambda { |time_period|
|
|
left_joins(:conversations)
|
|
.where('contact_inboxes.created_at < ?', time_period)
|
|
.where(conversations: { contact_id: nil })
|
|
}
|
|
|
|
def webhook_data
|
|
{
|
|
id: id,
|
|
contact: contact.try(:webhook_data),
|
|
inbox: inbox.webhook_data,
|
|
account: inbox.account.webhook_data,
|
|
current_conversation: current_conversation.try(:webhook_data),
|
|
source_id: source_id
|
|
}
|
|
end
|
|
|
|
def current_conversation
|
|
conversations.last
|
|
end
|
|
|
|
private
|
|
|
|
def validate_twilio_source_id
|
|
# https://www.twilio.com/docs/glossary/what-e164#regex-matching-for-e164
|
|
if inbox.channel.medium == 'sms' && !TWILIO_CHANNEL_SMS_REGEX.match?(source_id)
|
|
errors.add(:source_id, "invalid source id for twilio sms inbox. valid Regex #{TWILIO_CHANNEL_SMS_REGEX}")
|
|
elsif inbox.channel.medium == 'whatsapp' && !TWILIO_CHANNEL_WHATSAPP_REGEX.match?(source_id)
|
|
errors.add(:source_id, "invalid source id for twilio whatsapp inbox. valid Regex #{TWILIO_CHANNEL_WHATSAPP_REGEX}")
|
|
end
|
|
end
|
|
|
|
def validate_whatsapp_source_id
|
|
return if WHATSAPP_CHANNEL_REGEX.match?(source_id)
|
|
|
|
errors.add(:source_id, "invalid source id for whatsapp inbox. valid Regex #{WHATSAPP_CHANNEL_REGEX}")
|
|
end
|
|
|
|
def valid_source_id_format?
|
|
validate_twilio_source_id if inbox.channel_type == 'Channel::TwilioSms'
|
|
validate_whatsapp_source_id if inbox.channel_type == 'Channel::Whatsapp'
|
|
end
|
|
end
|