From 1c2c8f26fc221b5e625aff2deb60543e96287e37 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 6 Mar 2025 20:04:11 +0530 Subject: [PATCH] feat: update controllers to create delete request --- app/controllers/concerns/facebook_concern.rb | 22 ++++---------- .../facebook/confirm_controller.rb | 6 ++-- app/controllers/facebook/delete_controller.rb | 7 ++--- app/models/delete_request.rb | 29 ++++++++++++++++++- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/app/controllers/concerns/facebook_concern.rb b/app/controllers/concerns/facebook_concern.rb index de6411af4..ffb7515d9 100644 --- a/app/controllers/concerns/facebook_concern.rb +++ b/app/controllers/concerns/facebook_concern.rb @@ -5,23 +5,11 @@ module FacebookConcern private - def mark_deleting(id) - key = delete_key(id) - ::Redis::Alfred.set(key, true) - end - - def unset_deleting(id) - key = delete_key(id) - ::Redis::Alfred.delete(key) - end - - def deleting?(id) - key = delete_key(id) - ::Redis::Alfred.get(key).present? - end - - def delete_key(id) - format(::Redis::Alfred::META_DELETE_PROCESSING, id: id) + def deletion_processed?(code) + request = DeleteRequest.find_by!(confirmation_code: code) + request.completed? + rescue ActiveRecord::RecordNotFound + false end def parse_fb_signed_request(signed_request) diff --git a/app/controllers/facebook/confirm_controller.rb b/app/controllers/facebook/confirm_controller.rb index 224c7aa08..9bb6efad1 100644 --- a/app/controllers/facebook/confirm_controller.rb +++ b/app/controllers/facebook/confirm_controller.rb @@ -2,10 +2,10 @@ class Facebook::ConfirmController < ApplicationController include FacebookConcern def show - if deleting?(params[:id]) - render plain: 'Processing', status: :ok - else + if deletion_processed?(params[:id]) render plain: 'Data Deleted Successfully', status: :ok + else + render plain: 'Processing. If there is an issue, please contact support', status: :ok end end end diff --git a/app/controllers/facebook/delete_controller.rb b/app/controllers/facebook/delete_controller.rb index 00e9b145d..d29831c7d 100644 --- a/app/controllers/facebook/delete_controller.rb +++ b/app/controllers/facebook/delete_controller.rb @@ -6,15 +6,14 @@ class Facebook::DeleteController < ApplicationController payload = parse_fb_signed_request(signed_request) id_to_process = payload['user_id'] - mark_deleting(id_to_process) - ::Channels::Facebook::RedactContactDataJob.perform_later(id_to_process) - status_url = "#{app_url_base}/facebook/confirm/#{id_to_process}" + delete_request = DeleteRequest.create(fb_id: id_to_process) + status_url = "#{app_url_base}/facebook/confirm/#{delete_request.confirmation_code}" # IMPORTANT: Do not change the response format below. # Facebook's Data Deletion Request system specifically expects responses in this format # with a 'url' for status confirmation and a 'confirmation_code' field. # See: https://developers.facebook.com/docs/development/create-an-app/app-dashboard/data-deletion-callback/#implementing - render json: { url: status_url, confirmation_code: id_to_process }, status: :ok + render json: { url: status_url, confirmation_code: delete_request.confirmation_code }, status: :ok rescue InvalidDigestError render json: { error: 'Invalid signature' }, status: :unprocessable_entity rescue StandardError => e diff --git a/app/models/delete_request.rb b/app/models/delete_request.rb index 017d74496..6cbd04faf 100644 --- a/app/models/delete_request.rb +++ b/app/models/delete_request.rb @@ -19,5 +19,32 @@ # index_delete_requests_on_confirmation_code (confirmation_code) UNIQUE # class DeleteRequest < ApplicationRecord - belongs_to :account + belongs_to :account, optional: true + enum :status, %w[pending processing completed].index_by(&:itself), default: :pending + + before_create :ensure_unqiue_confirmation_code + + private + + def ensure_unqiue_confirmation_code + max_retries = 3 + retry_count = 0 + + begin + self.confirmation_code = generate_confirmation_code + raise ActiveRecord::RecordNotUnique if self.class.exists?(confirmation_code: confirmation_code) + rescue ActiveRecord::RecordNotUnique + retry_count += 1 + if retry_count > max_retries + # it's really really unlikely that we'll ever ever hit this case, but just in case + self.confirmation_code = generate_confirmation_code + SecureRandom.alphanumeric(3) + else + retry + end + end + end + + def generate_confirmation_code + SecureRandom.uuid.delete('-') + end end