rodauth 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/README.rdoc +20 -11
- data/doc/base.rdoc +2 -2
- data/doc/email_auth.rdoc +53 -0
- data/doc/email_base.rdoc +4 -0
- data/doc/internals.rdoc +3 -3
- data/doc/lockout.rdoc +28 -48
- data/doc/login.rdoc +4 -4
- data/doc/otp.rdoc +1 -3
- data/doc/release_notes/1.19.0.txt +116 -0
- data/doc/reset_password.rdoc +29 -49
- data/doc/verify_account.rdoc +30 -50
- data/doc/verify_login_change.rdoc +4 -0
- data/lib/rodauth/features/base.rb +0 -1
- data/lib/rodauth/features/change_login.rb +4 -0
- data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
- data/lib/rodauth/features/email_auth.rb +253 -0
- data/lib/rodauth/features/email_base.rb +2 -0
- data/lib/rodauth/features/lockout.rb +35 -6
- data/lib/rodauth/features/login.rb +46 -9
- data/lib/rodauth/features/otp.rb +8 -4
- data/lib/rodauth/features/recovery_codes.rb +0 -2
- data/lib/rodauth/features/remember.rb +1 -1
- data/lib/rodauth/features/reset_password.rb +32 -4
- data/lib/rodauth/features/sms_codes.rb +2 -8
- data/lib/rodauth/features/two_factor_base.rb +22 -15
- data/lib/rodauth/features/verify_account.rb +27 -1
- data/lib/rodauth/features/verify_login_change.rb +30 -7
- data/lib/rodauth/migrations.rb +2 -8
- data/lib/rodauth/version.rb +1 -1
- data/spec/email_auth_spec.rb +285 -0
- data/spec/lockout_spec.rb +24 -2
- data/spec/login_spec.rb +47 -1
- data/spec/migrate/001_tables.rb +13 -0
- data/spec/migrate_travis/001_tables.rb +10 -0
- data/spec/reset_password_spec.rb +20 -2
- data/spec/two_factor_spec.rb +46 -0
- data/spec/verify_account_grace_period_spec.rb +1 -1
- data/spec/verify_account_spec.rb +33 -3
- data/spec/verify_login_change_spec.rb +54 -1
- data/templates/email-auth-email.str +5 -0
- data/templates/email-auth-request-form.str +7 -0
- data/templates/email-auth.str +5 -0
- data/templates/login-display.str +4 -0
- data/templates/login.str +2 -2
- data/templates/otp-setup.str +13 -11
- metadata +12 -2
data/spec/lockout_spec.rb
CHANGED
@@ -2,10 +2,12 @@ require File.expand_path("spec_helper", File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
describe 'Rodauth lockout feature' do
|
4
4
|
it "should support account lockouts without autologin on unlock" do
|
5
|
+
lockouts = []
|
5
6
|
rodauth do
|
6
7
|
enable :lockout
|
7
8
|
max_invalid_logins 2
|
8
9
|
unlock_account_autologin? false
|
10
|
+
after_account_lockout{lockouts << true}
|
9
11
|
end
|
10
12
|
roda do |r|
|
11
13
|
r.rodauth
|
@@ -28,6 +30,7 @@ describe 'Rodauth lockout feature' do
|
|
28
30
|
click_button 'Login'
|
29
31
|
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
30
32
|
end
|
33
|
+
lockouts.must_equal [true]
|
31
34
|
|
32
35
|
fill_in 'Password', :with=>'012345678910'
|
33
36
|
click_button 'Login'
|
@@ -35,8 +38,15 @@ describe 'Rodauth lockout feature' do
|
|
35
38
|
page.body.must_include("This account is currently locked out")
|
36
39
|
click_button 'Request Account Unlock'
|
37
40
|
page.find('#notice_flash').text.must_equal 'An email has been sent to you with a link to unlock your account'
|
38
|
-
|
39
41
|
link = email_link(/(\/unlock-account\?key=.+)$/)
|
42
|
+
|
43
|
+
visit '/login'
|
44
|
+
fill_in 'Login', :with=>'foo@example.com'
|
45
|
+
fill_in 'Password', :with=>'012345678910'
|
46
|
+
click_button 'Login'
|
47
|
+
click_button 'Request Account Unlock'
|
48
|
+
email_link(/(\/unlock-account\?key=.+)$/).must_equal link
|
49
|
+
|
40
50
|
visit link[0...-1]
|
41
51
|
page.find('#error_flash').text.must_equal 'No matching unlock account key'
|
42
52
|
|
@@ -54,6 +64,7 @@ describe 'Rodauth lockout feature' do
|
|
54
64
|
rodauth do
|
55
65
|
enable :lockout
|
56
66
|
unlock_account_requires_password? true
|
67
|
+
account_lockouts_email_last_sent_column :email_last_sent
|
57
68
|
end
|
58
69
|
roda do |r|
|
59
70
|
r.rodauth
|
@@ -74,8 +85,16 @@ describe 'Rodauth lockout feature' do
|
|
74
85
|
page.body.must_include("This account is currently locked out")
|
75
86
|
click_button 'Request Account Unlock'
|
76
87
|
page.find('#notice_flash').text.must_equal 'An email has been sent to you with a link to unlock your account'
|
77
|
-
|
78
88
|
link = email_link(/(\/unlock-account\?key=.+)$/)
|
89
|
+
|
90
|
+
visit '/login'
|
91
|
+
fill_in 'Login', :with=>'foo@example.com'
|
92
|
+
fill_in 'Password', :with=>'012345678910'
|
93
|
+
click_button 'Login'
|
94
|
+
click_button 'Request Account Unlock'
|
95
|
+
page.find('#error_flash').text.must_equal "An email has recently been sent to you with a link to unlock the account"
|
96
|
+
Mail::TestMailer.deliveries.must_equal []
|
97
|
+
|
79
98
|
visit link
|
80
99
|
click_button 'Unlock Account'
|
81
100
|
|
@@ -147,9 +166,11 @@ describe 'Rodauth lockout feature' do
|
|
147
166
|
end
|
148
167
|
|
149
168
|
it "should handle uniqueness errors raised when inserting unlock account token" do
|
169
|
+
lockouts = []
|
150
170
|
rodauth do
|
151
171
|
enable :lockout
|
152
172
|
max_invalid_logins 2
|
173
|
+
after_account_lockout{lockouts << true}
|
153
174
|
end
|
154
175
|
roda do |r|
|
155
176
|
def rodauth.raised_uniqueness_violation(*) super; true; end
|
@@ -165,6 +186,7 @@ describe 'Rodauth lockout feature' do
|
|
165
186
|
|
166
187
|
fill_in 'Password', :with=>'012345678910'
|
167
188
|
click_button 'Login'
|
189
|
+
lockouts.must_equal [true]
|
168
190
|
page.find('#error_flash').text.must_equal "This account is currently locked out and cannot be logged in to."
|
169
191
|
page.body.must_include("This account is currently locked out")
|
170
192
|
click_button 'Request Account Unlock'
|
data/spec/login_spec.rb
CHANGED
@@ -34,6 +34,52 @@ describe 'Rodauth login feature' do
|
|
34
34
|
page.current_path.must_equal '/login'
|
35
35
|
end
|
36
36
|
|
37
|
+
it "should handle multi phase login (email first, then password)" do
|
38
|
+
rodauth do
|
39
|
+
enable :login, :logout
|
40
|
+
use_multi_phase_login? true
|
41
|
+
end
|
42
|
+
roda do |r|
|
43
|
+
r.rodauth
|
44
|
+
next unless rodauth.logged_in?
|
45
|
+
r.root{view :content=>"Logged In"}
|
46
|
+
end
|
47
|
+
|
48
|
+
visit '/login'
|
49
|
+
page.title.must_equal 'Login'
|
50
|
+
|
51
|
+
page.all('input[type=password]').must_be :empty?
|
52
|
+
fill_in 'Login', :with=>'foo2@example.com'
|
53
|
+
click_button 'Login'
|
54
|
+
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
55
|
+
page.html.must_include("no matching login")
|
56
|
+
|
57
|
+
page.all('input[type=password]').must_be :empty?
|
58
|
+
fill_in 'Login', :with=>'foo@example.com'
|
59
|
+
click_button 'Login'
|
60
|
+
page.find('#notice_flash').text.must_equal 'Login recognized, please enter your password'
|
61
|
+
|
62
|
+
page.all('input[type=text]').must_be :empty?
|
63
|
+
fill_in 'Password', :with=>'012345678'
|
64
|
+
click_button 'Login'
|
65
|
+
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
66
|
+
page.html.must_include("invalid password")
|
67
|
+
|
68
|
+
page.all('input[type=text]').must_be :empty?
|
69
|
+
fill_in 'Password', :with=>'0123456789'
|
70
|
+
click_button 'Login'
|
71
|
+
page.current_path.must_equal '/'
|
72
|
+
page.find('#notice_flash').text.must_equal 'You have been logged in'
|
73
|
+
page.html.must_include("Logged In")
|
74
|
+
|
75
|
+
visit '/logout'
|
76
|
+
page.title.must_equal 'Logout'
|
77
|
+
|
78
|
+
click_button 'Logout'
|
79
|
+
page.find('#notice_flash').text.must_equal 'You have been logged out'
|
80
|
+
page.current_path.must_equal '/login'
|
81
|
+
end
|
82
|
+
|
37
83
|
it "should not allow login to unverified account" do
|
38
84
|
rodauth do
|
39
85
|
enable :login
|
@@ -115,7 +161,7 @@ describe 'Rodauth login feature' do
|
|
115
161
|
it "should handle a prefix and some other login options" do
|
116
162
|
rodauth do
|
117
163
|
enable :login, :logout
|
118
|
-
prefix 'auth'
|
164
|
+
prefix '/auth'
|
119
165
|
session_key 'login_email'
|
120
166
|
account_from_session{DB[:accounts].first(:email=>session_value)}
|
121
167
|
account_session_value{account[:email]}
|
data/spec/migrate/001_tables.rb
CHANGED
@@ -36,6 +36,7 @@ Sequel.migration do
|
|
36
36
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
37
37
|
String :key, :null=>false
|
38
38
|
DateTime :deadline, deadline_opts[1]
|
39
|
+
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
39
40
|
end
|
40
41
|
|
41
42
|
# Used by the account verification feature
|
@@ -43,6 +44,7 @@ Sequel.migration do
|
|
43
44
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
44
45
|
String :key, :null=>false
|
45
46
|
DateTime :requested_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
47
|
+
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
46
48
|
end
|
47
49
|
|
48
50
|
# Used by the verify login change feature
|
@@ -69,6 +71,15 @@ Sequel.migration do
|
|
69
71
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
70
72
|
String :key, :null=>false
|
71
73
|
DateTime :deadline, deadline_opts[1]
|
74
|
+
DateTime :email_last_sent
|
75
|
+
end
|
76
|
+
|
77
|
+
# Used by the email auth feature
|
78
|
+
create_table(:account_email_auth_keys) do
|
79
|
+
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
80
|
+
String :key, :null=>false
|
81
|
+
DateTime :deadline, deadline_opts[1]
|
82
|
+
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
72
83
|
end
|
73
84
|
|
74
85
|
# Used by the password expiration feature
|
@@ -132,6 +143,7 @@ Sequel.migration do
|
|
132
143
|
run "GRANT ALL ON account_login_change_keys TO #{user}"
|
133
144
|
run "GRANT ALL ON account_remember_keys TO #{user}"
|
134
145
|
run "GRANT ALL ON account_login_failures TO #{user}"
|
146
|
+
run "GRANT ALL ON account_email_auth_keys TO #{user}"
|
135
147
|
run "GRANT ALL ON account_lockouts TO #{user}"
|
136
148
|
run "GRANT ALL ON account_password_change_times TO #{user}"
|
137
149
|
run "GRANT ALL ON account_activity_times TO #{user}"
|
@@ -149,6 +161,7 @@ Sequel.migration do
|
|
149
161
|
:account_session_keys,
|
150
162
|
:account_activity_times,
|
151
163
|
:account_password_change_times,
|
164
|
+
:account_email_auth_keys,
|
152
165
|
:account_lockouts,
|
153
166
|
:account_login_failures,
|
154
167
|
:account_remember_keys,
|
@@ -44,12 +44,14 @@ Sequel.migration do
|
|
44
44
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
45
45
|
String :key, :null=>false
|
46
46
|
DateTime :deadline, deadline_opts[1]
|
47
|
+
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
47
48
|
end
|
48
49
|
|
49
50
|
create_table(:account_verification_keys) do
|
50
51
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
51
52
|
String :key, :null=>false
|
52
53
|
DateTime :requested_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
54
|
+
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
53
55
|
end
|
54
56
|
|
55
57
|
create_table(:account_login_change_keys) do
|
@@ -65,6 +67,13 @@ Sequel.migration do
|
|
65
67
|
DateTime :deadline, deadline_opts[14]
|
66
68
|
end
|
67
69
|
|
70
|
+
create_table(:account_email_auth_keys) do
|
71
|
+
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
72
|
+
String :key, :null=>false
|
73
|
+
DateTime :deadline, deadline_opts[1]
|
74
|
+
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
75
|
+
end
|
76
|
+
|
68
77
|
create_table(:account_login_failures) do
|
69
78
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
70
79
|
Integer :number, :null=>false, :default=>1
|
@@ -73,6 +82,7 @@ Sequel.migration do
|
|
73
82
|
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
74
83
|
String :key, :null=>false
|
75
84
|
DateTime :deadline, deadline_opts[1]
|
85
|
+
DateTime :email_last_sent
|
76
86
|
end
|
77
87
|
|
78
88
|
create_table(:account_password_change_times) do
|
data/spec/reset_password_spec.rb
CHANGED
@@ -2,8 +2,10 @@ require File.expand_path("spec_helper", File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
describe 'Rodauth reset_password feature' do
|
4
4
|
it "should support resetting passwords for accounts" do
|
5
|
+
last_sent_column = nil
|
5
6
|
rodauth do
|
6
7
|
enable :login, :reset_password
|
8
|
+
reset_password_email_last_sent_column{last_sent_column}
|
7
9
|
end
|
8
10
|
roda do |r|
|
9
11
|
r.rodauth
|
@@ -29,8 +31,24 @@ describe 'Rodauth reset_password feature' do
|
|
29
31
|
click_button 'Request Password Reset'
|
30
32
|
email_link(/(\/reset-password\?key=.+)$/).must_equal link
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
login(:pass=>'01234567')
|
35
|
+
click_button 'Request Password Reset'
|
36
|
+
email_link(/(\/reset-password\?key=.+)$/).must_equal link
|
37
|
+
|
38
|
+
last_sent_column = :email_last_sent
|
39
|
+
login(:pass=>'01234567')
|
40
|
+
click_button 'Request Password Reset'
|
41
|
+
page.find('#error_flash').text.must_equal "An email has recently been sent to you with a link to reset your password"
|
42
|
+
Mail::TestMailer.deliveries.must_equal []
|
43
|
+
|
44
|
+
DB[:account_password_reset_keys].update(:email_last_sent => Time.now - 250).must_equal 1
|
45
|
+
login(:pass=>'01234567')
|
46
|
+
click_button 'Request Password Reset'
|
47
|
+
page.find('#error_flash').text.must_equal "An email has recently been sent to you with a link to reset your password"
|
48
|
+
Mail::TestMailer.deliveries.must_equal []
|
49
|
+
|
50
|
+
DB[:account_password_reset_keys].update(:email_last_sent => Time.now - 350).must_equal 1
|
51
|
+
login(:pass=>'01234567')
|
34
52
|
click_button 'Request Password Reset'
|
35
53
|
email_link(/(\/reset-password\?key=.+)$/).must_equal link
|
36
54
|
|
data/spec/two_factor_spec.rb
CHANGED
@@ -1316,4 +1316,50 @@ describe 'Rodauth OTP feature' do
|
|
1316
1316
|
DB[t].count.must_equal 0
|
1317
1317
|
end
|
1318
1318
|
end
|
1319
|
+
|
1320
|
+
it "should allow two factor authentication setup, login, recovery, removal" do
|
1321
|
+
warning = nil
|
1322
|
+
before_called = false
|
1323
|
+
rodauth do
|
1324
|
+
enable :login, :otp, :logout
|
1325
|
+
(class << self; self end).send(:define_method, :warn){|w| warning = w}
|
1326
|
+
before_otp_authentication_route{before_called = true}
|
1327
|
+
warning.must_equal "before_otp_authentication_route is deprecated, switch to before_otp_auth_route"
|
1328
|
+
otp_drift 10
|
1329
|
+
end
|
1330
|
+
roda do |r|
|
1331
|
+
r.rodauth
|
1332
|
+
|
1333
|
+
r.redirect '/login' unless rodauth.logged_in?
|
1334
|
+
|
1335
|
+
if rodauth.two_factor_authentication_setup?
|
1336
|
+
r.redirect '/otp-auth' unless rodauth.authenticated?
|
1337
|
+
view :content=>"With OTP"
|
1338
|
+
else
|
1339
|
+
view :content=>"Without OTP"
|
1340
|
+
end
|
1341
|
+
end
|
1342
|
+
|
1343
|
+
login
|
1344
|
+
page.html.must_include('Without OTP')
|
1345
|
+
|
1346
|
+
visit '/otp-auth'
|
1347
|
+
before_called.must_equal false
|
1348
|
+
page.current_path.must_equal '/otp-setup'
|
1349
|
+
|
1350
|
+
secret = page.html.match(/Secret: ([a-z2-7]{16})/)[1]
|
1351
|
+
totp = ROTP::TOTP.new(secret)
|
1352
|
+
fill_in 'Password', :with=>'0123456789'
|
1353
|
+
fill_in 'Authentication Code', :with=>totp.now
|
1354
|
+
click_button 'Setup Two Factor Authentication'
|
1355
|
+
page.find('#notice_flash').text.must_equal 'Two factor authentication is now setup'
|
1356
|
+
page.current_path.must_equal '/'
|
1357
|
+
page.html.must_include 'With OTP'
|
1358
|
+
|
1359
|
+
logout
|
1360
|
+
before_called.must_equal false
|
1361
|
+
login
|
1362
|
+
page.current_path.must_equal '/otp-auth'
|
1363
|
+
before_called.must_equal true
|
1364
|
+
end
|
1319
1365
|
end
|
@@ -73,7 +73,7 @@ describe 'Rodauth verify_account_grace_period feature' do
|
|
73
73
|
click_button 'Create Account'
|
74
74
|
click_button 'Send Verification Email Again'
|
75
75
|
page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your account"
|
76
|
-
page.current_path.must_equal '/
|
76
|
+
page.current_path.must_equal '/'
|
77
77
|
email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
|
78
78
|
|
79
79
|
visit link
|
data/spec/verify_account_spec.rb
CHANGED
@@ -2,9 +2,11 @@ require File.expand_path("spec_helper", File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
describe 'Rodauth verify_account feature' do
|
4
4
|
it "should support verifying accounts" do
|
5
|
+
last_sent_column = nil
|
5
6
|
rodauth do
|
6
7
|
enable :login, :create_account, :verify_account
|
7
8
|
verify_account_autologin? false
|
9
|
+
verify_account_email_last_sent_column{last_sent_column}
|
8
10
|
end
|
9
11
|
roda do |r|
|
10
12
|
r.rodauth
|
@@ -25,21 +27,49 @@ describe 'Rodauth verify_account feature' do
|
|
25
27
|
page.find('#error_flash').text.must_equal 'The account you tried to login with is currently awaiting verification'
|
26
28
|
page.html.must_include("If you no longer have the email to verify the account, you can request that it be resent to you")
|
27
29
|
click_button 'Send Verification Email Again'
|
28
|
-
page.current_path.must_equal '/
|
30
|
+
page.current_path.must_equal '/'
|
29
31
|
email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
|
30
32
|
|
33
|
+
visit '/login'
|
31
34
|
click_link 'Resend Verify Account Information'
|
32
35
|
fill_in 'Login', :with=>'foo@example2.com'
|
33
36
|
click_button 'Send Verification Email Again'
|
34
|
-
page.current_path.must_equal '/
|
37
|
+
page.current_path.must_equal '/'
|
35
38
|
email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
|
36
39
|
|
40
|
+
visit '/login'
|
41
|
+
last_sent_column = :email_last_sent
|
42
|
+
click_link 'Resend Verify Account Information'
|
43
|
+
fill_in 'Login', :with=>'foo@example2.com'
|
44
|
+
click_button 'Send Verification Email Again'
|
45
|
+
page.current_path.must_equal '/'
|
46
|
+
page.find('#error_flash').text.must_equal "An email has recently been sent to you with a link to verify your account"
|
47
|
+
Mail::TestMailer.deliveries.must_equal []
|
48
|
+
|
49
|
+
visit '/login'
|
50
|
+
DB[:account_verification_keys].update(:email_last_sent => Time.now - 250).must_equal 1
|
51
|
+
click_link 'Resend Verify Account Information'
|
52
|
+
fill_in 'Login', :with=>'foo@example2.com'
|
53
|
+
click_button 'Send Verification Email Again'
|
54
|
+
page.current_path.must_equal '/'
|
55
|
+
page.find('#error_flash').text.must_equal "An email has recently been sent to you with a link to verify your account"
|
56
|
+
Mail::TestMailer.deliveries.must_equal []
|
57
|
+
|
58
|
+
visit '/login'
|
59
|
+
DB[:account_verification_keys].update(:email_last_sent => Time.now - 350).must_equal 1
|
60
|
+
click_link 'Resend Verify Account Information'
|
61
|
+
fill_in 'Login', :with=>'foo@example2.com'
|
62
|
+
click_button 'Send Verification Email Again'
|
63
|
+
page.current_path.must_equal '/'
|
64
|
+
email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
|
65
|
+
|
66
|
+
DB[:account_verification_keys].update(:email_last_sent => Time.now - 350).must_equal 1
|
37
67
|
visit '/create-account'
|
38
68
|
fill_in 'Login', :with=>'foo@example2.com'
|
39
69
|
click_button 'Create Account'
|
40
70
|
click_button 'Send Verification Email Again'
|
41
71
|
page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your account"
|
42
|
-
page.current_path.must_equal '/
|
72
|
+
page.current_path.must_equal '/'
|
43
73
|
|
44
74
|
link = email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com')
|
45
75
|
visit link[0...-1]
|
@@ -78,7 +78,60 @@ describe 'Rodauth verify_login_change feature' do
|
|
78
78
|
page.body.must_include('Logged In')
|
79
79
|
end
|
80
80
|
|
81
|
-
it "should
|
81
|
+
it "should check for duplicate accounts before sending verify email and before updating login" do
|
82
|
+
rodauth do
|
83
|
+
enable :login, :logout, :verify_login_change, :create_account
|
84
|
+
change_login_requires_password? false
|
85
|
+
create_account_autologin? false
|
86
|
+
end
|
87
|
+
roda do |r|
|
88
|
+
r.rodauth
|
89
|
+
r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
|
90
|
+
end
|
91
|
+
|
92
|
+
visit '/create-account'
|
93
|
+
fill_in 'Login', :with=>'foo@example2.com'
|
94
|
+
fill_in 'Confirm Login', :with=>'foo@example2.com'
|
95
|
+
fill_in 'Password', :with=>'0123456789'
|
96
|
+
fill_in 'Confirm Password', :with=>'0123456789'
|
97
|
+
click_button 'Create Account'
|
98
|
+
|
99
|
+
login
|
100
|
+
|
101
|
+
visit '/change-login'
|
102
|
+
fill_in 'Login', :with=>'foo@example2.com'
|
103
|
+
fill_in 'Confirm Login', :with=>'foo@example.com'
|
104
|
+
click_button 'Change Login'
|
105
|
+
page.find('#error_flash').text.must_equal "There was an error changing your login"
|
106
|
+
page.body.must_include "logins do not match"
|
107
|
+
|
108
|
+
visit '/change-login'
|
109
|
+
fill_in 'Login', :with=>'foo@example2.com'
|
110
|
+
fill_in 'Confirm Login', :with=>'foo@example2.com'
|
111
|
+
click_button 'Change Login'
|
112
|
+
page.find('#error_flash').text.must_equal "There was an error changing your login"
|
113
|
+
page.body.must_include "invalid login, already an account with this login"
|
114
|
+
|
115
|
+
visit '/change-login'
|
116
|
+
fill_in 'Login', :with=>'foo@example3.com'
|
117
|
+
fill_in 'Confirm Login', :with=>'foo@example3.com'
|
118
|
+
click_button 'Change Login'
|
119
|
+
link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example3.com')
|
120
|
+
|
121
|
+
logout
|
122
|
+
|
123
|
+
DB[:accounts].where(:email=>'foo@example2.com').update(:email=>'foo@example3.com')
|
124
|
+
|
125
|
+
visit link
|
126
|
+
click_button 'Verify Login Change'
|
127
|
+
page.find('#error_flash').text.must_equal "Unable to change login as there is already an account with the new login"
|
128
|
+
page.current_path.must_equal '/login'
|
129
|
+
|
130
|
+
visit link
|
131
|
+
page.find('#error_flash').text.must_equal "invalid verify login change key"
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should handle uniqueness errors raised when inserting verify login change entry" do
|
82
135
|
unique = false
|
83
136
|
rodauth do
|
84
137
|
enable :login, :logout, :verify_login_change
|