rodauth 1.22.0 → 1.23.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +12 -0
  3. data/README.rdoc +5 -3
  4. data/doc/email_base.rdoc +1 -0
  5. data/doc/release_notes/1.23.0.txt +32 -0
  6. data/lib/rodauth.rb +5 -2
  7. data/lib/rodauth/features/base.rb +8 -0
  8. data/lib/rodauth/features/change_password_notify.rb +1 -1
  9. data/lib/rodauth/features/create_account.rb +1 -1
  10. data/lib/rodauth/features/email_auth.rb +3 -4
  11. data/lib/rodauth/features/email_base.rb +7 -2
  12. data/lib/rodauth/features/lockout.rb +1 -1
  13. data/lib/rodauth/features/login.rb +6 -2
  14. data/lib/rodauth/features/otp.rb +6 -3
  15. data/lib/rodauth/features/password_expiration.rb +1 -1
  16. data/lib/rodauth/features/recovery_codes.rb +3 -3
  17. data/lib/rodauth/features/reset_password.rb +2 -2
  18. data/lib/rodauth/features/sms_codes.rb +5 -5
  19. data/lib/rodauth/features/verify_account.rb +2 -2
  20. data/lib/rodauth/features/verify_login_change.rb +1 -1
  21. data/lib/rodauth/version.rb +1 -1
  22. data/templates/email-auth-request-form.str +2 -2
  23. data/templates/reset-password-request.str +3 -3
  24. data/templates/unlock-account-request.str +3 -3
  25. data/templates/verify-account-resend.str +3 -3
  26. metadata +5 -43
  27. data/Rakefile +0 -179
  28. data/spec/account_expiration_spec.rb +0 -225
  29. data/spec/all.rb +0 -1
  30. data/spec/change_login_spec.rb +0 -156
  31. data/spec/change_password_notify_spec.rb +0 -33
  32. data/spec/change_password_spec.rb +0 -202
  33. data/spec/close_account_spec.rb +0 -162
  34. data/spec/confirm_password_spec.rb +0 -70
  35. data/spec/create_account_spec.rb +0 -127
  36. data/spec/disallow_common_passwords_spec.rb +0 -93
  37. data/spec/disallow_password_reuse_spec.rb +0 -179
  38. data/spec/email_auth_spec.rb +0 -285
  39. data/spec/http_basic_auth_spec.rb +0 -143
  40. data/spec/jwt_cors_spec.rb +0 -57
  41. data/spec/jwt_refresh_spec.rb +0 -256
  42. data/spec/jwt_spec.rb +0 -235
  43. data/spec/lockout_spec.rb +0 -250
  44. data/spec/login_spec.rb +0 -328
  45. data/spec/migrate/001_tables.rb +0 -184
  46. data/spec/migrate/002_account_password_hash_column.rb +0 -11
  47. data/spec/migrate_password/001_tables.rb +0 -73
  48. data/spec/migrate_travis/001_tables.rb +0 -141
  49. data/spec/password_complexity_spec.rb +0 -109
  50. data/spec/password_expiration_spec.rb +0 -244
  51. data/spec/password_grace_period_spec.rb +0 -93
  52. data/spec/remember_spec.rb +0 -451
  53. data/spec/reset_password_spec.rb +0 -229
  54. data/spec/rodauth_spec.rb +0 -343
  55. data/spec/session_expiration_spec.rb +0 -58
  56. data/spec/single_session_spec.rb +0 -127
  57. data/spec/spec_helper.rb +0 -327
  58. data/spec/two_factor_spec.rb +0 -1462
  59. data/spec/update_password_hash_spec.rb +0 -40
  60. data/spec/verify_account_grace_period_spec.rb +0 -171
  61. data/spec/verify_account_spec.rb +0 -240
  62. data/spec/verify_change_login_spec.rb +0 -46
  63. data/spec/verify_login_change_spec.rb +0 -232
  64. data/spec/views/layout-other.str +0 -11
  65. data/spec/views/layout.str +0 -11
  66. data/spec/views/login.str +0 -21
@@ -1,11 +0,0 @@
1
- Sequel.migration do
2
- up do
3
- # Only for testing of account_password_hash_column, not recommended for new
4
- # applications
5
- add_column :accounts, :ph, String
6
- end
7
-
8
- down do
9
- drop_column :accounts, :ph
10
- end
11
- end
@@ -1,73 +0,0 @@
1
- require 'rodauth/migrations'
2
-
3
- Sequel.migration do
4
- up do
5
- create_table(:account_password_hashes) do
6
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
7
- String :password_hash, :null=>false
8
- end
9
- Rodauth.create_database_authentication_functions(self)
10
- case database_type
11
- when :postgres
12
- user = get(Sequel.lit('current_user')).sub(/_password\z/, '')
13
- run "REVOKE ALL ON account_password_hashes FROM public"
14
- run "REVOKE ALL ON FUNCTION rodauth_get_salt(int8) FROM public"
15
- run "REVOKE ALL ON FUNCTION rodauth_valid_password_hash(int8, text) FROM public"
16
- run "GRANT INSERT, UPDATE, DELETE ON account_password_hashes TO #{user}"
17
- run "GRANT SELECT(id) ON account_password_hashes TO #{user}"
18
- run "GRANT EXECUTE ON FUNCTION rodauth_get_salt(int8) TO #{user}"
19
- run "GRANT EXECUTE ON FUNCTION rodauth_valid_password_hash(int8, text) TO #{user}"
20
- when :mysql
21
- user = get(Sequel.lit('current_user')).sub(/_password@/, '@')
22
- db_name = get(Sequel.function(:database))
23
- run "GRANT EXECUTE ON #{db_name}.* TO #{user}"
24
- run "GRANT INSERT, UPDATE, DELETE ON account_password_hashes TO #{user}"
25
- run "GRANT SELECT (id) ON account_password_hashes TO #{user}"
26
- when :mssql
27
- user = get(Sequel.function(:DB_NAME))
28
- run "GRANT EXECUTE ON rodauth_get_salt TO #{user}"
29
- run "GRANT EXECUTE ON rodauth_valid_password_hash TO #{user}"
30
- run "GRANT INSERT, UPDATE, DELETE ON account_password_hashes TO #{user}"
31
- run "GRANT SELECT ON account_password_hashes(id) TO #{user}"
32
- end
33
-
34
- # Used by the disallow_password_reuse feature
35
- create_table(:account_previous_password_hashes) do
36
- primary_key :id, :type=>:Bignum
37
- foreign_key :account_id, :accounts, :type=>:Bignum
38
- String :password_hash, :null=>false
39
- end
40
- Rodauth.create_database_previous_password_check_functions(self)
41
-
42
- case database_type
43
- when :postgres
44
- user = get(Sequel.lit('current_user')).sub(/_password\z/, '')
45
- run "REVOKE ALL ON account_previous_password_hashes FROM public"
46
- run "REVOKE ALL ON FUNCTION rodauth_get_previous_salt(int8) FROM public"
47
- run "REVOKE ALL ON FUNCTION rodauth_previous_password_hash_match(int8, text) FROM public"
48
- run "GRANT INSERT, UPDATE, DELETE ON account_previous_password_hashes TO #{user}"
49
- run "GRANT SELECT(id, account_id) ON account_previous_password_hashes TO #{user}"
50
- run "GRANT USAGE ON account_previous_password_hashes_id_seq TO #{user}"
51
- run "GRANT EXECUTE ON FUNCTION rodauth_get_previous_salt(int8) TO #{user}"
52
- run "GRANT EXECUTE ON FUNCTION rodauth_previous_password_hash_match(int8, text) TO #{user}"
53
- when :mysql
54
- user = get(Sequel.lit('current_user')).sub(/_password@/, '@')
55
- db_name = get(Sequel.function(:database))
56
- run "GRANT EXECUTE ON #{db_name}.* TO #{user}"
57
- run "GRANT INSERT, UPDATE, DELETE ON account_previous_password_hashes TO #{user}"
58
- run "GRANT SELECT (id, account_id) ON account_previous_password_hashes TO #{user}"
59
- when :mssql
60
- user = get(Sequel.function(:DB_NAME))
61
- run "GRANT EXECUTE ON rodauth_get_previous_salt TO #{user}"
62
- run "GRANT EXECUTE ON rodauth_previous_password_hash_match TO #{user}"
63
- run "GRANT INSERT, UPDATE, DELETE ON account_previous_password_hashes TO #{user}"
64
- run "GRANT SELECT ON account_previous_password_hashes(id, account_id) TO #{user}"
65
- end
66
- end
67
-
68
- down do
69
- Rodauth.drop_database_previous_password_check_functions(self)
70
- Rodauth.drop_database_authentication_functions(self)
71
- drop_table(:account_previous_password_hashes, :account_password_hashes)
72
- end
73
- end
@@ -1,141 +0,0 @@
1
- require 'rodauth/migrations'
2
-
3
- Sequel.migration do
4
- up do
5
- extension :date_arithmetic
6
-
7
- create_table(:account_statuses) do
8
- Integer :id, :primary_key=>true
9
- String :name, :null=>false, :unique=>true
10
- end
11
- from(:account_statuses).import([:id, :name], [[1, 'Unverified'], [2, 'Verified'], [3, 'Closed']])
12
-
13
- db = self
14
- create_table(:accounts) do
15
- primary_key :id, :type=>:Bignum
16
- foreign_key :status_id, :account_statuses, :null=>false, :default=>1
17
- if db.database_type == :postgres
18
- citext :email, :null=>false
19
- constraint :valid_email, :email=>/^[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+$/
20
- index :email, :unique=>true, :where=>{:status_id=>[1, 2]}
21
- else
22
- String :email, :null=>false
23
- index :email, :unique=>true
24
- end
25
-
26
- String :ph
27
- end
28
-
29
- create_table(:account_password_hashes) do
30
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
31
- String :password_hash, :null=>false
32
- end
33
- Rodauth.create_database_authentication_functions(self)
34
-
35
- deadline_opts = proc do |days|
36
- if database_type == :mysql
37
- {:null=>false}
38
- else
39
- {:null=>false, :default=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, :days=>days)}
40
- end
41
- end
42
-
43
- create_table(:account_password_reset_keys) do
44
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
45
- String :key, :null=>false
46
- DateTime :deadline, deadline_opts[1]
47
- DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
48
- end
49
-
50
- # Used by the refresh token feature
51
- create_table(:account_jwt_refresh_keys) do
52
- primary_key :id, :type=>:Bignum
53
- foreign_key :account_id, :accounts, :type=>:Bignum
54
- String :key, :null=>false
55
- DateTime :deadline, deadline_opts[1]
56
- end
57
-
58
- create_table(:account_verification_keys) do
59
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
60
- String :key, :null=>false
61
- DateTime :requested_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
62
- DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
63
- end
64
-
65
- create_table(:account_login_change_keys) do
66
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
67
- String :key, :null=>false
68
- String :login, :null=>false
69
- DateTime :deadline, deadline_opts[1]
70
- end
71
-
72
- create_table(:account_remember_keys) do
73
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
74
- String :key, :null=>false
75
- DateTime :deadline, deadline_opts[14]
76
- end
77
-
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
83
- end
84
-
85
- create_table(:account_login_failures) do
86
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
87
- Integer :number, :null=>false, :default=>1
88
- end
89
- create_table(:account_lockouts) do
90
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
91
- String :key, :null=>false
92
- DateTime :deadline, deadline_opts[1]
93
- DateTime :email_last_sent
94
- end
95
-
96
- create_table(:account_password_change_times) do
97
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
98
- DateTime :changed_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
99
- end
100
-
101
- create_table(:account_activity_times) do
102
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
103
- DateTime :last_activity_at, :null=>false
104
- DateTime :last_login_at, :null=>false
105
- DateTime :expired_at
106
- end
107
-
108
- create_table(:account_session_keys) do
109
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
110
- String :key, :null=>false
111
- end
112
-
113
- create_table(:account_otp_keys) do
114
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
115
- String :key, :null=>false
116
- Integer :num_failures, :null=>false, :default=>0
117
- Time :last_use, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
118
- end
119
-
120
- create_table(:account_recovery_codes) do
121
- foreign_key :id, :accounts, :type=>:Bignum
122
- String :code
123
- primary_key [:id, :code]
124
- end
125
-
126
- create_table(:account_sms_codes) do
127
- foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
128
- String :phone_number, :null=>false
129
- Integer :num_failures
130
- String :code
131
- DateTime :code_issued_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
132
- end
133
-
134
- create_table(:account_previous_password_hashes) do
135
- primary_key :id, :type=>:Bignum
136
- foreign_key :account_id, :accounts, :type=>:Bignum
137
- String :password_hash, :null=>false
138
- end
139
- Rodauth.create_database_previous_password_check_functions(self)
140
- end
141
- end
@@ -1,109 +0,0 @@
1
- require File.expand_path("spec_helper", File.dirname(__FILE__))
2
-
3
- describe 'Rodauth password complexity feature' do
4
- it "should do additional password complexity checks" do
5
- rodauth do
6
- enable :login, :change_password, :password_complexity
7
- change_password_requires_password? false
8
- password_dictionary_file 'spec/words'
9
- end
10
- roda do |r|
11
- r.rodauth
12
- r.root{view :content=>""}
13
- end
14
-
15
- login
16
- page.current_path.must_equal '/'
17
-
18
- visit '/change-password'
19
-
20
- bad_passwords = [
21
- ["minimum 6 characters", %w"a1OX"],
22
- ["does not include uppercase letters, lowercase letters, and numbers",
23
- %w'sdflksdfl sdflks!fl Sdflksdfl dfl1sdfl DFL1SDFL DFL!SDFL'],
24
- ["includes common character sequence",
25
- %w"Aqwerty12 Aazerty12 HA123ha HA234ha HA345ha HA456ha HA567ha HA678ha HA789ha HA890ha"],
26
- ["contains 3 or more of the same character in a row", %w"Helll0 Hellllll0"],
27
- ["is a word in a dictionary",
28
- %w"Password1 1Password1 1PaSSword1 1P@$5w0Rd1 2398|3@$+7809 2|!7+1e l4$7$124 N!88|e56"]
29
- ]
30
-
31
-
32
- bad_passwords.each do |message, passwords|
33
- passwords.each do |pass|
34
- fill_in 'New Password', :with=>pass
35
- fill_in 'Confirm Password', :with=>pass
36
- click_button 'Change Password'
37
- page.html.must_include("invalid password, does not meet requirements (#{message})")
38
- page.find('#error_flash').text.must_equal "There was an error changing your password"
39
- end
40
- end
41
-
42
- fill_in 'New Password', :with=>'footpassword'
43
- fill_in 'Confirm Password', :with=>'footpassword'
44
- click_button 'Change Password'
45
- page.find('#notice_flash').text.must_equal "Your password has been changed"
46
- end
47
-
48
- it "should support default dictionary" do
49
- default_dictionary = '/usr/share/dict/words'
50
- skip("#{default_dictionary} not present") unless File.file?(default_dictionary)
51
- pass = File.read(default_dictionary).split.sort_by{|w| w.length}.last
52
- skip("#{default_dictionary} empty") unless pass
53
- pass = pass.downcase.gsub(/[^a-z]/, '')
54
-
55
- rodauth do
56
- enable :login, :change_password, :password_complexity
57
- change_password_requires_password? false
58
- end
59
- roda do |r|
60
- r.rodauth
61
- r.root{view :content=>""}
62
- end
63
-
64
- login
65
- page.current_path.must_equal '/'
66
-
67
- visit '/change-password'
68
- fill_in 'New Password', :with=>"135#{pass}135"
69
- fill_in 'Confirm Password', :with=>"135#{pass}135"
70
- click_button 'Change Password'
71
- page.html.must_include("invalid password")
72
- page.find('#error_flash').text.must_equal "There was an error changing your password"
73
-
74
- fill_in 'New Password', :with=>'footpassword'
75
- fill_in 'Confirm Password', :with=>'footpassword'
76
- click_button 'Change Password'
77
- page.find('#notice_flash').text.must_equal "Your password has been changed"
78
- end
79
-
80
- it "should support no dictionary" do
81
- default_dictionary = '/usr/share/dict/words'
82
- skip("#{default_dictionary} not present") unless File.file?(default_dictionary)
83
-
84
- rodauth do
85
- enable :login, :change_password, :password_complexity
86
- change_password_requires_password? false
87
- password_dictionary_file false
88
- end
89
- roda do |r|
90
- r.rodauth
91
- r.root{view :content=>""}
92
- end
93
-
94
- login
95
- page.current_path.must_equal '/'
96
-
97
- visit '/change-password'
98
- fill_in 'New Password', :with=>"password123"
99
- fill_in 'Confirm Password', :with=>"password123"
100
- click_button 'Change Password'
101
- page.html.must_include("invalid password")
102
- page.find('#error_flash').text.must_equal "There was an error changing your password"
103
-
104
- fill_in 'New Password', :with=>'Password1'
105
- fill_in 'Confirm Password', :with=>'Password1'
106
- click_button 'Change Password'
107
- page.find('#notice_flash').text.must_equal "Your password has been changed"
108
- end
109
- end
@@ -1,244 +0,0 @@
1
- require File.expand_path("spec_helper", File.dirname(__FILE__))
2
-
3
- describe 'Rodauth password expiration feature' do
4
- it "should force password changes after x number of days" do
5
- rodauth do
6
- enable :login, :logout, :change_password, :reset_password, :password_expiration
7
- allow_password_change_after 1000
8
- change_password_requires_password? false
9
- end
10
- roda do |r|
11
- r.rodauth
12
- rodauth.require_current_password if rodauth.logged_in?
13
- r.root{view :content=>""}
14
- end
15
-
16
- login(:pass=>'01234567')
17
- click_button 'Request Password Reset'
18
- link = email_link(/(\/reset-password\?key=.+)$/)
19
-
20
- visit link
21
- page.current_path.must_equal '/reset-password'
22
-
23
- login
24
- page.current_path.must_equal '/'
25
-
26
- visit '/change-password'
27
- fill_in 'New Password', :with=>'banana'
28
- fill_in 'Confirm Password', :with=>'banana'
29
- click_button 'Change Password'
30
- page.current_path.must_equal '/'
31
-
32
- visit '/change-password'
33
- page.current_path.must_equal '/'
34
- page.find('#error_flash').text.must_equal "Your password cannot be changed yet"
35
-
36
- logout
37
-
38
- visit link
39
- page.current_path.must_equal '/'
40
- page.find('#error_flash').text.must_equal "Your password cannot be changed yet"
41
-
42
- DB[:account_password_change_times].update(:changed_at=>Time.now - 1100)
43
-
44
- visit link
45
- page.current_path.must_equal '/reset-password'
46
-
47
- login(:pass=>'banana')
48
- page.current_path.must_equal '/'
49
-
50
- visit '/change-password'
51
- page.current_path.must_equal '/change-password'
52
-
53
- logout
54
-
55
- DB[:account_password_change_times].update(:changed_at=>Time.now - 91*86400)
56
-
57
- login(:pass=>'banana')
58
- page.current_path.must_equal '/change-password'
59
- page.find('#error_flash').text.must_equal "Your password has expired and needs to be changed"
60
-
61
- visit '/foo'
62
- page.current_path.must_equal '/change-password'
63
- page.find('#error_flash').text.must_equal "Your password has expired and needs to be changed"
64
-
65
- fill_in 'New Password', :with=>'banana2'
66
- fill_in 'Confirm Password', :with=>'banana2'
67
- click_button 'Change Password'
68
- page.current_path.must_equal '/'
69
-
70
- visit '/change-password'
71
- page.current_path.must_equal '/'
72
- page.find('#error_flash').text.must_equal "Your password cannot be changed yet"
73
-
74
- logout
75
-
76
- visit link
77
- page.current_path.must_equal '/'
78
- page.find('#error_flash').text.must_equal "Your password cannot be changed yet"
79
- end
80
-
81
- it "should update password changed at when creating accounts" do
82
- rodauth do
83
- enable :login, :change_password, :password_expiration
84
- password_expiration_default true
85
- change_password_requires_password? false
86
- end
87
- roda do |r|
88
- r.rodauth
89
- rodauth.require_current_password
90
- r.root{view :content=>""}
91
- end
92
-
93
- login
94
- page.current_path.must_equal '/change-password'
95
-
96
- visit '/'
97
- page.current_path.must_equal '/change-password'
98
- fill_in 'New Password', :with=>'banana'
99
- fill_in 'Confirm Password', :with=>'banana'
100
- click_button 'Change Password'
101
- page.current_path.must_equal '/'
102
- end
103
-
104
- it "should update password changed at when creating accounts" do
105
- rodauth do
106
- enable :login, :create_account, :password_expiration
107
- allow_password_change_after 1000
108
- account_password_hash_column :ph
109
- end
110
- roda do |r|
111
- r.rodauth
112
- r.root{view :content=>""}
113
- end
114
-
115
- visit '/create-account'
116
- fill_in 'Login', :with=>'foo2@example.com'
117
- fill_in 'Confirm Login', :with=>'foo2@example.com'
118
- fill_in 'Password', :with=>'apple2'
119
- fill_in 'Confirm Password', :with=>'apple2'
120
- click_button 'Create Account'
121
-
122
- visit '/change-password'
123
- page.current_path.must_equal '/'
124
- page.find('#error_flash').text.must_equal "Your password cannot be changed yet"
125
- end
126
-
127
- it "should remove password expiration data when closing accounts" do
128
- rodauth do
129
- enable :create_account, :close_account, :password_expiration
130
- close_account_requires_password? false
131
- create_account_autologin? true
132
- end
133
- roda do |r|
134
- r.rodauth
135
- r.root{view :content=>""}
136
- end
137
-
138
- visit '/create-account'
139
- fill_in 'Login', :with=>'foo2@example.com'
140
- fill_in 'Confirm Login', :with=>'foo2@example.com'
141
- fill_in 'Password', :with=>'apple2'
142
- fill_in 'Confirm Password', :with=>'apple2'
143
- click_button 'Create Account'
144
-
145
- DB[:account_password_change_times].count.must_equal 1
146
- visit '/close-account'
147
- click_button 'Close Account'
148
- DB[:account_password_change_times].count.must_equal 0
149
- end
150
-
151
- it "should handle the case where the password is expired while the user has logged in" do
152
- rodauth do
153
- enable :login, :change_password, :password_expiration
154
- password_expiration_default true
155
- allow_password_change_after(-1000)
156
- change_password_requires_password? false
157
- require_password_change_after 3600
158
- end
159
- roda do |r|
160
- r.rodauth
161
- rodauth.require_current_password
162
- r.get("expire", :d){|d| session[:password_changed_at] = Time.now.to_i - d.to_i; r.redirect '/'}
163
- r.root{view :content=>""}
164
- end
165
-
166
- login
167
- page.current_path.must_equal '/change-password'
168
-
169
- visit '/'
170
- page.current_path.must_equal '/change-password'
171
- fill_in 'New Password', :with=>'banana'
172
- fill_in 'Confirm Password', :with=>'banana'
173
- click_button 'Change Password'
174
- page.current_path.must_equal '/'
175
-
176
- visit "/expire/90"
177
- page.current_path.must_equal '/'
178
-
179
- visit "/expire/7200"
180
- page.current_path.must_equal '/change-password'
181
- end
182
-
183
- it "should force password changes via jwt" do
184
- rodauth do
185
- enable :login, :logout, :change_password, :reset_password, :password_expiration
186
- allow_password_change_after 1000
187
- change_password_requires_password? false
188
- reset_password_email_body{reset_password_email_link}
189
- end
190
- roda(:jwt) do |r|
191
- r.rodauth
192
- rodauth.require_current_password
193
- if rodauth.authenticated?
194
- [1]
195
- else
196
- [2]
197
- end
198
- end
199
-
200
- json_request.must_equal [200, [2]]
201
-
202
- res = json_request('/reset-password-request', :login=>'foo@example.com')
203
- res.must_equal [200, {"success"=>"An email has been sent to you with a link to reset the password for your account"}]
204
- link = email_link(/key=.+$/)
205
-
206
- json_login
207
-
208
- res = json_request('/change-password', :password=>'0123456789', "new-password"=>'0123456', "password-confirm"=>'0123456')
209
- res.must_equal [200, {'success'=>"Your password has been changed"}]
210
-
211
- json_request.must_equal [200, [1]]
212
-
213
- res = json_request('/change-password', :password=>'0123456', "new-password"=>'01234567', "password-confirm"=>'01234567')
214
- res.must_equal [400, {'error'=>"Your password cannot be changed yet"}]
215
-
216
- json_logout
217
-
218
- res = json_request('/reset-password', :key=>link[4..-1], :password=>'01234567', "password-confirm"=>'01234567')
219
- res.must_equal [400, {'error'=>"Your password cannot be changed yet"}]
220
-
221
- DB[:account_password_change_times].update(:changed_at=>Time.now - 1100)
222
- res = json_request('/reset-password', :key=>link[4..-1], :password=>'01234567', "password-confirm"=>'01234567')
223
- res.must_equal [200, {"success"=>"Your password has been reset"}]
224
-
225
- DB[:account_password_change_times].update(:changed_at=>Time.now - 1100)
226
- json_login(:pass=>'01234567')
227
- res = json_request('/change-password', :password=>'01234567', "new-password"=>'012345678', "password-confirm"=>'012345678')
228
- res.must_equal [200, {'success'=>"Your password has been changed"}]
229
-
230
- DB[:account_password_change_times].update(:changed_at=>Time.now - 91*86400)
231
-
232
- json_logout
233
- json_request.must_equal [200, [2]]
234
-
235
- res = json_login(:pass=>'012345678', :no_check=>true)
236
- res.must_equal [400, {'error'=>"Your password has expired and needs to be changed"}]
237
- json_request.must_equal [400, {'error'=>"Your password has expired and needs to be changed"}]
238
-
239
- res = json_request('/change-password', :password=>'012345678', "new-password"=>'012345678a', "password-confirm"=>'012345678a')
240
- res.must_equal [200, {'success'=>"Your password has been changed"}]
241
-
242
- json_request.must_equal [200, [1]]
243
- end
244
- end