Class: Redmine::Twofa::Base
- Inherits:
-
Object
- Object
- Redmine::Twofa::Base
- Defined in:
- lib/redmine/twofa/base.rb
Direct Known Subclasses
Class Method Summary collapse
Instance Method Summary collapse
- #backup_codes ⇒ Object
- #confirm_pairing!(code) ⇒ Object
- #deliver_twofa_paired ⇒ Object
- #deliver_twofa_unpaired ⇒ Object
- #destroy_pairing!(code) ⇒ Object
- #destroy_pairing_without_verify! ⇒ Object
- #init_backup_codes! ⇒ Object
- #init_pairing! ⇒ Object
-
#init_pairing_view_variables ⇒ Object
this will only be used on pairing initialization.
-
#initialize(user) ⇒ Base
constructor
A new instance of Base.
- #otp_confirm_view_variables ⇒ Object
- #scheme_name ⇒ Object
- #send_code(controller: nil, action: nil) ⇒ Object
- #verify!(code) ⇒ Object
- #verify_backup_code!(code) ⇒ Object
- #verify_otp!(code) ⇒ Object
Constructor Details
#initialize(user) ⇒ Base
Returns a new instance of Base.
36 37 38 |
# File 'lib/redmine/twofa/base.rb', line 36 def initialize(user) @user = user end |
Class Method Details
.inherited(child) ⇒ Object
23 24 25 26 |
# File 'lib/redmine/twofa/base.rb', line 23 def self.inherited(child) # require-ing a Base subclass will register it as a 2FA scheme Redmine::Twofa.register_scheme(scheme_name(child), child) end |
.scheme_name(klass = self) ⇒ Object
28 29 30 |
# File 'lib/redmine/twofa/base.rb', line 28 def self.scheme_name(klass = self) klass.name.demodulize.underscore end |
Instance Method Details
#backup_codes ⇒ Object
151 152 153 |
# File 'lib/redmine/twofa/base.rb', line 151 def backup_codes Token.where(user_id: @user.id, action: 'twofa_backup_code') end |
#confirm_pairing!(code) ⇒ Object
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/redmine/twofa/base.rb', line 44 def confirm_pairing!(code) # make sure an otp and not a backup code is used if verify_otp!(code) @user.update!(twofa_scheme: scheme_name) deliver_twofa_paired return true else return false end end |
#deliver_twofa_paired ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/redmine/twofa/base.rb', line 55 def deliver_twofa_paired ::Mailer.deliver_security_notification( @user, User.current, { title: :label_my_account, message: 'twofa_mail_body_security_notification_paired', # (mis-)use field here as value wouldn't get localized field: "twofa__#{scheme_name}__name", url: {controller: 'my', action: 'account'} } ) end |
#deliver_twofa_unpaired ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/redmine/twofa/base.rb', line 84 def deliver_twofa_unpaired ::Mailer.deliver_security_notification( @user, User.current, { title: :label_my_account, message: 'twofa_mail_body_security_notification_unpaired', url: {controller: 'my', action: 'account'} } ) end |
#destroy_pairing!(code) ⇒ Object
69 70 71 72 73 74 75 76 |
# File 'lib/redmine/twofa/base.rb', line 69 def destroy_pairing!(code) if verify!(code) destroy_pairing_without_verify! return true else return false end end |
#destroy_pairing_without_verify! ⇒ Object
78 79 80 81 82 |
# File 'lib/redmine/twofa/base.rb', line 78 def destroy_pairing_without_verify! @user.update!(twofa_scheme: nil) backup_codes.delete_all deliver_twofa_unpaired end |
#init_backup_codes! ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/redmine/twofa/base.rb', line 131 def init_backup_codes! backup_codes.delete_all tokens = [] 10.times do token = Token.create(user_id: @user.id, action: 'twofa_backup_code') token.update_columns value: Redmine::Utils.random_hex(6) tokens << token end ::Mailer.deliver_security_notification( @user, User.current, { title: :label_my_account, message: 'twofa_mail_body_backup_codes_generated', url: {controller: 'my', action: 'account'} } ) tokens end |
#init_pairing! ⇒ Object
40 41 42 |
# File 'lib/redmine/twofa/base.rb', line 40 def init_pairing! @user end |
#init_pairing_view_variables ⇒ Object
this will only be used on pairing initialization
156 157 158 |
# File 'lib/redmine/twofa/base.rb', line 156 def init_pairing_view_variables otp_confirm_view_variables end |
#otp_confirm_view_variables ⇒ Object
160 161 162 163 164 165 |
# File 'lib/redmine/twofa/base.rb', line 160 def otp_confirm_view_variables { scheme_name: scheme_name, resendable: false } end |
#scheme_name ⇒ Object
32 33 34 |
# File 'lib/redmine/twofa/base.rb', line 32 def scheme_name self.class.scheme_name end |
#send_code(controller: nil, action: nil) ⇒ Object
96 97 98 99 |
# File 'lib/redmine/twofa/base.rb', line 96 def send_code(controller: nil, action: nil) # return true only if the scheme sends a code to the user false end |
#verify!(code) ⇒ Object
101 102 103 |
# File 'lib/redmine/twofa/base.rb', line 101 def verify!(code) verify_otp!(code) || verify_backup_code!(code) end |
#verify_backup_code!(code) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/redmine/twofa/base.rb', line 109 def verify_backup_code!(code) # backup codes are case-insensitive and white-space-insensitive code = code.to_s.remove(/[[:space:]]/).downcase user_from_code = Token.find_active_user('twofa_backup_code', code) # invalidate backup code after usage Token.where(user_id: @user.id).find_token('twofa_backup_code', code).try(:delete) # make sure the user using the backup code is the same it's been issued to return false unless @user.present? && @user == user_from_code ::Mailer.deliver_security_notification( @user, User.current, { originator: @user, title: :label_my_account, message: 'twofa_mail_body_backup_code_used', url: {controller: 'my', action: 'account'} } ) return true end |
#verify_otp!(code) ⇒ Object
105 106 107 |
# File 'lib/redmine/twofa/base.rb', line 105 def verify_otp!(code) raise 'not implemented' end |