rodauth 1.9.0 → 1.10.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 (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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63d284b3ed1dc87ff182d472e730e52d823e4dae
4
- data.tar.gz: 47599804ed740325e00c8c7bda5dcafde8b669c3
3
+ metadata.gz: b1741b1db3b830dd1edde47d251c388e51901d85
4
+ data.tar.gz: 1066a17b7b2a3565335cbcd47ef6903d3c1f5a93
5
5
  SHA512:
6
- metadata.gz: a4f64fc7c93e5a97c4ef7a100d26dcb286b157a7085c939db4bdce203b3b63f18e239f71ea09cc4881740facacc695c00a220427e91f9daea0aec7f1e65a51d3
7
- data.tar.gz: 3424177852d8cbf98f1acca6f75c46e23316664950febab7af6af720a55038570fe6d4655d4dc983e0ee29df70ad011a7cff468b5f0169604c3baed09da1e94f
6
+ metadata.gz: 76b1d26463432bb939565f09b3779cbdf6f8d7b632079115eaf62288c2817f80c1f24752e3847893e17242eadb21eccfae5cc7d7df54a45f4f7be2032207e751
7
+ data.tar.gz: 59c18ab583fde50543c9284a7831d2fbf2087d64bb8e5c33a257b82cd3b3ded7c6d28f1a38a6a32cbba04d1c34ff9d2d87264a9356fc44cc40c02ceac8298454
data/CHANGELOG CHANGED
@@ -1,3 +1,23 @@
1
+ === 1.10.0 (2017-03-23)
2
+
3
+ * Add Internals Guide (jeremyevans)
4
+
5
+ * Set FeatureConfiguration instances to constants, just like Feature instances (jeremyevans)
6
+
7
+ * When reopening rodauth configuration in roda subclass, automatically subclass rodauth configuration so it doesn't modify superclass (jeremyevans)
8
+
9
+ * Add verify_login_change feature as an alternative to verify_change_login, where the change doesn't take affect until after verification (jeremyevans) (#31)
10
+
11
+ * Add login_failed_reset_password_request_form for customizing the HTML used for the request password request form on login failures (jeremyevans)
12
+
13
+ * Make reset password request form available without requiring a login attempt, and provide a login field in that case (jeremyevans) (#30)
14
+
15
+ * Make resending verify account email request form available without requiring a login/account creation attempt, and provide a login field in that case (jeremyevans) (#30)
16
+
17
+ * Fix resending verify account email when attempting to create a new account with same login as unverified account when using verify_account_grace_period feature (jeremyevans) (#30)
18
+
19
+ * Fix precompile_rodauth_templates usage with reset_password feature (jeremyevans)
20
+
1
21
  === 1.9.0 (2017-02-22)
2
22
 
3
23
  * Make reset-password use existing password reset key if one is present (jeremyevans) (#26)
data/README.rdoc CHANGED
@@ -29,7 +29,7 @@ hashes by protecting access via database functions.
29
29
  * OTP (2 factor authentication via TOTP)
30
30
  * Recovery Codes (2 factor authentication via backup codes)
31
31
  * SMS Codes (2 factor authentication via SMS)
32
- * Verify Change Login (Reverify accounts after login changes)
32
+ * Verify Login Change (Verify new login before changing login)
33
33
  * Verify Account Grace Period (Don't require verification before login)
34
34
  * Password Grace Period (Don't require password entry if recently entered)
35
35
  * Password Complexity (More sophisticated checks)
@@ -280,6 +280,14 @@ versions of Sequel, switch the :Bignum symbols to Bignum constants.
280
280
  DateTime :requested_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
281
281
  end
282
282
 
283
+ # Used by the verify login change feature
284
+ create_table(:account_login_change_keys) do
285
+ foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
286
+ String :key, :null=>false
287
+ String :login, :null=>false
288
+ DateTime :deadline, deadline_opts[1]
289
+ end
290
+
283
291
  # Used by the remember me feature
284
292
  create_table(:account_remember_keys) do
285
293
  foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
@@ -356,6 +364,7 @@ versions of Sequel, switch the :Bignum symbols to Bignum constants.
356
364
  run "GRANT ALL ON accounts TO #{user}"
357
365
  run "GRANT ALL ON account_password_reset_keys TO #{user}"
358
366
  run "GRANT ALL ON account_verification_keys TO #{user}"
367
+ run "GRANT ALL ON account_login_change_keys TO #{user}"
359
368
  run "GRANT ALL ON account_remember_keys TO #{user}"
360
369
  run "GRANT ALL ON account_login_failures TO #{user}"
361
370
  run "GRANT ALL ON account_lockouts TO #{user}"
@@ -378,6 +387,7 @@ versions of Sequel, switch the :Bignum symbols to Bignum constants.
378
387
  :account_lockouts,
379
388
  :account_login_failures,
380
389
  :account_remember_keys,
390
+ :account_login_change_keys,
381
391
  :account_verification_keys,
382
392
  :account_password_reset_keys,
383
393
  :accounts,
@@ -993,8 +1003,9 @@ use the following basic structure
993
1003
 
994
1004
  module Rodauth
995
1005
  # :feature_name will be the argument given to enable to
996
- # load the feature
997
- FeatureName = Feature.define(:feature_name) do
1006
+ # load the feature, :FeatureName is optional and will be used to
1007
+ # set a constant name for prettier inspect output.
1008
+ Feature.define(:feature_name, :FeatureName) do
998
1009
  # Shortcut for defining auth value methods with static values
999
1010
  auth_value_method :method_name, 1 # method_value
1000
1011
 
data/Rakefile CHANGED
@@ -116,10 +116,10 @@ task :db_setup_mssql do
116
116
  $: << 'lib'
117
117
  require 'sequel'
118
118
  Sequel.extension :migration
119
- Sequel.tinytds('rodauth_test', :user=>'rodauth_test_password', :password=>'rodauth_test') do |db|
119
+ Sequel.tinytds('rodauth_test', :host=>'localhost', :user=>'rodauth_test_password', :password=>'Rodauth1.') do |db|
120
120
  Sequel::Migrator.run(db, 'spec/migrate')
121
121
  end
122
- Sequel.tinytds('rodauth_test', :user=>'rodauth_test_password', :password=>'rodauth_test') do |db|
122
+ Sequel.tinytds('rodauth_test', :host=>'localhost', :user=>'rodauth_test_password', :password=>'Rodauth1.') do |db|
123
123
  Sequel::Migrator.run(db, 'spec/migrate_password', :table=>'schema_info_password')
124
124
  end
125
125
  end
data/doc/base.rdoc CHANGED
@@ -116,7 +116,7 @@ password_match?(password) :: Check whether the given password matches the
116
116
  stored password hash.
117
117
  random_key :: A randomly generated string, used for creating tokens.
118
118
  redirect(path) :: Redirect the request to the given path.
119
- session_value :: Alias for account_session_value.
119
+ session_value :: The value for session_key in the current session.
120
120
  set_error_flash(message) :: Set the current error flash to the given message.
121
121
  set_notice_flash(message) :: Set the next notice flash to the given message.
122
122
  set_notice_now_flash(message) :: Set the current notice flash to the given message.
@@ -0,0 +1,222 @@
1
+ = Rodauth Internals
2
+
3
+ Rodauth's implementation heavily uses metaprogramming in order to DRY up the codebase, which can be a little intimiting to developers who are not familiar with the codebase. This guide explains how Rodauth is built, which should make the internals easier to understand.
4
+
5
+ == Object Model
6
+
7
+ First, let's talk about the basic parts of Rodauth.
8
+
9
+ === Rodauth::Auth
10
+
11
+ Rodauth::Auth is the core of rodauth. If a user calls +rodauth+ inside their Roda application, they get a Rodauth::Auth subclass instance. Rodauth's configuration DSL is designed to build a Rodauth::Auth subclass appropriate to the application, by loading only the features that are needed, and overriding defaults as appropriate.
12
+
13
+ === Rodauth::Configuration
14
+
15
+ Inside the block you pass to <tt>plugin :rodauth</tt>, +self+ is an instance of this class. This class is mostly empty, as most of Rodauth is implemented as separate features, and the configuration for each feature is loaded as a separate module into this instance.
16
+
17
+ === Rodauth::Feature
18
+
19
+ Each of the parts of rodauth that you can use is going to be a separate feature. Rodauth::Feature is a Module subclass, and every feature you load is included in the Rodauth::Auth subclass used by the Roda application. Rodauth::Feature has many methods designed to make building Rodauth features easier by defining methods in the Rodauth::Feature instance.
20
+
21
+ === Rodauth::FeatureConfiguration
22
+
23
+ Just as each feature is a module included in the Rodauth::Auth subclass for the application, each feature also contains a configuration module that is an instance of Rodauth::FeatureConfiguration (also a module subclass). For each feature you load into the Rodauth configuration, the Rodauth::Configuration instance is extended with the feature's Rodauth::FeatureConfiguration instance, which is what makes the feature's configuration methods available inside the <tt>plugin :rodauth</tt> block. This is why you need to enable the features in Rodauth before configuring them.
24
+
25
+
26
+ == Object Model Example
27
+
28
+ Here's some commented output hopefully showing the relation between the different parts
29
+
30
+ Roda.plugin :rodauth do
31
+ self # => #<Rodauth::Configuration> (instance)
32
+ auth # => Rodauth::Auth subclass
33
+
34
+ singleton_class.ancestors # => [#<Class:#<Rodauth::Configuration>> (singleton class of self),
35
+ # Rodauth::FeatureConfiguration::Base (instance of Rodauth::FeatureConfiguration),
36
+ # Rodauth::Configuration,
37
+ # ...]
38
+ auth.ancestors # => [Rodauth::Auth subclass,
39
+ # Rodauth::Base (instance of Rodauth::Feature),
40
+ # Rodauth::Auth,
41
+ # ...]
42
+
43
+ enable :login
44
+
45
+ singleton_class.ancestors # => [#<Class:#<Rodauth::Configuration>> (singleton class of self),
46
+ # Rodauth::FeatureConfiguration::Login (instance of Rodauth::FeatureConfiguration),
47
+ # Rodauth::FeatureConfiguration::Base (instance of Rodauth::FeatureConfiguration),
48
+ # Rodauth::Configuration,
49
+ # ...]
50
+ auth.ancestors # => [Rodauth::Auth subclass,
51
+ # Rodauth::Login (instance of Rodauth::Feature),
52
+ # Rodauth::Base (instance of Rodauth::Feature),
53
+ # Rodauth::Auth,
54
+ # ...]
55
+ end
56
+
57
+ Roda.rodauth # => Rodauth::Auth subclass
58
+ Roda.rodauth.ancestors # => [Rodauth::Auth subclass,
59
+ # Rodauth::Login (instance of Rodauth::Feature),
60
+ # Rodauth::Base (instance of Rodauth::Feature),
61
+ # Rodauth::Auth,
62
+ # ...]
63
+
64
+ Roda.route do |r|
65
+ rodauth # => Rodauth::Auth subclass instance
66
+ end
67
+
68
+ == Feature Creation Example
69
+
70
+ Here's a heavily commented example showing what is going on inside a Rodauth feature.
71
+
72
+ module Rodauth
73
+ # Feature.define takes a symbol, specifying the name of the feature. This
74
+ # is the same symbol you would pass to enable when loading the feature into
75
+ # the Rodauth configuration. Feature is a module subclass, and Feature.define
76
+ # is a class method that creates an instance of Feature (a module) and executes
77
+ # the block in the context of the Feature instance.
78
+ #
79
+ # The second argument is optional, and sets the Feature instance and related
80
+ # FeatureConfiguration instance to a constant in the Rodauth namespace, which
81
+ # makes it easier to locate via inspect.
82
+ Feature.define(:foo, :Foo) do
83
+ # Inside this block, self is an instance of Feature. As this instance of
84
+ # Feature will be included in the Rodauth::Auth subclass instance if
85
+ # the feature is loaded into the rodauth configuration, methods you define
86
+ # in this block (via def or define_method) will be callable on any
87
+ # rodauth object if this feature is loaded into the rodauth configuration.
88
+
89
+ # Feature has many instance methods that define methods in the Feature
90
+ # instance. This is one of those methods, which sets the text of the notice
91
+ # flash, shown after successful submission of the form. It's basically
92
+ # equivalent to executing this code in the feature:
93
+ #
94
+ # def foo_notice_flash
95
+ # "It worked!"
96
+ # end
97
+ #
98
+ # while also adding a method to the configuration which does:
99
+ #
100
+ # def foo_notice_flash(v=nil, &block)
101
+ # block ||= proc{v}
102
+ # @auth.class_eval do
103
+ # define_method(:foo_notice_flash, &block)
104
+ # end
105
+ # end
106
+ #
107
+ # This is what easily allows you to modify any part of Rodauth during
108
+ # configuration. The Rodauth::Auth subclass has the default behavior
109
+ # added via a method in an included module (the Feature instance), and the
110
+ # Rodauth::Configuration instance has a method that when called defines
111
+ # a method in the Rodauth::Auth subclass itself, which will take precedence
112
+ # over the default method, which defined in the included Feature instance.
113
+ notice_flash "It worked!"
114
+
115
+ # The rest of these method calls are fairly similar to notice_flash.
116
+ # This defines the foo_error_flash method, for the error flash message to
117
+ # show if the form submission wasn't successful.
118
+ error_flash "There was an error"
119
+
120
+ # This defines the foo_view method to use template 'foo.str' in the templates
121
+ # folder, and set the title of the page to 'Foo'.
122
+ view 'foo', 'Foo'
123
+
124
+ # This defines the foo_additional_form_tags method, which would generally be called
125
+ # inside the foo.str template.
126
+ additional_form_tags
127
+
128
+ # This defines the foo_button method, for the text to use on the submit button
129
+ # for the form in foo.str.
130
+ button 'Submit'
131
+
132
+ # This defines the foo_redirect method, for where to redirect after successful submission
133
+ # of the form.
134
+ redirect
135
+
136
+ # This defines the before_foo method, called before performing the foo action.
137
+ before
138
+
139
+ # This defines the after_foo method, called after successfully performing the foo action.
140
+ after
141
+
142
+ # This defines a loaded_templates method that calls super and adds 'foo' as one of the
143
+ # templates. This is necessary for precompilation of templates to work.
144
+ loaded_templates ['foo']
145
+
146
+ # auth_value_method is a generic method that takes two arguments, a method to define
147
+ # and a default value. It is similar to the methods above, except that it allows
148
+ # arbitrary method names. The notice_flash, error_flash, button, and additional_form_tags
149
+ # methods are actually defined in terms of this method.
150
+ #
151
+ # So this particular method defines a foo_error_status method that will return 401 by
152
+ # default, but also adds a cofniguration method that allows you to override the default.
153
+ auth_value_method :foo_error_status, 401
154
+
155
+ # This is similar to auth_value_method, but it only adds the configuration method.
156
+ # Using this should only be done if you have defining the method in the feature
157
+ # separately (see below).
158
+ auth_value_methods :foo_bar
159
+
160
+ # This is similar to auth_value_methods, but it changes the configuration method so that
161
+ # a block is required and you cannot provide an argument. This is used for the cases
162
+ # where a statically defined value would never make sense, such as when any correct
163
+ # behavior would depend on accessing request-specific information.
164
+ auth_methods :foo
165
+
166
+ # route defines a route used for the feature. This is the code that will be executed
167
+ # if a user goes to /foo in the Roda app.
168
+ route do |r|
169
+ # Inside the block, you are in the context of the Roda instance, just as you would
170
+ # be inside a Roda route block. r is the RodaRequest instance, just as it would
171
+ # be for a Roda route block.
172
+
173
+ # route adds a before_foo_route method that by default does nothing. It also
174
+ # adds a configuration method that you can call to set behavior that will be
175
+ # executed before routing.
176
+ before_foo_route
177
+
178
+ # Just like in Roda, r.get is called for GET requests
179
+ r.get do
180
+ # This will render a view to the user, using the foo.erb template from the
181
+ # templates directory (unless the user has overridden it), inside the Roda
182
+ # application's layout.
183
+ foo_view
184
+ end
185
+
186
+ # Just like in Roda, r.post is called for GET requests
187
+ r.post do
188
+ # This is called before performing the foo action
189
+ before_foo
190
+
191
+ # This assumes foo returns false or nil on failure, or otherwise on
192
+ # success.
193
+ if foo
194
+ # In general, Rodauth only calls after_foo if foo is successful.
195
+ after_foo
196
+
197
+ # Successful form submission will usually set the notice flash,
198
+ # the redirect to the appropriate page.
199
+ set_notice_flash foo_notice_flash
200
+ redirect foo_redirect
201
+ else
202
+ # Unsucessful form subsmission will usually set the error flash,
203
+ # the redisplay the page so that the submission can be fixed.
204
+ set_error_flash foo_error_flash
205
+ foo_view
206
+ end
207
+ end
208
+ end
209
+
210
+ # This is the default behavior for the foo method, if a user doesn't
211
+ # call the foo method inside the configuration block.
212
+ def foo
213
+ # Do Something
214
+ end
215
+
216
+ # This is the default behavior for the foo_bar method, if a user doesn't
217
+ # call the foo_bar method inside the configuration block.
218
+ def foo_bar
219
+ 42
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,80 @@
1
+ = New Features
2
+
3
+ * A verify_login_change feature has been added. This is designed
4
+ as a replacement for the previous verify_change_login feature,
5
+ which was problematic as it could result in a user being unable
6
+ to access their account if they used an incorrect email when
7
+ changing their login.
8
+
9
+ The verify_login_change feature does not change the user's login
10
+ until after the user has confirmed that they can receive email
11
+ using the new login.
12
+
13
+ The verify_login_change feature requires an additional database
14
+ table to store information on login changes, so it is not a
15
+ drop in replacement for the verify_change_login feature. However,
16
+ it is recommended that all users of verify_change_login switch
17
+ to verify_login_change.
18
+
19
+ * If using the reset_password feature, there is now a link on the
20
+ login page to a page that will allow you to request a password
21
+ reset. Previously you had to attempt to login with the account
22
+ in order to request a password reset.
23
+
24
+ * If using the verify_account feature, there is now a link on the
25
+ login page to a page that will allow you to request that the
26
+ account verification email be resent. Previously you had to
27
+ attempt to login with the account or attempt to create a new
28
+ account with the same login in order to get an account verification
29
+ email resent.
30
+
31
+ * If using the reset_password feature, there is now a
32
+ login_failed_reset_password_request_form configuration method for
33
+ customizing the HTML used for the request password reset form shown
34
+ when there is a login failure.
35
+
36
+ = Improvements
37
+
38
+ * When using the verify_account_grace_period feature, attempting to
39
+ create a new account using the same login as an existing
40
+ unverified account now correctly offers the ability to resend the
41
+ account verification email.
42
+
43
+ * The precompile_rodauth_templates method now works with the
44
+ reset_password feature.
45
+
46
+ * When attempting to reopen a rodauth configuration in a subclass
47
+ of the Roda class that created the rodauth configuration, a
48
+ subclass of the rodauth configuration is now automatically
49
+ created. This makes it so changes to the rodauth configuration
50
+ in the Roda subclass no longer affect the rodauth configuration
51
+ of the superclass.
52
+
53
+ * The FeatureConfiguration instances for each feature are now
54
+ assigned to constants, making inspect output more descriptive.
55
+
56
+ * An internals guide has been added, which explains the
57
+ metaprogramming used to implement Rodauth.
58
+
59
+ = Backwards Compatibility
60
+
61
+ * Any external features should start providing two arguments to
62
+ Feature.define, with the second argument being the constant
63
+ name to use. So instead of:
64
+
65
+ module Rodauth
66
+ Foo = Feature.define(:foo) do
67
+ # ...
68
+ end
69
+ end
70
+
71
+ switch to:
72
+
73
+ module Rodauth
74
+ Feature.define(:foo, :Foo) do
75
+ # ...
76
+ end
77
+ end
78
+
79
+ This will ensure that the related FeatureConfiguration instance
80
+ is assigned to a constant.
@@ -38,6 +38,8 @@ reset_password_request_additional_form_tags :: HTML fragment containing addition
38
38
  reset_password_request_button :: The text to use for the reset password request button.
39
39
  reset_password_request_error_flash :: The flash error to show if not able to send a reset
40
40
  password email.
41
+ reset_password_request_link :: The HTML to use for a link to the page to request a password
42
+ reset.
41
43
  reset_password_request_route :: The route to the reset password request action.
42
44
  Defaults to +reset-password-request+.
43
45
  reset_password_route :: The route to the reset password action. Defaults to
@@ -57,10 +59,13 @@ before_reset_password :: Run arbitrary code before resetting a password.
57
59
  before_reset_password_request :: Run arbitrary code before sending the reset password
58
60
  email.
59
61
  before_reset_password_route :: Run arbitrary code before handling a reset password route.
60
- create_reset_password_key :: A random string to use as a reset password key.
62
+ create_reset_password_key :: Add the reset password key data to the database.
63
+ create_reset_password_email :: A Mail::Message for the reset password email.
61
64
  get_reset_password_key(id) :: Get the password reset key for the given account id
62
65
  from the database.
63
- create_reset_password_email :: A Mail::Message for the reset password email.
66
+ login_failed_reset_password_request_form :: The HTML to use for a form to request a password
67
+ reset, shown on the login page after the user
68
+ tries to login with an invalid password.
64
69
  remove_reset_password_key :: Remove the reset password key for the current account,
65
70
  run after successful password reset.
66
71
  reset_password_email_body :: The body to use for the reset password email.
@@ -69,5 +74,6 @@ reset_password_email_link :: The link to the reset password form in the reset
69
74
  reset_password_key_insert_hash :: The hash to insert into the reset password keys
70
75
  table.
71
76
  reset_password_key_value :: The reset password key for the current account.
77
+ reset_password_request_view :: The HTML to use for the reset password request form.
72
78
  reset_password_view :: The HTML to use for the reset password form.
73
79
  send_reset_password_email :: Send the reset password email.
@@ -38,6 +38,8 @@ verify_account_resend_button :: The text to use for the verify account resend bu
38
38
  verify_account_redirect :: Where to redirect after verifying the account.
39
39
  verify_account_resend_error_flash :: The flash error to show if unable to resend a
40
40
  verify account email.
41
+ verify_account_resend_link :: The HTML to use for a link to the page to request
42
+ the account verification email be resent.
41
43
  verify_account_resend_route :: The route to the verify account resend action.
42
44
  Defaults to +verify-account-resend+.
43
45
  verify_account_route :: The route to the verify account action. Defaults to
@@ -52,10 +54,13 @@ account_from_verify_account_key(key) :: Retrieve the account using the given ver
52
54
  matches.
53
55
  after_verify_account :: Run arbitrary code after verifying the account.
54
56
  after_verify_account_resend :: Run arbitrary code after resending a verify account email.
57
+ allow_resending_verify_account_email? :: Whether to allow sending the verify account email
58
+ for the account, true by default only if the
59
+ account has not been verified.
55
60
  before_verify_account :: Run arbitrary code before verifying the account.
56
61
  before_verify_account_resend :: Run arbitrary code before resending a verify account email.
57
62
  before_verify_account_route :: Run arbitrary code before handling a verify account route.
58
- create_verify_account_key :: A random string to use as a verify account key.
63
+ create_verify_account_key :: Add the verify account key data to the database.
59
64
  create_verify_account_email :: A Mail::Message for the verify account email.
60
65
  get_verify_account_key(id) :: Get the verify account key for the given account id
61
66
  from the database.
@@ -70,4 +75,5 @@ verify_account_email_link :: The link to the verify account form in the verify
70
75
  account email.
71
76
  verify_account_key_insert_hash :: The hash to insert into the verify account keys
72
77
  table.
78
+ verify_account_key_value :: The value of the verify account key.
73
79
  verify_account_view :: The HTML to use for the verify account form.
@@ -1,9 +1,11 @@
1
1
  = Documentation for Verify Change Login Feature
2
2
 
3
+ This feature is deprecated, because it is possible for a user to get
4
+ locked out of their account if they use the wrong address on the
5
+ change login page. It is recommended that users switch to using the
6
+ verify login change feature, which doesn't change the login until
7
+ after it has been verified.
8
+
3
9
  The verify change login feature implements account reverification after
4
- change login. Any time you use the verify account and change login
5
- features together, you should probably use this, otherwise it is trivial
6
- for users to work around account verification by creating an account with
7
- an email address they control, and the changing the login to an email
8
- address they don't control. Depends on the change login and verify
9
- account grace period features.
10
+ change login. Depends on the change login and verify account grace
11
+ period features.
@@ -0,0 +1,52 @@
1
+ = Documentation for Verify Login Change Feature
2
+
3
+ The verify login change feature implements login verification after
4
+ a login change. With this feature, login changes do not take effect
5
+ until after the user has verified the new login. Until the new
6
+ login has been verified, the old login continues to work.
7
+
8
+ Any time you use the verify login change and change login features together,
9
+ you should probably use this, otherwise it is trivial for users to work
10
+ around account verification by creating an account with an email address
11
+ they control, and the changing the login to an email address they don't
12
+ control. Depends on the change login and email base features.
13
+
14
+ == Auth Value Methods
15
+
16
+ no_matching_verify_login_change_key_message :: The flash error message to show when an invalid verify login change key is used.
17
+ verify_login_change_additional_form_tags :: HTML fragment containing additional form tags to use on the verify login change form.
18
+ verify_login_change_autologin? :: Whether to autologin the user after successful login change verification, false by default.
19
+ verify_login_change_button :: The text to use for the verify login change button.
20
+ verify_login_change_deadline_column :: The column name in the verify login change keys table storing the deadline after which the token will be ignored.
21
+ verify_login_change_deadline_interval :: The amount of time for which to allow users to verify login changes, 1 day by default.
22
+ verify_login_change_email_subject :: The subject to use for the verify login change email.
23
+ verify_login_change_error_flash :: The flash error to show if no matching key is submitted when verifying login change.
24
+ verify_login_change_id_column :: The id column in the verify login change keys table, should be a foreign key referencing the accounts table.
25
+ verify_login_change_key_column :: The verify login change key/token column in the verify login change keys table.
26
+ verify_login_change_key_param :: The parameter name to use for the verify login change key.
27
+ verify_login_change_login_column :: The login column in the verify login change keys table, containing the new login.
28
+ verify_login_change_notice_flash :: The flash notice to show after verifying the login change.
29
+ verify_login_change_redirect :: Where to redirect after verifying the login change.
30
+ verify_login_change_route :: The route to the verify login change action. Defaults to +verify-login-change+.
31
+ verify_login_change_session_key :: The key in the session to hold the verify login change key temporarily.
32
+ verify_login_change_table :: The name of the verify login change keys table.
33
+
34
+ == Auth Methods
35
+
36
+ account_from_verify_login_change_key(key) :: Retrieve the account using the given verify account key, or return nil if no account matches. Should also override verify_login_change_new_login if overriding this method.
37
+ after_verify_login_change :: Run arbitrary code after verifying the login change.
38
+ before_verify_login_change :: Run arbitrary code before verifying the login change.
39
+ before_verify_login_change_route :: Run arbitrary code before handling a verify login change route.
40
+ create_verify_login_change_email(login) :: A Mail::Message for the verify login change email.
41
+ create_verify_login_change_key(login) :: Add the verify login change key data to the database.
42
+ get_verify_login_change_login_and_key(id) :: Get the verify login change login and key for the given account id from the database.
43
+ remove_verify_login_change_key :: Remove the verify login change key for the current account, run after successful login change verification.
44
+ send_verify_login_change_email(login) :: Send the verify login change email.
45
+ verify_login_change :: Change the login for the given account to the new login.
46
+ verify_login_change_email_body :: The body to use for the verify login change email.
47
+ verify_login_change_email_link :: The link to the verify login change form in the verify login change email.
48
+ verify_login_change_key_insert_hash(login) :: The hash to insert into the verify login change keys table.
49
+ verify_login_change_key_value :: The value of the verify login change key.
50
+ verify_login_change_new_login :: The new login to use when the login change is verified.
51
+ verify_login_change_old_login :: The old login to display in the verify login change email.
52
+ verify_login_change_view :: The HTML to use for the verify login change form.
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- AccountExpiration = Feature.define(:account_expiration) do
4
+ Feature.define(:account_expiration, :AccountExpiration) do
5
5
  error_flash "You cannot log into this account as it has expired"
6
6
  redirect
7
7
  after
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- Base = Feature.define(:base) do
4
+ Feature.define(:base, :Base) do
5
5
  after 'login'
6
6
  after 'login_failure'
7
7
  before 'login'
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- ChangeLogin = Feature.define(:change_login) do
4
+ Feature.define(:change_login, :ChangeLogin) do
5
5
  depends :login_password_requirements_base
6
6
 
7
7
  notice_flash 'Your login has been changed'
@@ -63,11 +63,18 @@ module Rodauth
63
63
  end
64
64
 
65
65
  def change_login(login)
66
- updated = nil
67
66
  if account_ds.get(login_column).downcase == login.downcase
68
67
  @login_requirement_message = 'same as current login'
69
68
  return false
70
69
  end
70
+
71
+ update_login(login)
72
+ end
73
+
74
+ private
75
+
76
+ def update_login(login)
77
+ updated = nil
71
78
  raised = raises_uniqueness_violation?{updated = update_account({login_column=>login}, account_ds.exclude(login_column=>login)) == 1}
72
79
  if raised
73
80
  @login_requirement_message = 'already an account with this login'
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- ChangePassword = Feature.define(:change_password) do
4
+ Feature.define(:change_password, :ChangePassword) do
5
5
  depends :login_password_requirements_base
6
6
 
7
7
  notice_flash 'Your password has been changed'
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- CloseAccount = Feature.define(:close_account) do
4
+ Feature.define(:close_account, :CloseAccount) do
5
5
  notice_flash 'Your account has been closed'
6
6
  error_flash 'There was an error closing your account'
7
7
  loaded_templates %w'close-account password-field'
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- ConfirmPassword = Feature.define(:confirm_password) do
4
+ Feature.define(:confirm_password, :ConfirmPassword) do
5
5
  notice_flash "Your password has been confirmed"
6
6
  error_flash "There was an error confirming your password"
7
7
  loaded_templates %w'confirm-password password-field'
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- CreateAccount = Feature.define(:create_account) do
4
+ Feature.define(:create_account, :CreateAccount) do
5
5
  depends :login_password_requirements_base
6
6
 
7
7
  depends :login
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- DisallowPasswordReuse = Feature.define(:disallow_password_reuse) do
4
+ Feature.define(:disallow_password_reuse, :DisallowPasswordReuse) do
5
5
  depends :login_password_requirements_base
6
6
 
7
7
  auth_value_method :password_same_as_previous_password_message, "same as previous password"