Signal group and Formstack fixes

This commit is contained in:
Darren Clarke 2025-11-13 10:42:16 +01:00
parent 00d1fe5eef
commit 0e8c9be247
16 changed files with 692 additions and 142 deletions

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
class CdrSignalChannelsController < ApplicationController
prepend_before_action -> { authentication_check && authorize! }
def index
channels = Channel.where(area: 'Signal::Number', active: true).map do |channel|
{
id: channel.id,
phone_number: channel.options['phone_number'],
bot_token: channel.options['bot_token'],
bot_endpoint: channel.options['bot_endpoint']
}
end
render json: channels
end
end

View file

@ -122,6 +122,11 @@ class ChannelsCdrSignalController < ApplicationController
return update_group
end
# Handle group member joined events
if params[:event] == 'group_member_joined'
return handle_group_member_joined
end
channel_id = channel.id
# validate input
@ -397,6 +402,10 @@ class ChannelsCdrSignalController < ApplicationController
ticket.preferences[:cdr_signal][:original_recipient] = params[:original_recipient] if params[:original_recipient].present?
ticket.preferences[:cdr_signal][:group_created_at] = params[:timestamp] if params[:timestamp].present?
# Track whether user has joined the group (initially false)
# This will be updated to true when we receive a group join event from Signal
ticket.preferences[:cdr_signal][:group_joined] = params[:group_joined] if params.key?(:group_joined)
ticket.save!
Rails.logger.info "Signal group #{params[:group_id]} associated with ticket #{ticket.id}"
@ -407,4 +416,64 @@ class ChannelsCdrSignalController < ApplicationController
ticket_number: ticket.number
}, status: :ok
end
# Webhook endpoint for receiving group member joined notifications from bridge-worker
# This is called when a user accepts the Signal group invitation
# Expected payload:
# {
# "event": "group_member_joined",
# "group_id": "group.base64encodedid",
# "member_phone": "+1234567890",
# "timestamp": "ISO8601 timestamp"
# }
def handle_group_member_joined
# Validate required parameters
errors = {}
errors['event'] = 'required' unless params[:event].present?
errors['group_id'] = 'required' unless params[:group_id].present?
errors['member_phone'] = 'required' unless params[:member_phone].present?
if errors.present?
render json: {
errors: errors
}, status: :bad_request
return
end
# Find ticket(s) with this group_id in preferences
# Search all active tickets for matching group
state_ids = Ticket::State.where(name: %w[closed merged removed]).pluck(:id)
ticket = Ticket.where.not(state_id: state_ids).find do |t|
t.preferences.is_a?(Hash) &&
t.preferences['cdr_signal'].is_a?(Hash) &&
t.preferences['cdr_signal']['chat_id'] == params[:group_id]
end
unless ticket
Rails.logger.warn "Signal group member joined: Ticket not found for group_id #{params[:group_id]}"
render json: { error: 'Ticket not found for this group' }, status: :not_found
return
end
# Check if the member who joined matches the original recipient
original_recipient = ticket.preferences.dig('cdr_signal', 'original_recipient')
member_phone = params[:member_phone]
# Update group_joined flag
ticket.preferences[:cdr_signal][:group_joined] = true
ticket.preferences[:cdr_signal][:group_joined_at] = params[:timestamp] if params[:timestamp].present?
ticket.preferences[:cdr_signal][:group_joined_by] = member_phone
ticket.save!
Rails.logger.info "Signal group member #{member_phone} joined group #{params[:group_id]} for ticket #{ticket.id}"
render json: {
success: true,
ticket_id: ticket.id,
ticket_number: ticket.number,
group_joined: true
}, status: :ok
end
end

View file

@ -30,6 +30,25 @@ class CommunicateCdrSignalJob < ApplicationJob
log_error(article,
"Can't find ticket.preferences['cdr_signal']['chat_id'] for Ticket.find(#{article.ticket_id})")
end
# Check if this is a group chat and if the user has joined
chat_id = ticket.preferences['cdr_signal']['chat_id']
is_group_chat = chat_id&.start_with?('group.')
group_joined = ticket.preferences.dig('cdr_signal', 'group_joined')
# If this is a group chat and user hasn't joined yet, don't send the message
if is_group_chat && group_joined == false
Rails.logger.info "Ticket ##{ticket.number}: User hasn't joined Signal group yet, skipping message delivery"
# Mark article as pending delivery
article.preferences['delivery_status'] = 'pending'
article.preferences['delivery_status_message'] = 'Waiting for user to join Signal group'
article.preferences['delivery_status_date'] = Time.zone.now
article.save!
# Retry later when user might have joined
raise 'User has not joined Signal group yet'
end
channel = ::CdrSignal.bot_by_bot_token(ticket.preferences['cdr_signal']['bot_token'])
channel ||= ::Channel.lookup(id: ticket.preferences['channel_id'])
unless channel

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
module Controllers
class CdrSignalChannelsControllerPolicy < Controllers::ApplicationControllerPolicy
def index?
user.permissions?('admin.channel')
end
end
end

View file

@ -0,0 +1,5 @@
Zammad::Application.routes.draw do
api_path = Rails.configuration.api_path
match api_path + '/cdr_signal_channels', to: 'cdr_signal_channels#index', via: :get
end