Handling contact verifications

This commit is contained in:
tsoganov 2024-10-09 11:57:32 +03:00
parent 44e42dd0fb
commit 637cabf95f
19 changed files with 612 additions and 5 deletions

View file

@ -25,6 +25,7 @@ class ApplicationController < ActionController::Base
def comma_support_for(parent_key, key)
return if params[parent_key].blank?
return if params[parent_key][key].blank?
params[parent_key][key].sub!(/,/, '.')
end

View file

@ -0,0 +1,72 @@
# frozen_string_literal: true
module Eeid
module Webhooks
# Controller for handling eeID identification requests webhook
class IdentificationRequestsController < ActionController::Base
THROTTLED_ACTIONS = %i[create].freeze
include Shunter::Integration::Throttle
rescue_from Shunter::ThrottleError, with: :handle_throttle_error
# POST /eeid/webhooks/identification_requests
def create
return render_unauthorized unless ip_whitelisted?
return render_invalid_signature unless valid_hmac_signature?(request.headers['X-HMAC-Signature'])
verify_contact(permitted_params[:reference])
render json: { status: 'success' }, status: :ok
rescue StandardError => e
Rails.logger.error("Error handling webhook: #{e.message}")
render json: { error: 'Internal Server Error' }, status: :internal_server_error
end
private
def permitted_params
params.permit(:identification_request_id, :reference, :client_id)
end
def render_unauthorized
render json: { error: "IPAddress #{request.remote_ip} not authorized" }, status: :unauthorized
end
def render_invalid_signature
render json: { error: 'Invalid HMAC signature' }, status: :unauthorized
end
def valid_hmac_signature?(hmac_signature)
secret = ENV['ident_service_client_secret']
computed_signature = OpenSSL::HMAC.hexdigest('SHA256', secret, request.raw_post)
ActiveSupport::SecurityUtils.secure_compare(computed_signature, hmac_signature)
end
def verify_contact(ref)
contact = Contact.find_by_code(ref)
if contact&.ident_request_sent_at.present?
contact.update(verified_at: Time.zone.now)
Rails.logger.info("Contact verified: #{ref}")
else
Rails.logger.error("Valid contact not found for reference: #{ref}")
end
end
def ip_whitelisted?
allowed_ips = ENV['webhook_allowed_ips'].to_s.split(',').map(&:strip)
allowed_ips.include?(request.remote_ip) || Rails.env.development?
end
# Mock throttled_user using request IP
def throttled_user
# Create a mock user-like object with the request IP
OpenStruct.new(id: request.remote_ip, class: 'WebhookRequest')
end
def handle_throttle_error
render json: { error: Shunter.default_error_message }, status: :bad_request
end
end
end
end

View file

@ -2,10 +2,10 @@ require 'serializers/repp/contact'
module Repp
module V1
class ContactsController < BaseController # rubocop:disable Metrics/ClassLength
before_action :find_contact, only: %i[show update destroy]
before_action :find_contact, only: %i[show update destroy verify]
skip_around_action :log_request, only: :search
THROTTLED_ACTIONS = %i[index check search create show update destroy].freeze
THROTTLED_ACTIONS = %i[index check search create show update destroy verify].freeze
include Shunter::Integration::Throttle
api :get, '/repp/v1/contacts'
@ -116,6 +116,22 @@ module Repp
render_success
end
api :POST, '/repp/v1/contacts/verify/:contact_code'
desc 'Generate and send identification request to a contact'
def verify
authorize! :verify, Epp::Contact
action = Actions::ContactVerify.new(@contact)
unless action.call
handle_non_epp_errors(@contact)
return
end
data = { contact: { code: params[:id] } }
render_success(data: data)
end
private
def index_params
@ -217,7 +233,8 @@ module Repp
end
def contact_params
params.require(:contact).permit(:id, :name, :email, :phone, :legal_document,
params.require(:contact).permit(:id, :name, :email, :phone, :legal_document, :verified,
:verification_link,
legal_document: %i[body type],
ident: [%i[ident ident_type ident_country_code]],
addr: [%i[country_code city street zip state]])