fix(voice): harden agent-label parsing and prevent started_at drift
- Conference::Manager.extract_user_id now requires the account id in the participant label to match call.account_id, so a spoofed label can't attach a user from another account to the call. - CallStatus::Manager keeps the earliest started_at across multiple in-progress webhooks (Twilio can emit answered + in-progress, plus retries) so duration_seconds isn't undercounted.
This commit is contained in:
@@ -17,7 +17,10 @@ class Voice::CallStatus::Manager
|
||||
ts = timestamp || now_seconds
|
||||
|
||||
if status == 'in_progress'
|
||||
attrs[:started_at] = Time.zone.at(ts)
|
||||
# Twilio can emit multiple in-progress updates (answered + in-progress, retries).
|
||||
# Keep the earliest timestamp so duration_seconds doesn't shift forward.
|
||||
started_at = Time.zone.at(ts)
|
||||
attrs[:started_at] = started_at if call.started_at.nil? || started_at < call.started_at
|
||||
elsif Call::TERMINAL_STATUSES.include?(status)
|
||||
call.ended_at = ts
|
||||
attrs[:meta] = call.meta
|
||||
|
||||
@@ -35,6 +35,17 @@ class Voice::Conference::Manager
|
||||
status_manager.process_status_update('in_progress', timestamp: now)
|
||||
end
|
||||
|
||||
# Parses agent user_id from participant_label. Only returns an id when the
|
||||
# label's embedded account id matches the call's account — protects against
|
||||
# a spoofed/cross-account label attaching a foreign user to the call.
|
||||
def extract_user_id
|
||||
match = participant_label.to_s.match(AGENT_LABEL_PATTERN)
|
||||
return unless match
|
||||
return unless match[2].to_i == call.account_id
|
||||
|
||||
match[1].to_i
|
||||
end
|
||||
|
||||
def handle_leave!
|
||||
case call.status
|
||||
when 'ringing'
|
||||
@@ -54,11 +65,6 @@ class Voice::Conference::Manager
|
||||
participant_label.to_s.start_with?('agent-')
|
||||
end
|
||||
|
||||
def extract_user_id
|
||||
match = participant_label.to_s.match(AGENT_LABEL_PATTERN)
|
||||
match && match[1].to_i
|
||||
end
|
||||
|
||||
def now
|
||||
Time.zone.now.to_i
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user