77 lines
2.2 KiB
Ruby
77 lines
2.2 KiB
Ruby
class APIToken < ApplicationRecord
|
||
include ActiveRecord::SecureToken
|
||
|
||
belongs_to :administrateur, inverse_of: :api_tokens
|
||
has_many :procedures, through: :administrateur
|
||
|
||
before_save :check_allowed_procedure_ids_ownership
|
||
|
||
def context
|
||
context = { administrateur_id: administrateur_id, write_access: write_access? }
|
||
|
||
if full_access?
|
||
context.merge procedure_ids:
|
||
else
|
||
context.merge procedure_ids: procedure_ids & allowed_procedure_ids
|
||
end
|
||
end
|
||
|
||
def full_access?
|
||
allowed_procedure_ids.nil?
|
||
end
|
||
|
||
def procedures_to_allow
|
||
procedures.select(:id, :libelle, :path).where.not(id: allowed_procedure_ids || []).order(:libelle)
|
||
end
|
||
|
||
def allowed_procedures
|
||
if allowed_procedure_ids.present?
|
||
procedures.select(:id, :libelle, :path).where(id: allowed_procedure_ids).order(:libelle)
|
||
else
|
||
[]
|
||
end
|
||
end
|
||
|
||
def disallow_procedure(procedure_id)
|
||
allowed_procedure_ids = allowed_procedures.map(&:id) - [procedure_id]
|
||
if allowed_procedure_ids.empty?
|
||
allowed_procedure_ids = nil
|
||
end
|
||
update!(allowed_procedure_ids:)
|
||
end
|
||
|
||
# Prefix is made of the first 6 characters of the uuid base64 encoded
|
||
# it does not leak plain token
|
||
def prefix
|
||
Base64.urlsafe_encode64(id).slice(0, 5)
|
||
end
|
||
|
||
class << self
|
||
def generate(administrateur)
|
||
plain_token = generate_unique_secure_token
|
||
encrypted_token = BCrypt::Password.create(plain_token)
|
||
api_token = create!(administrateur:, encrypted_token:, name: Date.today.strftime('Jeton d’API généré le %d/%m/%Y'))
|
||
packed_token = Base64.urlsafe_encode64([api_token.id, plain_token].join(';'))
|
||
[api_token, packed_token]
|
||
end
|
||
|
||
def find_and_verify(base64_packed_token)
|
||
id, plain_token = Base64.urlsafe_decode64(base64_packed_token).split(';')
|
||
find_by(id:, version: 3)&.then(&ensure_valid_token(plain_token))
|
||
end
|
||
|
||
private
|
||
|
||
def ensure_valid_token(plain_token)
|
||
-> (api_token) { api_token if BCrypt::Password.new(api_token.encrypted_token) == plain_token }
|
||
end
|
||
end
|
||
|
||
private
|
||
|
||
def check_allowed_procedure_ids_ownership
|
||
if allowed_procedure_ids.present?
|
||
self.allowed_procedure_ids = allowed_procedures.map(&:id)
|
||
end
|
||
end
|
||
end
|