Files
Dalan/app/api/v2/identity/utils.rb
2026-08-13 19:56:46 +03:30

162 lines
5.3 KiB
Ruby

# frozen_string_literal: true
module API::V2
module Identity
module Utils
def session
request.session
end
def codec
@_codec ||= Barong::JWT.new(key: Barong::App.config.keystore.private_key)
end
def open_session(user)
csrf_token = SecureRandom.hex(10)
session.merge!(
"uid": user.uid,
"user_ip": remote_ip,
"user_agent": request.env['HTTP_USER_AGENT'],
"expire_time": Time.now.to_i + Barong::App.config.session_expire_time,
"csrf_token": csrf_token
)
csrf_token
end
def verify_captcha!(response:, endpoint:, error_statuses: [400, 422])
# by default we protect user_create session_create password_reset email_confirmation endpoints
return unless BarongConfig.list['captcha_protected_endpoints']&.include?(endpoint)
case Barong::App.config.captcha
when 'recaptcha'
recaptcha(response: response)
when 'geetest'
geetest(response: response)
end
end
def recaptcha(response:, error_statuses: [400, 422])
error!({ errors: ['identity.captcha.required'] }, error_statuses.first) if response.blank?
captcha_error_message = 'identity.captcha.verification_failed'
if CaptchaService::RecaptchaVerifier.new(request: request).response_valid?(skip_remote_ip: true, response: response)
return
end
error!({ errors: [captcha_error_message] }, error_statuses.last)
rescue StandardError
error!({ errors: [captcha_error_message] }, error_statuses.last)
end
def geetest(response:, error_statuses: [400, 422])
error!({ errors: ['identity.captcha.required'] }, error_statuses.first) if response.blank?
geetest_error_message = 'identity.captcha.verification_failed'
validate_geetest_response(response: response)
return if CaptchaService::GeetestVerifier.new.validate(response)
error!({ errors: [geetest_error_message] }, error_statuses.last)
rescue StandardError
error!({ errors: [geetest_error_message] }, error_statuses.last)
end
def validate_geetest_response(response:)
unless (response['geetest_challenge'].is_a? String) &&
(response['geetest_validate'].is_a? String) &&
(response['geetest_seccode'].is_a? String)
error!({ errors: ['identity.captcha.mandatory_fields'] }, 400)
end
end
def login_error!(options = {})
options[:data] = { reason: options[:reason] }.to_json
options[:topic] = 'session'
activity_record(options.except(:reason, :error_code, :error_text))
error!({ errors: ['identity.session.' + options[:error_text]] }, options[:error_code])
end
def activity_record(options = {})
params = {
category: 'user',
user_id: options[:user],
user_ip: remote_ip,
user_agent: request.env['HTTP_USER_AGENT'],
topic: options[:topic],
action: options[:action],
result: options[:result],
data: options[:data]
}
Activity.create(params)
end
def token_uniq?(jti)
error!({ errors: ['identity.user.utilized_token'] }, 422) if Rails.cache.read(jti) == 'utilized'
Rails.cache.write(jti, 'utilized', expires_in: Barong::App.config.jwt_expire_time.seconds)
end
def publish_confirmation(user, domain)
token = codec.encode(sub: 'confirmation', email: user.email, uid: user.uid)
EventAPI.notify(
'system.user.email.confirmation.token',
record: {
user: user.as_json_for_event_api,
domain: domain,
token: token
}
)
end
def publish_confirmation_code(user, domain, action)
totp = TOTPServiceAction.new(action)
totp.create(user.uid, user.email)
record = {
user: user.as_json_for_event_api,
domain: domain,
code: totp.read_code(user.uid)
}
case action
when 'sign-up'
record[:token] = codec.encode(sub: 'confirmation', email: user.email, uid: user.uid)
when 'reset-password'
reset_token = SecureRandom.hex(10)
Rails.cache.write(
"reset_password_#{user.email}",
reset_token,
expires_in: Barong::App.config.jwt_expire_time.seconds
)
record[:token] = codec.encode(
sub: 'reset',
email: user.email,
uid: user.uid,
reset_token: reset_token
)
end
EventAPI.notify(action, record: record)
end
def publish_session_create(user)
EventAPI.notify('system.session.create',
record: {
user: user.as_json_for_event_api,
user_ip: remote_ip,
user_agent: request.env['HTTP_USER_AGENT']
})
end
def publish_session_failed(user)
EventAPI.notify('system.session.failed',
record: {
user: user.as_json_for_event_api,
user_ip: remote_ip,
user_agent: request.env['HTTP_USER_AGENT']
})
end
end
end
end