diff --git a/app/controllers/webhooks/shopify_controller.rb b/app/controllers/webhooks/shopify_controller.rb new file mode 100644 index 000000000..efc6a5122 --- /dev/null +++ b/app/controllers/webhooks/shopify_controller.rb @@ -0,0 +1,35 @@ +class Webhooks::ShopifyController < ActionController::API + before_action :verify_hmac! + + def events + case request.headers['X-Shopify-Topic'] + when 'shop/redact' + handle_shop_redact + end + + head :ok + end + + private + + def verify_hmac! + secret = GlobalConfigService.load('SHOPIFY_CLIENT_SECRET', nil) + return head :unauthorized if secret.blank? + + data = request.body.read + request.body.rewind + + hmac_header = request.headers['X-Shopify-Hmac-SHA256'] + return head :unauthorized if hmac_header.blank? + + computed = Base64.strict_encode64(OpenSSL::HMAC.digest('SHA256', secret, data)) + return head :unauthorized unless ActiveSupport::SecurityUtils.secure_compare(computed, hmac_header) + end + + def handle_shop_redact + shop_domain = params[:shop_domain] + return if shop_domain.blank? + + Integrations::Hook.where(app_id: 'shopify', reference_id: shop_domain).destroy_all + end +end diff --git a/config/routes.rb b/config/routes.rb index cab069201..38c93b91e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -564,6 +564,7 @@ Rails.application.routes.draw do get 'webhooks/instagram', to: 'webhooks/instagram#verify' post 'webhooks/instagram', to: 'webhooks/instagram#events' post 'webhooks/tiktok', to: 'webhooks/tiktok#events' + post 'webhooks/shopify', to: 'webhooks/shopify#events' namespace :twitter do resource :callback, only: [:show]