rodauth 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +20 -0
  3. data/README.rdoc +14 -3
  4. data/Rakefile +2 -2
  5. data/doc/base.rdoc +1 -1
  6. data/doc/internals.rdoc +222 -0
  7. data/doc/release_notes/1.10.0.txt +80 -0
  8. data/doc/reset_password.rdoc +8 -2
  9. data/doc/verify_account.rdoc +7 -1
  10. data/doc/verify_change_login.rdoc +8 -6
  11. data/doc/verify_login_change.rdoc +52 -0
  12. data/lib/rodauth/features/account_expiration.rb +1 -1
  13. data/lib/rodauth/features/base.rb +1 -1
  14. data/lib/rodauth/features/change_login.rb +9 -2
  15. data/lib/rodauth/features/change_password.rb +1 -1
  16. data/lib/rodauth/features/close_account.rb +1 -1
  17. data/lib/rodauth/features/confirm_password.rb +1 -1
  18. data/lib/rodauth/features/create_account.rb +1 -1
  19. data/lib/rodauth/features/disallow_password_reuse.rb +1 -1
  20. data/lib/rodauth/features/email_base.rb +6 -2
  21. data/lib/rodauth/features/http_basic_auth.rb +1 -1
  22. data/lib/rodauth/features/jwt.rb +1 -1
  23. data/lib/rodauth/features/lockout.rb +1 -1
  24. data/lib/rodauth/features/login.rb +1 -1
  25. data/lib/rodauth/features/login_password_requirements_base.rb +1 -1
  26. data/lib/rodauth/features/logout.rb +1 -1
  27. data/lib/rodauth/features/otp.rb +1 -1
  28. data/lib/rodauth/features/password_complexity.rb +1 -1
  29. data/lib/rodauth/features/password_expiration.rb +1 -1
  30. data/lib/rodauth/features/password_grace_period.rb +1 -1
  31. data/lib/rodauth/features/recovery_codes.rb +1 -1
  32. data/lib/rodauth/features/remember.rb +1 -1
  33. data/lib/rodauth/features/reset_password.rb +22 -4
  34. data/lib/rodauth/features/session_expiration.rb +1 -1
  35. data/lib/rodauth/features/single_session.rb +1 -1
  36. data/lib/rodauth/features/sms_codes.rb +1 -1
  37. data/lib/rodauth/features/two_factor_base.rb +1 -1
  38. data/lib/rodauth/features/update_password_hash.rb +1 -1
  39. data/lib/rodauth/features/verify_account.rb +23 -5
  40. data/lib/rodauth/features/verify_account_grace_period.rb +1 -1
  41. data/lib/rodauth/features/verify_change_login.rb +1 -1
  42. data/lib/rodauth/features/verify_login_change.rb +189 -0
  43. data/lib/rodauth/version.rb +1 -1
  44. data/lib/rodauth.rb +16 -2
  45. data/spec/migrate/001_tables.rb +10 -0
  46. data/spec/migrate_travis/001_tables.rb +7 -0
  47. data/spec/reset_password_spec.rb +8 -1
  48. data/spec/rodauth_spec.rb +27 -0
  49. data/spec/spec_helper.rb +11 -7
  50. data/spec/verify_account_grace_period_spec.rb +36 -0
  51. data/spec/verify_account_spec.rb +6 -0
  52. data/spec/verify_login_change_spec.rb +179 -0
  53. data/templates/reset-password-request.str +3 -3
  54. data/templates/verify-account-resend.str +3 -3
  55. data/templates/verify-login-change-email.str +9 -0
  56. data/templates/verify-login-change.str +5 -0
  57. metadata +12 -2
@@ -18,11 +18,18 @@ describe 'Rodauth reset_password feature' do
18
18
  click_button 'Request Password Reset'
19
19
  page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to reset the password for your account"
20
20
  page.current_path.must_equal '/'
21
-
22
21
  link = email_link(/(\/reset-password\?key=.+)$/)
22
+
23
23
  visit link[0...-1]
24
24
  page.find('#error_flash').text.must_equal "invalid password reset key"
25
25
 
26
+ visit '/login'
27
+ click_link 'Forgot Password?'
28
+ fill_in 'Login', :with=>'foo@example.com'
29
+ click_button 'Request Password Reset'
30
+ email_link(/(\/reset-password\?key=.+)$/).must_equal link
31
+
32
+ visit '/login'
26
33
  login(:pass=>'01234567', :visit=>false)
27
34
  click_button 'Request Password Reset'
28
35
  email_link(/(\/reset-password\?key=.+)$/).must_equal link
data/spec/rodauth_spec.rb CHANGED
@@ -220,4 +220,31 @@ describe 'Rodauth' do
220
220
  app.instance_variable_get(:@middleware).length.must_equal 1
221
221
  app.ancestors.map(&:to_s).wont_include 'Roda::RodaPlugins::Flash::InstanceMethods'
222
222
  end
223
+
224
+ it "should inherit rodauth configuration in subclass" do
225
+ auth_class = nil
226
+ no_freeze!
227
+ rodauth{auth_class = auth}
228
+ roda(:csrf=>false, :flash=>false){}
229
+ Class.new(app).rodauth.must_equal auth_class
230
+ end
231
+
232
+ it "should use subclass of rodauth configuration if modifying rodauth configuration in subclass" do
233
+ auth_class = nil
234
+ no_freeze!
235
+ rodauth{auth_class = auth; auth_class_eval{def foo; 'foo' end}}
236
+ roda{|r| rodauth.foo}
237
+ visit '/'
238
+ page.html.must_equal 'foo'
239
+
240
+ a = Class.new(app)
241
+ a.plugin(:rodauth){auth_class_eval{def foo; "#{super}bar" end}}
242
+ a.rodauth.superclass.must_equal auth_class
243
+
244
+ visit '/'
245
+ page.html.must_equal 'foo'
246
+ self.app = a
247
+ visit '/'
248
+ page.html.must_equal 'foobar'
249
+ end
223
250
  end
data/spec/spec_helper.rb CHANGED
@@ -43,22 +43,26 @@ require 'tilt/string'
43
43
  db_url = ENV['RODAUTH_SPEC_DB'] || 'postgres:///?user=rodauth_test&password=rodauth_test'
44
44
  DB = Sequel.connect(db_url, :identifier_mangling=>false)
45
45
  DB.extension :freeze_datasets, :date_arithmetic
46
- DB.freeze
47
46
  puts "using #{DB.database_type}"
48
47
 
49
48
  #DB.loggers << Logger.new($stdout)
50
- if DB.adapter_scheme == :jdbc && DB.database_type == :postgres
51
- DB.add_named_conversion_proc(:citext){|s| s}
52
- end
53
- if DB.adapter_scheme == :jdbc && DB.database_type == :sqlite
54
- DB.timezone = :utc
55
- Sequel.application_timezone = :local
49
+ if DB.adapter_scheme == :jdbc
50
+ case DB.database_type
51
+ when :postgres
52
+ DB.add_named_conversion_proc(:citext){|s| s}
53
+ when :sqlite
54
+ DB.timezone = :utc
55
+ Sequel.application_timezone = :local
56
+ end
56
57
  end
58
+
57
59
  if ENV['RODAUTH_SPEC_MIGRATE']
58
60
  Sequel.extension :migration
59
61
  Sequel::Migrator.run(DB, 'spec/migrate_travis')
60
62
  end
61
63
 
64
+ DB.freeze
65
+
62
66
  ENV['RACK_ENV'] = 'test'
63
67
 
64
68
  ::Mail.defaults do
@@ -46,6 +46,42 @@ describe 'Rodauth verify_account_grace_period feature' do
46
46
  page.body.must_include('Logged Intrue')
47
47
  end
48
48
 
49
+ it "should resend verify account email if attempting to create new account with same login" do
50
+ rodauth do
51
+ enable :login, :logout, :change_password, :create_account, :verify_account_grace_period
52
+ change_password_requires_password? false
53
+ end
54
+ roda do |r|
55
+ r.rodauth
56
+ r.root{view :content=>rodauth.logged_in? ? "Logged In#{rodauth.verified_account?}" : "Not Logged"}
57
+ end
58
+
59
+ visit '/create-account'
60
+ fill_in 'Login', :with=>'foo@example2.com'
61
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
62
+ fill_in 'Password', :with=>'0123456789'
63
+ fill_in 'Confirm Password', :with=>'0123456789'
64
+ click_button 'Create Account'
65
+ page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your account"
66
+ link = email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com')
67
+ page.body.must_include('Logged Infalse')
68
+ page.current_path.must_equal '/'
69
+
70
+ logout
71
+ visit '/create-account'
72
+ fill_in 'Login', :with=>'foo@example2.com'
73
+ click_button 'Create Account'
74
+ click_button 'Send Verification Email Again'
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 '/login'
77
+ email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
78
+
79
+ visit link
80
+ click_button 'Verify Account'
81
+ page.find('#notice_flash').text.must_equal "Your account has been verified"
82
+ page.body.must_include('Logged Intrue')
83
+ end
84
+
49
85
  it "should not allow changing logins for unverified accounts" do
50
86
  rodauth do
51
87
  enable :login, :logout, :change_login, :verify_account_grace_period
@@ -26,8 +26,14 @@ describe 'Rodauth verify_account feature' do
26
26
  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
27
  click_button 'Send Verification Email Again'
28
28
  page.current_path.must_equal '/login'
29
+ email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
29
30
 
31
+ click_link 'Resend Verify Account Information'
32
+ fill_in 'Login', :with=>'foo@example2.com'
33
+ click_button 'Send Verification Email Again'
34
+ page.current_path.must_equal '/login'
30
35
  email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com').must_equal link
36
+
31
37
  visit '/create-account'
32
38
  fill_in 'Login', :with=>'foo@example2.com'
33
39
  click_button 'Create Account'
@@ -0,0 +1,179 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe 'Rodauth verify_login_change feature' do
4
+ it "should support verifying login changes" do
5
+ rodauth do
6
+ enable :login, :logout, :verify_login_change
7
+ change_login_requires_password? false
8
+ end
9
+ roda do |r|
10
+ r.rodauth
11
+ r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
12
+ end
13
+
14
+ login
15
+
16
+ visit '/change-login'
17
+ fill_in 'Login', :with=>'foo@example2.com'
18
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
19
+ click_button 'Change Login'
20
+ link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com')
21
+ page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your login change"
22
+
23
+ visit '/change-login'
24
+ fill_in 'Login', :with=>'foo@example2.com'
25
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
26
+ click_button 'Change Login'
27
+ email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com').must_equal link
28
+
29
+ visit '/change-login'
30
+ fill_in 'Login', :with=>'foo@example3.com'
31
+ fill_in 'Confirm Login', :with=>'foo@example3.com'
32
+ click_button 'Change Login'
33
+ new_link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example3.com')
34
+ new_link.wont_equal link
35
+
36
+ logout
37
+
38
+ visit link
39
+ page.find('#error_flash').text.must_equal "invalid verify login change key"
40
+
41
+ visit new_link
42
+ page.title.must_equal 'Verify Login Change'
43
+ click_button 'Verify Login Change'
44
+ page.find('#notice_flash').text.must_equal "Your login change has been verified"
45
+ page.body.must_include('Not Logged')
46
+
47
+ login
48
+ page.find('#error_flash').text.must_equal "There was an error logging in"
49
+
50
+ login(:login=>'foo@example3.com')
51
+ page.body.must_include('Logged In')
52
+ end
53
+
54
+ it "should support verifying login changes with autologin" do
55
+ rodauth do
56
+ enable :login, :logout, :verify_login_change
57
+ verify_login_change_autologin? true
58
+ change_login_requires_password? false
59
+ end
60
+ roda do |r|
61
+ r.rodauth
62
+ r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
63
+ end
64
+
65
+ login
66
+
67
+ visit '/change-login'
68
+ fill_in 'Login', :with=>'foo@example2.com'
69
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
70
+ click_button 'Change Login'
71
+ link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com')
72
+
73
+ logout
74
+
75
+ visit link
76
+ click_button 'Verify Login Change'
77
+ page.find('#notice_flash').text.must_equal "Your login change has been verified"
78
+ page.body.must_include('Logged In')
79
+ end
80
+
81
+ it "should handle uniqueness errors raised when inserting password reset token" do
82
+ unique = false
83
+ rodauth do
84
+ enable :login, :logout, :verify_login_change
85
+ change_login_requires_password? false
86
+
87
+ auth_class_eval do
88
+ define_method(:raised_uniqueness_violation) do |*a, &block|
89
+ unique.call if unique
90
+ super(*a, &block)
91
+ end
92
+ end
93
+ end
94
+ roda do |r|
95
+ r.rodauth
96
+ r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
97
+ end
98
+
99
+ login
100
+
101
+ visit '/change-login'
102
+ fill_in 'Login', :with=>'foo@example2.com'
103
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
104
+ click_button 'Change Login'
105
+ link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com')
106
+ page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your login change"
107
+
108
+ unique = lambda{DB[:account_login_change_keys].update(:login=>'foo@example3.com'); true}
109
+ visit '/change-login'
110
+ fill_in 'Login', :with=>'foo@example2.com'
111
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
112
+ proc{click_button 'Change Login'}.must_raise Sequel::ConstraintViolation
113
+ end
114
+
115
+ it "should clear verify login change token when closing account" do
116
+ rodauth do
117
+ enable :login, :verify_login_change, :close_account
118
+ change_login_requires_password? false
119
+ end
120
+ roda do |r|
121
+ r.rodauth
122
+ r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
123
+ end
124
+
125
+ login
126
+
127
+ visit '/change-login'
128
+ fill_in 'Login', :with=>'foo@example2.com'
129
+ fill_in 'Confirm Login', :with=>'foo@example2.com'
130
+ click_button 'Change Login'
131
+ email_link(/key=.+$/, 'foo@example2.com').wont_be_nil
132
+
133
+ DB[:account_login_change_keys].count.must_equal 1
134
+ visit '/close-account'
135
+ fill_in 'Password', :with=>'0123456789'
136
+ click_button 'Close Account'
137
+ DB[:account_login_change_keys].count.must_equal 0
138
+ end
139
+
140
+ it "should support verifying login changes for accounts via jwt" do
141
+ rodauth do
142
+ enable :login, :verify_login_change
143
+ change_login_requires_password? false
144
+ verify_login_change_email_body{verify_login_change_email_link}
145
+ end
146
+ roda(:jwt) do |r|
147
+ r.rodauth
148
+ end
149
+
150
+ json_login
151
+
152
+ res = json_request('/change-login', :login=>'foo2@example.com', "login-confirm"=>'foo2@example.com')
153
+ res.must_equal [200, {'success'=>"An email has been sent to you with a link to verify your login change"}]
154
+ link = email_link(/key=.+$/, 'foo2@example.com')
155
+
156
+ res = json_request('/change-login', :login=>'foo2@example.com', "login-confirm"=>'foo2@example.com')
157
+ res.must_equal [200, {'success'=>"An email has been sent to you with a link to verify your login change"}]
158
+ email_link(/key=.+$/, 'foo2@example.com').must_equal link
159
+
160
+ res = json_request('/change-login', :login=>'foo3@example.com', "login-confirm"=>'foo3@example.com')
161
+ res.must_equal [200, {'success'=>"An email has been sent to you with a link to verify your login change"}]
162
+ new_link = email_link(/key=.+$/, 'foo3@example.com')
163
+ new_link.wont_equal link
164
+
165
+ res = json_request('/verify-login-change')
166
+ res.must_equal [401, {"error"=>"Unable to verify login change"}]
167
+
168
+ res = json_request('/verify-login-change', :key=>link[4..-1])
169
+ res.must_equal [401, {"error"=>"Unable to verify login change"}]
170
+
171
+ res = json_request('/verify-login-change', :key=>new_link[4..-1])
172
+ res.must_equal [200, {"success"=>"Your login change has been verified"}]
173
+
174
+ res = json_request("/login", :login=>'foo@example.com', :password=>'0123456789')
175
+ res.must_equal [401, {'error'=>"There was an error logging in", "field-error"=>["login", "no matching login"]}]
176
+
177
+ json_login(:login=>'foo3@example.com')
178
+ end
179
+ end
@@ -1,7 +1,7 @@
1
1
  <form action="#{rodauth.prefix}/#{rodauth.reset_password_request_route}" method="post" class="rodauth form-horizontal" role="form" id="reset-password-request-form">
2
2
  #{rodauth.reset_password_request_additional_form_tags}
3
- <input type="hidden" name="#{rodauth.login_param}" value="#{h request[rodauth.login_param]}"/>
4
3
  #{rodauth.csrf_tag}
5
- If you have forgotten your password, you can request a password reset:
6
- <input type="submit" class="btn btn-primary inline" value="#{rodauth.reset_password_request_button}"/>
4
+ <p>If you have forgotten your password, you can request a password reset: </p>
5
+ #{(login = request[rodauth.login_param]) ? "<input type=\"hidden\" name=\"#{rodauth.login_param}\" value=\"#{h login}\"/>" : rodauth.render('login-field')}
6
+ #{rodauth.button(rodauth.reset_password_request_button)}
7
7
  </form>
@@ -1,7 +1,7 @@
1
1
  <form action="#{rodauth.prefix}/#{rodauth.verify_account_resend_route}" method="post" class="rodauth form-horizontal" role="form" id="verify-account-resend-form">
2
2
  #{rodauth.verify_account_resend_additional_form_tags}
3
- <input type="hidden" name="#{rodauth.login_param}" value="#{h request[rodauth.login_param]}"/>
4
3
  #{rodauth.csrf_tag}
5
- If you no longer have the email to verify the account, you can request that it be resent to you:
6
- <input type="submit" class="btn btn-primary inline" value="#{rodauth.verify_account_resend_button}"/>
4
+ <p>If you no longer have the email to verify the account, you can request that it be resent to you:</p>
5
+ #{(login = request[rodauth.login_param]) ? "<input type=\"hidden\" name=\"#{rodauth.login_param}\" value=\"#{h login}\"/>" : rodauth.render('login-field')}
6
+ #{rodauth.button(rodauth.verify_account_resend_button)}
7
7
  </form>
@@ -0,0 +1,9 @@
1
+ Someone with an account has requested their login be changed to this email address:
2
+
3
+ Old Login: #{rodauth.verify_login_change_old_login}
4
+ New Login: #{rodauth.verify_login_change_new_login}
5
+
6
+ If you did not request this login change, please ignore this message. If you
7
+ requested this login change, please go to
8
+ #{rodauth.verify_login_change_email_link}
9
+ to verify the login change.
@@ -0,0 +1,5 @@
1
+ <form method="post" class="rodauth form-horizontal" role="form" id="verify-login-change-form">
2
+ #{rodauth.verify_login_change_additional_form_tags}
3
+ #{rodauth.csrf_tag}
4
+ #{rodauth.button(rodauth.verify_login_change_button)}
5
+ </form>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-23 00:00:00.000000000 Z
11
+ date: 2017-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -226,6 +226,8 @@ extra_rdoc_files:
226
226
  - doc/verify_change_login.rdoc
227
227
  - doc/update_password_hash.rdoc
228
228
  - doc/http_basic_auth.rdoc
229
+ - doc/verify_login_change.rdoc
230
+ - doc/internals.rdoc
229
231
  - doc/release_notes/1.0.0.txt
230
232
  - doc/release_notes/1.1.0.txt
231
233
  - doc/release_notes/1.2.0.txt
@@ -236,6 +238,7 @@ extra_rdoc_files:
236
238
  - doc/release_notes/1.7.0.txt
237
239
  - doc/release_notes/1.8.0.txt
238
240
  - doc/release_notes/1.9.0.txt
241
+ - doc/release_notes/1.10.0.txt
239
242
  files:
240
243
  - CHANGELOG
241
244
  - MIT-LICENSE
@@ -251,6 +254,7 @@ files:
251
254
  - doc/disallow_password_reuse.rdoc
252
255
  - doc/email_base.rdoc
253
256
  - doc/http_basic_auth.rdoc
257
+ - doc/internals.rdoc
254
258
  - doc/jwt.rdoc
255
259
  - doc/lockout.rdoc
256
260
  - doc/login.rdoc
@@ -263,6 +267,7 @@ files:
263
267
  - doc/recovery_codes.rdoc
264
268
  - doc/release_notes/1.0.0.txt
265
269
  - doc/release_notes/1.1.0.txt
270
+ - doc/release_notes/1.10.0.txt
266
271
  - doc/release_notes/1.2.0.txt
267
272
  - doc/release_notes/1.3.0.txt
268
273
  - doc/release_notes/1.4.0.txt
@@ -281,6 +286,7 @@ files:
281
286
  - doc/verify_account.rdoc
282
287
  - doc/verify_account_grace_period.rdoc
283
288
  - doc/verify_change_login.rdoc
289
+ - doc/verify_login_change.rdoc
284
290
  - lib/roda/plugins/rodauth.rb
285
291
  - lib/rodauth.rb
286
292
  - lib/rodauth/features/account_expiration.rb
@@ -313,6 +319,7 @@ files:
313
319
  - lib/rodauth/features/verify_account.rb
314
320
  - lib/rodauth/features/verify_account_grace_period.rb
315
321
  - lib/rodauth/features/verify_change_login.rb
322
+ - lib/rodauth/features/verify_login_change.rb
316
323
  - lib/rodauth/migrations.rb
317
324
  - lib/rodauth/version.rb
318
325
  - spec/account_expiration_spec.rb
@@ -345,6 +352,7 @@ files:
345
352
  - spec/verify_account_grace_period_spec.rb
346
353
  - spec/verify_account_spec.rb
347
354
  - spec/verify_change_login_spec.rb
355
+ - spec/verify_login_change_spec.rb
348
356
  - spec/views/layout-other.str
349
357
  - spec/views/layout.str
350
358
  - spec/views/login.str
@@ -383,6 +391,8 @@ files:
383
391
  - templates/verify-account-email.str
384
392
  - templates/verify-account-resend.str
385
393
  - templates/verify-account.str
394
+ - templates/verify-login-change-email.str
395
+ - templates/verify-login-change.str
386
396
  homepage: https://github.com/jeremyevans/rodauth
387
397
  licenses:
388
398
  - MIT