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.
37 38 39 |
# File 'lib/redmine/twofa/base.rb', line 37 def initialize(user) @user = user end |
Class Method Details
.inherited(child) ⇒ Object
23 24 25 26 27 |
# File 'lib/redmine/twofa/base.rb', line 23 def self.inherited(child) super # 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
29 30 31 |
# File 'lib/redmine/twofa/base.rb', line 29 def self.scheme_name(klass = self) klass.name.demodulize.underscore end |
Instance Method Details
#backup_codes ⇒ Object
152 153 154 |
# File 'lib/redmine/twofa/base.rb', line 152 def backup_codes Token.where(user_id: @user.id, action: 'twofa_backup_code') end |
#confirm_pairing!(code) ⇒ Object
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/redmine/twofa/base.rb', line 45 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
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/redmine/twofa/base.rb', line 56 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
85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/redmine/twofa/base.rb', line 85 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
70 71 72 73 74 75 76 77 |
# File 'lib/redmine/twofa/base.rb', line 70 def destroy_pairing!(code) if verify!(code) destroy_pairing_without_verify! return true else return false end end |
#destroy_pairing_without_verify! ⇒ Object
79 80 81 82 83 |
# File 'lib/redmine/twofa/base.rb', line 79 def destroy_pairing_without_verify! @user.update!(twofa_scheme: nil) backup_codes.delete_all deliver_twofa_unpaired end |
#init_backup_codes! ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/redmine/twofa/base.rb', line 132 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
41 42 43 |
# File 'lib/redmine/twofa/base.rb', line 41 def init_pairing! @user end |
#init_pairing_view_variables ⇒ Object
this will only be used on pairing initialization
157 158 159 |
# File 'lib/redmine/twofa/base.rb', line 157 def init_pairing_view_variables otp_confirm_view_variables end |
#otp_confirm_view_variables ⇒ Object
161 162 163 164 165 166 |
# File 'lib/redmine/twofa/base.rb', line 161 def otp_confirm_view_variables { scheme_name: scheme_name, resendable: false } end |
#scheme_name ⇒ Object
33 34 35 |
# File 'lib/redmine/twofa/base.rb', line 33 def scheme_name self.class.scheme_name end |
#send_code(controller: nil, action: nil) ⇒ Object
97 98 99 100 |
# File 'lib/redmine/twofa/base.rb', line 97 def send_code(controller: nil, action: nil) # return true only if the scheme sends a code to the user false end |
#verify!(code) ⇒ Object
102 103 104 |
# File 'lib/redmine/twofa/base.rb', line 102 def verify!(code) verify_otp!(code) || verify_backup_code!(code) end |
#verify_backup_code!(code) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/redmine/twofa/base.rb', line 110 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
106 107 108 |
# File 'lib/redmine/twofa/base.rb', line 106 def verify_otp!(code) raise 'not implemented' end |