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
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"