rodauth 1.13.0 → 1.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f6c97c6e01c1026bf027fb99348421103909a668
4
- data.tar.gz: 910777f85e599d240356aeb2eba4339db0c481c3
2
+ SHA256:
3
+ metadata.gz: 62724514e9c4c31b8af9992d86ed3f1de98a38860ee7890f2da54e28fa4f2394
4
+ data.tar.gz: 58ba690b1c2e193728c6341d60df851e043fd3706ed1769c5ae6ecc0eed24592
5
5
  SHA512:
6
- metadata.gz: c2a571d6eac5c96a458da39020a074edb561c2f71ef32a93382177fcdfe67d73d0ad5dd548255d7c8a09e9f9d67166becd616ec1d8c650d30d766a42b24990ae
7
- data.tar.gz: '070838b8388668fa6c7ac73145c82dd0e825d61c83ea43e603789f1efd0383d3c57b147345f55b47d709f6a3786f475fc78fa2e1f5fd30213d6e691fcb6ba5ba'
6
+ metadata.gz: 8b187d024978cf9a7c22cc8f21e892dab50075c7eb2a605c45c7423cec186169e160d944e051d1e9c369222e373ee0e5ebd9effe217ca13f0d3edc7ec0e2875e
7
+ data.tar.gz: b990669e7aecbc09dcd90d89001ca35dd12fea964bbe1e8c29629b95f9a9bfe4fbb19cbcd683ab5b28575a7e00940aff087604e80f18c3d6c9a65b7bc658976b
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ === 1.14.0 (2017-12-19)
2
+
3
+ * Don't allow unlocking expired accounts when using account_expiration and lockout features (jeremyevans)
4
+
5
+ * Don't allow resetting passwords for expired accounts when using account_expiration and reset_password features (jeremyevans)
6
+
7
+ * Add change_password_notify feature for emailing when user uses change password feature (jeremyevans)
8
+
1
9
  === 1.13.0 (2017-11-21)
2
10
 
3
11
  * Add json_response_body(hash) configuration method to jwt feature (jeremyevans)
data/README.rdoc CHANGED
@@ -41,6 +41,7 @@ hashes by protecting access via database functions.
41
41
  * JWT (JSON API support for all other features)
42
42
  * Update Password Hash (when hash cost changes)
43
43
  * HTTP Basic Auth
44
+ * Change Password Notify
44
45
 
45
46
  == Resources
46
47
 
@@ -0,0 +1,24 @@
1
+ = Documentation for Change Password Notify Feature
2
+
3
+ The change password notify feature emails the user when their password
4
+ is changed using the change password feature.
5
+ auth_value_method :password_changed_email_subject, 'Password Changed'
6
+
7
+ auth_value_methods(
8
+ :password_changed_email_body
9
+ )
10
+ auth_methods(
11
+ :create_password_changed_email,
12
+ :send_password_changed_email
13
+ )
14
+
15
+
16
+ == Auth Value Methods
17
+
18
+ password_changed_email_subject :: Subject to use for the password changed emails
19
+ password_changed_email_body :: Body to use for the password changed emails
20
+
21
+ == Auth Methods
22
+
23
+ create_password_changed_email :: A Mail::Message for the password changed email to send.
24
+ send_password_changed_email :: Send the account unlock email.
@@ -0,0 +1,19 @@
1
+ = New Features
2
+
3
+ * A change_password_notify feature has been added, which emails the
4
+ user when the change_password feature is used to change their
5
+ password. This can alert the user when their password may have
6
+ been changed without their knowledge.
7
+
8
+ = Other Improvements
9
+
10
+ * When using the account_expiration feature with the reset_password
11
+ feature, resetting the passwords for expired accounts is no longer
12
+ allowed. Note that the previous behavior isn't considered a
13
+ security issue, because even after resetting their password,
14
+ expired accounts could not login.
15
+
16
+ * When using the account_expiration feature with the lockout feature,
17
+ unlocking expired accounts is no longer allowed. Note that the
18
+ previous behavior isn't considered a security issue, because even
19
+ after unlocking the account, expired accounts could not login.
@@ -71,6 +71,26 @@ module Rodauth
71
71
 
72
72
  private
73
73
 
74
+ def before_reset_password
75
+ check_account_expiration
76
+ super if defined?(super)
77
+ end
78
+
79
+ def before_reset_password_request
80
+ check_account_expiration
81
+ super if defined?(super)
82
+ end
83
+
84
+ def before_unlock_account
85
+ check_account_expiration
86
+ super if defined?(super)
87
+ end
88
+
89
+ def before_unlock_account_request
90
+ check_account_expiration
91
+ super if defined?(super)
92
+ end
93
+
74
94
  def after_close_account
75
95
  super if defined?(super)
76
96
  account_activity_ds(account_id).delete
@@ -0,0 +1,37 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Rodauth
4
+ Feature.define(:change_password_notify, :ChangePasswordNotify) do
5
+ depends :change_password, :email_base
6
+
7
+ auth_value_method :password_changed_email_subject, 'Password Changed'
8
+
9
+ auth_value_methods(
10
+ :password_changed_email_body
11
+ )
12
+ auth_methods(
13
+ :create_password_changed_email,
14
+ :send_password_changed_email
15
+ )
16
+
17
+ private
18
+
19
+ def send_password_changed_email
20
+ create_password_changed_email.deliver!
21
+ end
22
+
23
+ def create_password_changed_email
24
+ create_email(password_changed_email_subject, password_changed_email_body)
25
+ end
26
+
27
+ def password_changed_email_body
28
+ render('password-changed-email')
29
+ end
30
+
31
+ def after_change_password
32
+ super
33
+ send_password_changed_email
34
+ end
35
+ end
36
+ end
37
+
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- VERSION = '1.13.0'.freeze
4
+ VERSION = '1.14.0'.freeze
5
5
 
6
6
  def self.version
7
7
  VERSION
@@ -1,7 +1,7 @@
1
1
  require File.expand_path("spec_helper", File.dirname(__FILE__))
2
2
 
3
3
  describe 'Rodauth account expiration feature' do
4
- it "should force account expiration after x number of days" do
4
+ it "should force account expiration after x number of days since last login" do
5
5
  rodauth do
6
6
  enable :login, :logout, :account_expiration
7
7
  end
@@ -27,6 +27,141 @@ describe 'Rodauth account expiration feature' do
27
27
  end
28
28
  end
29
29
 
30
+ it "should not allow resetting of passwords for expired accounts" do
31
+ rodauth do
32
+ enable :login, :logout, :account_expiration, :reset_password
33
+ end
34
+ roda do |r|
35
+ r.rodauth
36
+ r.root{view :content=>rodauth.logged_in? ? "Logged In#{rodauth.last_account_login_at.strftime('%m%d%y')}" : "Not Logged"}
37
+ end
38
+
39
+ now = Time.now
40
+ login
41
+ page.body.must_include "Logged In#{now.strftime('%m%d%y')}"
42
+ logout
43
+
44
+ visit '/login'
45
+ click_link 'Forgot Password?'
46
+ fill_in 'Login', :with=>'foo@example.com'
47
+ click_button 'Request Password Reset'
48
+ link = email_link(/(\/reset-password\?key=.+)$/)
49
+
50
+ visit link
51
+ fill_in 'Password', :with=>'0123456'
52
+ fill_in 'Confirm Password', :with=>'0123456'
53
+ click_button 'Reset Password'
54
+ page.find('#notice_flash').text.must_equal "Your password has been reset"
55
+ page.current_path.must_equal '/'
56
+
57
+ visit '/login'
58
+ click_link 'Forgot Password?'
59
+ fill_in 'Login', :with=>'foo@example.com'
60
+ click_button 'Request Password Reset'
61
+ link = email_link(/(\/reset-password\?key=.+)$/)
62
+
63
+ DB[:account_activity_times].update(:last_login_at => Time.now - 181*86400)
64
+
65
+ visit link
66
+ page.title.must_equal 'Reset Password'
67
+ fill_in 'Password', :with=>'01234567'
68
+ fill_in 'Confirm Password', :with=>'01234567'
69
+ click_button 'Reset Password'
70
+ page.find('#error_flash').text.must_equal "You cannot log into this account as it has expired"
71
+ page.body.must_include 'Not Logged'
72
+ page.current_path.must_equal '/'
73
+
74
+ visit '/login'
75
+ click_link 'Forgot Password?'
76
+ fill_in 'Login', :with=>'foo@example.com'
77
+ click_button 'Request Password Reset'
78
+ page.find('#error_flash').text.must_equal "You cannot log into this account as it has expired"
79
+ page.body.must_include 'Not Logged'
80
+ page.current_path.must_equal '/'
81
+ end
82
+
83
+ it "should not allow account unlocks for expired accounts" do
84
+ rodauth do
85
+ enable :lockout, :account_expiration, :logout
86
+ max_invalid_logins 2
87
+ unlock_account_autologin? false
88
+ end
89
+ roda do |r|
90
+ r.rodauth
91
+ r.root{view :content=>(rodauth.logged_in? ? "Logged In" : "Not Logged")}
92
+ end
93
+
94
+ login
95
+ logout
96
+
97
+ visit '/login'
98
+ fill_in 'Login', :with=>'foo@example.com'
99
+ 3.times do
100
+ fill_in 'Password', :with=>'012345678910'
101
+ click_button 'Login'
102
+ end
103
+
104
+ page.body.must_include("This account is currently locked out")
105
+ click_button 'Request Account Unlock'
106
+ page.find('#notice_flash').text.must_equal 'An email has been sent to you with a link to unlock your account'
107
+ link = email_link(/(\/unlock-account\?key=.+)$/)
108
+
109
+ visit link
110
+ click_button 'Unlock Account'
111
+ page.find('#notice_flash').text.must_equal 'Your account has been unlocked'
112
+ page.body.must_include('Not Logged')
113
+
114
+ visit '/login'
115
+ fill_in 'Login', :with=>'foo@example.com'
116
+ 3.times do
117
+ fill_in 'Password', :with=>'012345678910'
118
+ click_button 'Login'
119
+ end
120
+
121
+ page.body.must_include("This account is currently locked out")
122
+ click_button 'Request Account Unlock'
123
+ page.find('#notice_flash').text.must_equal 'An email has been sent to you with a link to unlock your account'
124
+ link = email_link(/(\/unlock-account\?key=.+)$/)
125
+
126
+ DB[:account_activity_times].update(:last_login_at => Time.now - 181*86400)
127
+
128
+ visit link
129
+ click_button 'Unlock Account'
130
+ page.find('#error_flash').text.must_equal "You cannot log into this account as it has expired"
131
+ page.body.must_include 'Not Logged'
132
+ page.current_path.must_equal '/'
133
+ end
134
+
135
+ it "should not allow account unlock requests for expired accounts" do
136
+ rodauth do
137
+ enable :lockout, :account_expiration, :logout
138
+ max_invalid_logins 2
139
+ unlock_account_autologin? false
140
+ end
141
+ roda do |r|
142
+ r.rodauth
143
+ r.root{view :content=>(rodauth.logged_in? ? "Logged In" : "Not Logged")}
144
+ end
145
+
146
+ login
147
+ logout
148
+
149
+ visit '/login'
150
+ fill_in 'Login', :with=>'foo@example.com'
151
+ 3.times do
152
+ fill_in 'Password', :with=>'012345678910'
153
+ click_button 'Login'
154
+ end
155
+
156
+ DB[:account_activity_times].update(:last_login_at => Time.now - 181*86400)
157
+
158
+ page.body.must_include("This account is currently locked out")
159
+ click_button 'Request Account Unlock'
160
+ page.find('#error_flash').text.must_equal "You cannot log into this account as it has expired"
161
+ page.body.must_include 'Not Logged'
162
+ page.current_path.must_equal '/'
163
+ end
164
+
30
165
  it "should use last activity time if configured" do
31
166
  rodauth do
32
167
  enable :login, :logout, :account_expiration
@@ -0,0 +1,33 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe 'Rodauth change_password_notify feature' do
4
+ it "should email when using change password" do
5
+ rodauth do
6
+ enable :login, :logout, :change_password_notify
7
+ change_password_requires_password? false
8
+ end
9
+ roda do |r|
10
+ r.rodauth
11
+ r.root{view :content=>""}
12
+ end
13
+
14
+ login
15
+ page.current_path.must_equal '/'
16
+
17
+ visit '/change-password'
18
+ fill_in 'New Password', :with=>'0123456'
19
+ fill_in 'Confirm Password', :with=>'0123456'
20
+ click_button 'Change Password'
21
+ page.find('#notice_flash').text.must_equal "Your password has been changed"
22
+
23
+ page.current_path.must_equal '/'
24
+ msgs = Mail::TestMailer.deliveries
25
+ msgs.length.must_equal 1
26
+ msgs.first.to.first.must_equal 'foo@example.com'
27
+ msgs.first.body.to_s.must_equal <<EMAIL
28
+ Someone (hopefully you) has changed the password for the account
29
+ associated to this email address.
30
+ EMAIL
31
+ msgs.clear
32
+ end
33
+ end
@@ -0,0 +1,2 @@
1
+ Someone (hopefully you) has changed the password for the account
2
+ associated to this email address.
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.13.0
4
+ version: 1.14.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-11-21 00:00:00.000000000 Z
11
+ date: 2017-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -228,6 +228,7 @@ extra_rdoc_files:
228
228
  - doc/http_basic_auth.rdoc
229
229
  - doc/verify_login_change.rdoc
230
230
  - doc/internals.rdoc
231
+ - doc/change_password_notify.rdoc
231
232
  - doc/release_notes/1.0.0.txt
232
233
  - doc/release_notes/1.1.0.txt
233
234
  - doc/release_notes/1.2.0.txt
@@ -242,6 +243,7 @@ extra_rdoc_files:
242
243
  - doc/release_notes/1.11.0.txt
243
244
  - doc/release_notes/1.12.0.txt
244
245
  - doc/release_notes/1.13.0.txt
246
+ - doc/release_notes/1.14.0.txt
245
247
  files:
246
248
  - CHANGELOG
247
249
  - MIT-LICENSE
@@ -251,6 +253,7 @@ files:
251
253
  - doc/base.rdoc
252
254
  - doc/change_login.rdoc
253
255
  - doc/change_password.rdoc
256
+ - doc/change_password_notify.rdoc
254
257
  - doc/close_account.rdoc
255
258
  - doc/confirm_password.rdoc
256
259
  - doc/create_account.rdoc
@@ -274,6 +277,7 @@ files:
274
277
  - doc/release_notes/1.11.0.txt
275
278
  - doc/release_notes/1.12.0.txt
276
279
  - doc/release_notes/1.13.0.txt
280
+ - doc/release_notes/1.14.0.txt
277
281
  - doc/release_notes/1.2.0.txt
278
282
  - doc/release_notes/1.3.0.txt
279
283
  - doc/release_notes/1.4.0.txt
@@ -299,6 +303,7 @@ files:
299
303
  - lib/rodauth/features/base.rb
300
304
  - lib/rodauth/features/change_login.rb
301
305
  - lib/rodauth/features/change_password.rb
306
+ - lib/rodauth/features/change_password_notify.rb
302
307
  - lib/rodauth/features/close_account.rb
303
308
  - lib/rodauth/features/confirm_password.rb
304
309
  - lib/rodauth/features/create_account.rb
@@ -331,6 +336,7 @@ files:
331
336
  - spec/account_expiration_spec.rb
332
337
  - spec/all.rb
333
338
  - spec/change_login_spec.rb
339
+ - spec/change_password_notify_spec.rb
334
340
  - spec/change_password_spec.rb
335
341
  - spec/close_account_spec.rb
336
342
  - spec/confirm_password_spec.rb
@@ -377,6 +383,7 @@ files:
377
383
  - templates/otp-auth.str
378
384
  - templates/otp-disable.str
379
385
  - templates/otp-setup.str
386
+ - templates/password-changed-email.str
380
387
  - templates/password-confirm-field.str
381
388
  - templates/password-field.str
382
389
  - templates/recovery-auth.str
@@ -426,7 +433,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
426
433
  version: '0'
427
434
  requirements: []
428
435
  rubyforge_project:
429
- rubygems_version: 2.6.13
436
+ rubygems_version: 2.7.3
430
437
  signing_key:
431
438
  specification_version: 4
432
439
  summary: Authentication and Account Management Framework for Rack Applications