fix: anchor contact phone number validation (#15415)
Contact phone numbers with stray text in front of them, like
`abc+12312312321`, were saving successfully instead of being rejected as
invalid. Agents could end up with unusable numbers on a contact, and the
same values were persisted rather than discarded when captured through
the live chat widget.
## How to reproduce
1. Open a contact and edit its details.
2. Set the phone number to `abc+12312312321` via the API (`PATCH
/api/v1/accounts/:id/contacts/:id`).
3. Before this change the update succeeds. Now it fails validation.
## What changed
The E.164 format check was missing a leading `\A` anchor, so Rails
matched it anywhere in the string and accepted any prefix ahead of a
valid number. Both the validation and the `phone_number_format` fallback
used by `discard_invalid_attrs` are now anchored, so the widget path
discards these values instead of storing them.
Contacts already holding a prefixed number will now fail validation on
their next save. Worth a count on production first:
```sql
SELECT count(*) FROM contacts WHERE phone_number !~ '^\+[1-9][0-9]{1,14}$' AND phone_number <> '';
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
@@ -53,7 +53,7 @@ class Contact < ApplicationRecord
|
||||
validates :identifier, allow_blank: true, uniqueness: { scope: [:account_id] }
|
||||
validates :phone_number,
|
||||
allow_blank: true, uniqueness: { scope: [:account_id] },
|
||||
format: { with: /\+[1-9]\d{1,14}\z/, message: I18n.t('errors.contacts.phone_number.invalid') }
|
||||
format: { with: /\A\+[1-9]\d{1,14}\z/, message: I18n.t('errors.contacts.phone_number.invalid') }
|
||||
|
||||
belongs_to :account
|
||||
has_many :conversations, dependent: :destroy_async
|
||||
@@ -206,7 +206,7 @@ class Contact < ApplicationRecord
|
||||
def phone_number_format
|
||||
return if phone_number.blank?
|
||||
|
||||
self.phone_number = phone_number_was unless phone_number.match?(/\+[1-9]\d{1,14}\z/)
|
||||
self.phone_number = phone_number_was unless phone_number.match?(/\A\+[1-9]\d{1,14}\z/)
|
||||
end
|
||||
|
||||
def email_format
|
||||
|
||||
Reference in New Issue
Block a user