app/services/census_authorization_handler.rb
# frozen_string_literal: true
# Checks the authorization against the census for Badalona.
require "digest/md5"
# This class performs a check against the official census database in order
# to verify the citizen's residence.
class CensusAuthorizationHandler < Decidim::AuthorizationHandler
include ActionView::Helpers::SanitizeHelper
include Virtus::Multiparams
attribute :date_of_birth, Date
attribute :postal_code, String
attribute :document_number, String
attribute :document_type, Symbol
validates :date_of_birth, presence: true
validates :postal_code, presence: true, format: { with: /\A[0-9]*\z/ }
validates :document_type, inclusion: { in: %i(DNI NIE PASS) }, presence: true
validates :document_number, format: { with: /\A[A-z0-9]*\z/ }, presence: true
validate :over_12
validate :check_response
# If you need to store any of the defined attributes in the authorization you
# can do it here.
#
# You must return a Hash that will be serialized to the authorization when
# it's created, and available though authorization.metadata
def metadata
super.merge(postal_code: postal_code)
end
def census_document_types
%i(DNI NIE PASS).map do |type|
[I18n.t(type, scope: "decidim.census_authorization_handler.document_types"), type]
end
end
def unique_id
Digest::MD5.hexdigest(
"#{document_number}-#{Rails.application.secrets.secret_key_base}"
)
end
private
def check_response
errors.add(:base, :invalid) unless response.present? && response["status"] == "OK"
end
def sanitized_date_of_birth
@sanitized_date_of_birth ||= date_of_birth&.strftime("%d/%m/%Y")
end
def response
return nil if date_of_birth.blank? ||
postal_code.blank? ||
document_type.blank? ||
document_number.blank?
return @response if defined?(@response)
connection = Faraday.new Rails.application.secrets.dig(:census, :url), ssl: { verify: false }
connection.basic_auth(Rails.application.secrets.dig(:census, :auth_user), Rails.application.secrets.dig(:census, :auth_pass))
response = connection.get do |request|
request.params = request_params
end
@response ||= JSON.parse(response.body)
end
def request_params
{
datnaix: sanitized_date_of_birth,
cdpost: postal_code,
tipdoc: document_type,
docident: document_number
}
end
def over_12
errors.add(:date_of_birth, I18n.t("census_authorization_handler.age_under_12")) unless age && age >= 12
end
def age
return nil if date_of_birth.blank?
now = Date.current
extra_year = (now.month > date_of_birth.month) || (
now.month == date_of_birth.month && now.day >= date_of_birth.day
)
now.year - date_of_birth.year - (extra_year ? 0 : 1)
end
end