Initial commit
This commit is contained in:
161
app/api/v2/identity/utils.rb
Normal file
161
app/api/v2/identity/utils.rb
Normal file
@@ -0,0 +1,161 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user