feat: add meta deletion callback endpoint

This commit is contained in:
Shivam Mishra
2025-03-03 17:36:10 +05:30
parent 6040e50265
commit 96a3999c8b
4 changed files with 96 additions and 0 deletions
@@ -0,0 +1,48 @@
class Webhooks::FacebookController < ActionController::API
class InvalidDigestError < StandardError; end
def process_deletion
signed_request = params['signed_request']
payload = parse_fb_signed_request(signed_request)
id_to_process = payload['user_id']
set_processing
Webhooks::MetaDeleteJob.perform_later(id_to_process)
status_url = "#{app_url_base}/meta/delete-status/#{id_to_process}"
render json: { status_url: status_url, code: id_to_process }, status: :ok
rescue InvalidDigestError
render json: { error: 'Invalid signature' }, status: :unprocessable_entity
end
private
def set_processing
# we use this key to check if the deletion is completed or not
# Once the key is gone, we know the deletion is completed
# And we can show as such
key = format(::Redis::Alfred::META_DELETE_PROCESSING, id: id_to_process)
::Redis::Alfred.set(key, true)
end
def app_url_base
ENV.fetch('FRONTEND_URL', nil)
end
def parse_fb_signed_request(signed_request)
encoded_signature, payload = signed_request.split('.', 2)
decoded_signature = Base64.urlsafe_decode64(encoded_signature)
decoded_payload = JSON.parse(Base64.urlsafe_decode64(payload))
expected_signature = OpenSSL::HMAC.digest('sha256', app_secret, payload)
raise InvalidDigestError if decoded_signature != expected_signature
decoded_payload
end
def app_secret
GlobalConfigService.load('FB_APP_SECRET', '')
end
end
+44
View File
@@ -0,0 +1,44 @@
class Webhooks::MetaDeleteJob < ApplicationJob
queue_as :low
attr_reader :id_to_process
def perform(id_to_process)
@id_to_process = id_to_process
delete_channel_if_present
delete_contact_if_present
unset_processing
end
private
def unset_processing
key = format(::Redis::Alfred::META_DELETE_PROCESSING, id: id_to_process)
::Redis::Alfred.del(key)
end
def delete_channel_if_present
channel = Channel::FacebookPage.find_by(page_id: id_to_process)
return unless channel
inbox = channel.inbox
inbox.destroy
end
def remove_contact_if_present
contact_inbox = ContactInbox.find_by(source_id: id_to_process)
return unless contact_inbox
contact = contact_inbox.contact
contact.update!(
name: 'Deleted User',
email: nil,
phone_number: nil,
identifier: nil,
additional_attributes: {},
custom_attributes: {}
)
end
end
+1
View File
@@ -448,6 +448,7 @@ Rails.application.routes.draw do
post 'webhooks/whatsapp/:phone_number', to: 'webhooks/whatsapp#process_payload'
get 'webhooks/instagram', to: 'webhooks/instagram#verify'
post 'webhooks/instagram', to: 'webhooks/instagram#events'
post 'webhooks/facebook/delete', to: 'webhooks/facebook#process_deletion'
namespace :twitter do
resource :callback, only: [:show]
+3
View File
@@ -41,4 +41,7 @@ module Redis::RedisKeys
IG_MESSAGE_MUTEX = 'IG_MESSAGE_CREATE_LOCK::%<sender_id>s::%<ig_account_id>s'.freeze
SLACK_MESSAGE_MUTEX = 'SLACK_MESSAGE_LOCK::%<conversation_id>s::%<reference_id>s'.freeze
EMAIL_MESSAGE_MUTEX = 'EMAIL_CHANNEL_LOCK::%<inbox_id>s'.freeze
## Meta deletion flags
META_DELETE_PROCESSING = 'META_DELETE_PROCESSING::%<id>s'.freeze
end