70 lines
1.4 KiB
Ruby
70 lines
1.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'vault'
|
|
|
|
module Vault
|
|
# Vault::TOTP helper
|
|
module TOTP
|
|
Error = Class.new(StandardError)
|
|
|
|
class << self
|
|
|
|
def server_available?
|
|
read_data('sys/health').present?
|
|
rescue StandardError
|
|
false
|
|
end
|
|
|
|
def validate?(uid, code)
|
|
write_data(totp_code_key(uid), code: code).data[:valid]
|
|
end
|
|
|
|
def with_human_error
|
|
raise ArgumentError, 'Block is required' unless block_given?
|
|
yield
|
|
rescue Vault::VaultError => e
|
|
::Rails.logger.error { e }
|
|
if e.message.include?('connection refused')
|
|
raise Error, '2FA server is under maintenance'
|
|
end
|
|
|
|
if e.message.include?('code already used')
|
|
raise Error, 'This code was already used. Wait until the next time period'
|
|
end
|
|
|
|
raise e
|
|
end
|
|
|
|
private
|
|
|
|
def totp_key(uid)
|
|
"totp/keys/#{Vault.application}_#{uid}"
|
|
end
|
|
|
|
def totp_code_key(uid)
|
|
"totp/code/#{Vault.application}_#{uid}"
|
|
end
|
|
|
|
def read_data(key)
|
|
with_human_error do
|
|
vault.read(key)
|
|
end
|
|
end
|
|
|
|
def read_code(uid)
|
|
read_data(totp_code_key(uid)).data[:code]
|
|
end
|
|
|
|
def write_data(key, params)
|
|
with_human_error do
|
|
vault.write(key, params)
|
|
end
|
|
end
|
|
|
|
def vault
|
|
Vault.logical
|
|
end
|
|
end
|
|
end
|
|
end
|