rodauth 0.10.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +146 -0
- data/README.rdoc +644 -220
- data/Rakefile +99 -11
- data/doc/account_expiration.rdoc +55 -0
- data/doc/base.rdoc +104 -0
- data/doc/change_login.rdoc +29 -0
- data/doc/change_password.rdoc +26 -0
- data/doc/close_account.rdoc +31 -0
- data/doc/confirm_password.rdoc +22 -0
- data/doc/create_account.rdoc +34 -0
- data/doc/disallow_password_reuse.rdoc +37 -0
- data/doc/email_base.rdoc +19 -0
- data/doc/jwt.rdoc +35 -0
- data/doc/lockout.rdoc +83 -0
- data/doc/login.rdoc +27 -0
- data/doc/login_password_requirements_base.rdoc +50 -0
- data/doc/logout.rdoc +21 -0
- data/doc/otp.rdoc +100 -0
- data/doc/password_complexity.rdoc +50 -0
- data/doc/password_expiration.rdoc +52 -0
- data/doc/password_grace_period.rdoc +10 -0
- data/doc/recovery_codes.rdoc +60 -0
- data/doc/release_notes/1.0.0.txt +443 -0
- data/doc/remember.rdoc +82 -0
- data/doc/reset_password.rdoc +70 -0
- data/doc/session_expiration.rdoc +27 -0
- data/doc/single_session.rdoc +43 -0
- data/doc/sms_codes.rdoc +119 -0
- data/doc/two_factor_base.rdoc +27 -0
- data/doc/verify_account.rdoc +70 -0
- data/doc/verify_account_grace_period.rdoc +15 -0
- data/doc/verify_change_login.rdoc +9 -0
- data/lib/roda/plugins/rodauth.rb +3 -262
- data/lib/rodauth.rb +260 -0
- data/lib/rodauth/features/account_expiration.rb +108 -0
- data/lib/rodauth/features/base.rb +479 -0
- data/lib/rodauth/features/change_login.rb +77 -0
- data/lib/rodauth/features/change_password.rb +66 -0
- data/lib/rodauth/features/close_account.rb +82 -0
- data/lib/rodauth/features/confirm_password.rb +51 -0
- data/lib/rodauth/features/create_account.rb +128 -0
- data/lib/rodauth/features/disallow_password_reuse.rb +82 -0
- data/lib/rodauth/features/email_base.rb +63 -0
- data/lib/rodauth/features/jwt.rb +151 -0
- data/lib/rodauth/features/lockout.rb +262 -0
- data/lib/rodauth/features/login.rb +61 -0
- data/lib/rodauth/features/login_password_requirements_base.rb +123 -0
- data/lib/rodauth/features/logout.rb +37 -0
- data/lib/rodauth/features/otp.rb +338 -0
- data/lib/rodauth/features/password_complexity.rb +89 -0
- data/lib/rodauth/features/password_expiration.rb +111 -0
- data/lib/rodauth/features/password_grace_period.rb +46 -0
- data/lib/rodauth/features/recovery_codes.rb +240 -0
- data/lib/rodauth/features/remember.rb +200 -0
- data/lib/rodauth/features/reset_password.rb +207 -0
- data/lib/rodauth/features/session_expiration.rb +55 -0
- data/lib/rodauth/features/single_session.rb +87 -0
- data/lib/rodauth/features/sms_codes.rb +498 -0
- data/lib/rodauth/features/two_factor_base.rb +135 -0
- data/lib/rodauth/features/verify_account.rb +232 -0
- data/lib/rodauth/features/verify_account_grace_period.rb +76 -0
- data/lib/rodauth/features/verify_change_login.rb +20 -0
- data/lib/rodauth/migrations.rb +130 -0
- data/lib/rodauth/version.rb +9 -0
- data/spec/account_expiration_spec.rb +90 -0
- data/spec/all.rb +1 -0
- data/spec/change_login_spec.rb +149 -0
- data/spec/change_password_spec.rb +177 -0
- data/spec/close_account_spec.rb +162 -0
- data/spec/confirm_password_spec.rb +70 -0
- data/spec/create_account_spec.rb +127 -0
- data/spec/disallow_password_reuse_spec.rb +84 -0
- data/spec/lockout_spec.rb +228 -0
- data/spec/login_spec.rb +188 -0
- data/spec/migrate/001_tables.rb +103 -16
- data/spec/migrate/002_account_password_hash_column.rb +11 -0
- data/spec/migrate_password/001_tables.rb +60 -42
- data/spec/migrate_travis/001_tables.rb +116 -0
- data/spec/password_complexity_spec.rb +108 -0
- data/spec/password_expiration_spec.rb +243 -0
- data/spec/password_grace_period_spec.rb +93 -0
- data/spec/remember_spec.rb +424 -0
- data/spec/reset_password_spec.rb +185 -0
- data/spec/rodauth_spec.rb +57 -980
- data/spec/session_expiration_spec.rb +58 -0
- data/spec/single_session_spec.rb +107 -0
- data/spec/spec_helper.rb +202 -0
- data/spec/two_factor_spec.rb +1310 -0
- data/spec/verify_account_grace_period_spec.rb +135 -0
- data/spec/verify_account_spec.rb +142 -0
- data/spec/verify_change_login_spec.rb +46 -0
- data/spec/views/login.str +2 -2
- data/templates/add-recovery-codes.str +2 -0
- data/templates/button.str +5 -0
- data/templates/change-login.str +5 -18
- data/templates/change-password.str +6 -14
- data/templates/close-account.str +3 -6
- data/templates/confirm-password.str +4 -14
- data/templates/create-account.str +6 -30
- data/templates/login-confirm-field.str +6 -0
- data/templates/login-field.str +6 -0
- data/templates/login.str +5 -19
- data/templates/logout.str +2 -6
- data/templates/otp-auth-code-field.str +6 -0
- data/templates/otp-auth.str +8 -0
- data/templates/otp-disable.str +6 -0
- data/templates/otp-setup.str +21 -0
- data/templates/password-confirm-field.str +6 -0
- data/templates/password-field.str +6 -0
- data/templates/recovery-auth.str +12 -0
- data/templates/recovery-codes.str +6 -0
- data/templates/remember.str +8 -12
- data/templates/reset-password-request.str +2 -2
- data/templates/reset-password.str +4 -18
- data/templates/sms-auth.str +6 -0
- data/templates/sms-code-field.str +6 -0
- data/templates/sms-confirm.str +7 -0
- data/templates/sms-disable.str +7 -0
- data/templates/sms-request.str +5 -0
- data/templates/sms-setup.str +12 -0
- data/templates/unlock-account-request.str +3 -7
- data/templates/unlock-account.str +4 -7
- data/templates/verify-account-resend.str +2 -2
- data/templates/verify-account.str +2 -6
- metadata +191 -29
- data/lib/roda/plugins/rodauth/base.rb +0 -428
- data/lib/roda/plugins/rodauth/change_login.rb +0 -48
- data/lib/roda/plugins/rodauth/change_password.rb +0 -42
- data/lib/roda/plugins/rodauth/close_account.rb +0 -42
- data/lib/roda/plugins/rodauth/create_account.rb +0 -92
- data/lib/roda/plugins/rodauth/lockout.rb +0 -292
- data/lib/roda/plugins/rodauth/login.rb +0 -81
- data/lib/roda/plugins/rodauth/logout.rb +0 -36
- data/lib/roda/plugins/rodauth/remember.rb +0 -226
- data/lib/roda/plugins/rodauth/reset_password.rb +0 -205
- data/lib/roda/plugins/rodauth/verify_account.rb +0 -228
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
ChangeLogin = Feature.define(:change_login) do
|
5
|
+
depends :login_password_requirements_base
|
6
|
+
|
7
|
+
notice_flash 'Your login has been changed'
|
8
|
+
error_flash 'There was an error changing your login'
|
9
|
+
view 'change-login', 'Change Login'
|
10
|
+
after
|
11
|
+
before
|
12
|
+
additional_form_tags
|
13
|
+
button 'Change Login'
|
14
|
+
redirect
|
15
|
+
|
16
|
+
auth_value_methods :change_login_requires_password?
|
17
|
+
|
18
|
+
auth_methods :change_login
|
19
|
+
|
20
|
+
route do |r|
|
21
|
+
require_account
|
22
|
+
before_change_login_route
|
23
|
+
|
24
|
+
r.get do
|
25
|
+
change_login_view
|
26
|
+
end
|
27
|
+
|
28
|
+
r.post do
|
29
|
+
catch_error do
|
30
|
+
if change_login_requires_password? && !password_match?(param(password_param))
|
31
|
+
throw_error(password_param, invalid_password_message)
|
32
|
+
end
|
33
|
+
|
34
|
+
login = param(login_param)
|
35
|
+
unless login_meets_requirements?(login)
|
36
|
+
throw_error(login_param, login_does_not_meet_requirements_message)
|
37
|
+
end
|
38
|
+
|
39
|
+
if require_login_confirmation? && login != param(login_confirm_param)
|
40
|
+
throw_error(login_param, logins_do_not_match_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
transaction do
|
44
|
+
before_change_login
|
45
|
+
unless change_login(login)
|
46
|
+
throw_error(login_param, login_does_not_meet_requirements_message)
|
47
|
+
end
|
48
|
+
|
49
|
+
after_change_login
|
50
|
+
set_notice_flash change_login_notice_flash
|
51
|
+
redirect change_login_redirect
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
set_error_flash change_login_error_flash
|
56
|
+
change_login_view
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def change_login_requires_password?
|
61
|
+
modifications_require_password?
|
62
|
+
end
|
63
|
+
|
64
|
+
def change_login(login)
|
65
|
+
updated = nil
|
66
|
+
if account_ds.get(login_column).downcase == login.downcase
|
67
|
+
@login_requirement_message = 'same as current login'
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
raised = raises_uniqueness_violation?{updated = update_account({login_column=>login}, account_ds.exclude(login_column=>login)) == 1}
|
71
|
+
if raised
|
72
|
+
@login_requirement_message = 'already an account with this login'
|
73
|
+
end
|
74
|
+
updated && !raised
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
ChangePassword = Feature.define(:change_password) do
|
5
|
+
depends :login_password_requirements_base
|
6
|
+
|
7
|
+
notice_flash 'Your password has been changed'
|
8
|
+
error_flash 'There was an error changing your password'
|
9
|
+
view 'change-password', 'Change Password'
|
10
|
+
after
|
11
|
+
before
|
12
|
+
additional_form_tags
|
13
|
+
button 'Change Password'
|
14
|
+
redirect
|
15
|
+
|
16
|
+
auth_value_method :new_password_label, 'New Password'
|
17
|
+
auth_value_method :new_password_param, 'new-password'
|
18
|
+
|
19
|
+
auth_value_methods :change_password_requires_password?
|
20
|
+
|
21
|
+
route do |r|
|
22
|
+
require_account
|
23
|
+
before_change_password_route
|
24
|
+
|
25
|
+
r.get do
|
26
|
+
change_password_view
|
27
|
+
end
|
28
|
+
|
29
|
+
r.post do
|
30
|
+
catch_error do
|
31
|
+
if change_password_requires_password? && !password_match?(param(password_param))
|
32
|
+
throw_error(password_param, invalid_password_message)
|
33
|
+
end
|
34
|
+
|
35
|
+
password = param(new_password_param)
|
36
|
+
if require_password_confirmation? && password != param(password_confirm_param)
|
37
|
+
throw_error(new_password_param, passwords_do_not_match_message)
|
38
|
+
end
|
39
|
+
|
40
|
+
if password_match?(password)
|
41
|
+
throw_error(new_password_param, same_as_existing_password_message)
|
42
|
+
end
|
43
|
+
|
44
|
+
unless password_meets_requirements?(password)
|
45
|
+
throw_error(new_password_param, password_does_not_meet_requirements_message)
|
46
|
+
end
|
47
|
+
|
48
|
+
transaction do
|
49
|
+
before_change_password
|
50
|
+
set_password(password)
|
51
|
+
after_change_password
|
52
|
+
end
|
53
|
+
set_notice_flash change_password_notice_flash
|
54
|
+
redirect change_password_redirect
|
55
|
+
end
|
56
|
+
|
57
|
+
set_error_flash change_password_error_flash
|
58
|
+
change_password_view
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def change_password_requires_password?
|
63
|
+
modifications_require_password?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
CloseAccount = Feature.define(:close_account) do
|
5
|
+
notice_flash 'Your account has been closed'
|
6
|
+
error_flash 'There was an error closing your account'
|
7
|
+
view 'close-account', 'Close Account'
|
8
|
+
additional_form_tags
|
9
|
+
button 'Close Account'
|
10
|
+
after
|
11
|
+
before
|
12
|
+
redirect
|
13
|
+
|
14
|
+
auth_value_method :account_closed_status_value, 3
|
15
|
+
|
16
|
+
auth_value_methods(
|
17
|
+
:close_account_requires_password?,
|
18
|
+
:delete_account_on_close?
|
19
|
+
)
|
20
|
+
|
21
|
+
auth_methods(
|
22
|
+
:close_account,
|
23
|
+
:delete_account
|
24
|
+
)
|
25
|
+
|
26
|
+
route do |r|
|
27
|
+
require_account
|
28
|
+
before_close_account_route
|
29
|
+
|
30
|
+
r.get do
|
31
|
+
close_account_view
|
32
|
+
end
|
33
|
+
|
34
|
+
r.post do
|
35
|
+
if !close_account_requires_password? || password_match?(param(password_param))
|
36
|
+
transaction do
|
37
|
+
before_close_account
|
38
|
+
close_account
|
39
|
+
after_close_account
|
40
|
+
if delete_account_on_close?
|
41
|
+
delete_account
|
42
|
+
end
|
43
|
+
end
|
44
|
+
clear_session
|
45
|
+
|
46
|
+
set_notice_flash close_account_notice_flash
|
47
|
+
redirect close_account_redirect
|
48
|
+
else
|
49
|
+
set_field_error(password_param, invalid_password_message)
|
50
|
+
set_error_flash close_account_error_flash
|
51
|
+
close_account_view
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def close_account_requires_password?
|
57
|
+
modifications_require_password?
|
58
|
+
end
|
59
|
+
|
60
|
+
def close_account
|
61
|
+
unless skip_status_checks?
|
62
|
+
update_account(account_status_column=>account_closed_status_value)
|
63
|
+
end
|
64
|
+
|
65
|
+
unless account_password_hash_column
|
66
|
+
password_hash_ds.delete
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_account
|
71
|
+
account_ds.delete
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete_account_on_close?
|
75
|
+
skip_status_checks?
|
76
|
+
end
|
77
|
+
|
78
|
+
def skip_status_checks?
|
79
|
+
false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
ConfirmPassword = Feature.define(:confirm_password) do
|
5
|
+
notice_flash "Your password has been confirmed"
|
6
|
+
error_flash "There was an error confirming your password"
|
7
|
+
view 'confirm-password', 'Confirm Password'
|
8
|
+
additional_form_tags
|
9
|
+
button 'Confirm Password'
|
10
|
+
before
|
11
|
+
after
|
12
|
+
|
13
|
+
auth_value_methods :confirm_password_redirect
|
14
|
+
|
15
|
+
auth_methods :confirm_password
|
16
|
+
|
17
|
+
route do
|
18
|
+
require_account
|
19
|
+
before_confirm_password_route
|
20
|
+
|
21
|
+
request.get do
|
22
|
+
confirm_password_view
|
23
|
+
end
|
24
|
+
|
25
|
+
request.post do
|
26
|
+
if password_match?(param(password_param))
|
27
|
+
transaction do
|
28
|
+
before_confirm_password
|
29
|
+
confirm_password
|
30
|
+
after_confirm_password
|
31
|
+
end
|
32
|
+
set_notice_flash confirm_password_notice_flash
|
33
|
+
redirect confirm_password_redirect
|
34
|
+
else
|
35
|
+
set_field_error(password_param, invalid_password_message)
|
36
|
+
set_error_flash confirm_password_error_flash
|
37
|
+
confirm_password_view
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def confirm_password
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def confirm_password_redirect
|
47
|
+
session.delete(:confirm_password_redirect) || default_redirect
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
CreateAccount = Feature.define(:create_account) do
|
5
|
+
depends :login_password_requirements_base
|
6
|
+
|
7
|
+
depends :login
|
8
|
+
notice_flash 'Your account has been created'
|
9
|
+
error_flash "There was an error creating your account"
|
10
|
+
view 'create-account', 'Create Account'
|
11
|
+
after
|
12
|
+
before
|
13
|
+
button 'Create Account'
|
14
|
+
additional_form_tags
|
15
|
+
redirect
|
16
|
+
|
17
|
+
auth_value_method :create_account_autologin?, true
|
18
|
+
|
19
|
+
auth_value_methods :create_account_link
|
20
|
+
|
21
|
+
auth_methods(
|
22
|
+
:save_account,
|
23
|
+
:set_new_account_password
|
24
|
+
)
|
25
|
+
|
26
|
+
auth_private_methods(
|
27
|
+
:new_account
|
28
|
+
)
|
29
|
+
|
30
|
+
route do |r|
|
31
|
+
check_already_logged_in
|
32
|
+
before_create_account_route
|
33
|
+
|
34
|
+
r.get do
|
35
|
+
create_account_view
|
36
|
+
end
|
37
|
+
|
38
|
+
r.post do
|
39
|
+
login = param(login_param)
|
40
|
+
password = param(password_param)
|
41
|
+
new_account(login)
|
42
|
+
|
43
|
+
if account_password_hash_column
|
44
|
+
set_new_account_password(param(password_param))
|
45
|
+
end
|
46
|
+
|
47
|
+
catch_error do
|
48
|
+
if require_login_confirmation? && login != param(login_confirm_param)
|
49
|
+
throw_error(login_param, logins_do_not_match_message)
|
50
|
+
end
|
51
|
+
|
52
|
+
unless login_meets_requirements?(login)
|
53
|
+
throw_error(login_param, login_does_not_meet_requirements_message)
|
54
|
+
end
|
55
|
+
|
56
|
+
if require_password_confirmation? && password != param(password_confirm_param)
|
57
|
+
throw_error(password_param, passwords_do_not_match_message)
|
58
|
+
end
|
59
|
+
|
60
|
+
unless password_meets_requirements?(password)
|
61
|
+
throw_error(password_param, password_does_not_meet_requirements_message)
|
62
|
+
end
|
63
|
+
|
64
|
+
transaction do
|
65
|
+
before_create_account
|
66
|
+
unless save_account
|
67
|
+
throw_error(login_param, login_does_not_meet_requirements_message)
|
68
|
+
end
|
69
|
+
|
70
|
+
unless account_password_hash_column
|
71
|
+
set_password(password)
|
72
|
+
end
|
73
|
+
after_create_account
|
74
|
+
if create_account_autologin?
|
75
|
+
update_session
|
76
|
+
end
|
77
|
+
set_notice_flash create_account_notice_flash
|
78
|
+
redirect create_account_redirect
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
set_error_flash create_account_error_flash
|
83
|
+
create_account_view
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_account_link
|
88
|
+
"<p><a href=\"#{prefix}/#{create_account_route}\">Create a New Account</a></p>"
|
89
|
+
end
|
90
|
+
|
91
|
+
def login_form_footer
|
92
|
+
super + create_account_link
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_new_account_password(password)
|
96
|
+
account[account_password_hash_column] = password_hash(password)
|
97
|
+
end
|
98
|
+
|
99
|
+
def new_account(login)
|
100
|
+
@account = _new_account(login)
|
101
|
+
end
|
102
|
+
|
103
|
+
def save_account
|
104
|
+
id = nil
|
105
|
+
raised = raises_uniqueness_violation?{id = db[accounts_table].insert(account)}
|
106
|
+
|
107
|
+
if raised
|
108
|
+
@login_requirement_message = 'already an account with this login'
|
109
|
+
end
|
110
|
+
|
111
|
+
if id
|
112
|
+
account[account_id_column] = id
|
113
|
+
end
|
114
|
+
|
115
|
+
id && !raised
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def _new_account(login)
|
121
|
+
acc = {login_column=>login}
|
122
|
+
unless skip_status_checks?
|
123
|
+
acc[account_status_column] = account_initial_status_value
|
124
|
+
end
|
125
|
+
acc
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
DisallowPasswordReuse = Feature.define(:disallow_password_reuse) do
|
5
|
+
depends :login_password_requirements_base
|
6
|
+
|
7
|
+
auth_value_method :password_same_as_previous_password_message, "same as previous password"
|
8
|
+
auth_value_method :previous_password_account_id_column, :account_id
|
9
|
+
auth_value_method :previous_password_hash_column, :password_hash
|
10
|
+
auth_value_method :previous_password_hash_table, :account_previous_password_hashes
|
11
|
+
auth_value_method :previous_password_id_column, :id
|
12
|
+
auth_value_method :previous_passwords_to_check, 6
|
13
|
+
|
14
|
+
auth_methods(
|
15
|
+
:add_previous_password_hash,
|
16
|
+
:password_doesnt_match_previous_password?
|
17
|
+
)
|
18
|
+
|
19
|
+
def set_password(password)
|
20
|
+
hash = super
|
21
|
+
add_previous_password_hash(hash)
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_previous_password_hash(hash)
|
26
|
+
ds = previous_password_ds
|
27
|
+
keep_before = ds.reverse(previous_password_id_column).
|
28
|
+
limit(nil, previous_passwords_to_check).
|
29
|
+
get(previous_password_id_column)
|
30
|
+
|
31
|
+
ds.where(Sequel.expr(previous_password_id_column) <= keep_before).
|
32
|
+
delete
|
33
|
+
|
34
|
+
# This should never raise uniqueness violations, as it uses a serial primary key
|
35
|
+
ds.insert(previous_password_account_id_column=>account_id, previous_password_hash_column=>hash)
|
36
|
+
end
|
37
|
+
|
38
|
+
def password_meets_requirements?(password)
|
39
|
+
super &&
|
40
|
+
password_doesnt_match_previous_password?(password)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def password_doesnt_match_previous_password?(password)
|
46
|
+
id = account_id
|
47
|
+
match = if use_database_authentication_functions?
|
48
|
+
salts = previous_password_ds.
|
49
|
+
select_map([previous_password_id_column, Sequel.function(function_name(:rodauth_get_previous_salt), previous_password_id_column).as(:salt)])
|
50
|
+
return true if salts.empty?
|
51
|
+
|
52
|
+
salts.any? do |hash_id, salt|
|
53
|
+
db.get(Sequel.function(function_name(:rodauth_previous_password_hash_match), hash_id, BCrypt::Engine.hash_secret(password, salt)))
|
54
|
+
end
|
55
|
+
else
|
56
|
+
# :nocov:
|
57
|
+
previous_password_ds.select_map(previous_password_hash_column).any?{|hash| BCrypt::Password.new(hash) == password}
|
58
|
+
# :nocov:
|
59
|
+
end
|
60
|
+
|
61
|
+
return true unless match
|
62
|
+
@password_requirement_message = password_same_as_previous_password_message
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
def after_close_account
|
67
|
+
super if defined?(super)
|
68
|
+
previous_password_ds.delete
|
69
|
+
end
|
70
|
+
|
71
|
+
def after_create_account
|
72
|
+
if account_password_hash_column
|
73
|
+
add_previous_password_hash(password_hash(request[password_param]))
|
74
|
+
end
|
75
|
+
super if defined?(super)
|
76
|
+
end
|
77
|
+
|
78
|
+
def previous_password_ds
|
79
|
+
db[previous_password_hash_table].where(previous_password_account_id_column=>account_id)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|