rodauth 2.16.0 → 2.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +38 -0
- data/README.rdoc +6 -2
- data/doc/error_reasons.rdoc +3 -0
- data/doc/guides/change_table_and_column_names.rdoc +19 -0
- data/doc/guides/i18n.rdoc +3 -0
- data/doc/guides/share_configuration.rdoc +34 -0
- data/doc/login_password_requirements_base.rdoc +9 -3
- data/doc/release_notes/2.17.0.txt +10 -0
- data/doc/release_notes/2.18.0.txt +27 -0
- data/doc/release_notes/2.19.0.txt +61 -0
- data/doc/release_notes/2.20.0.txt +10 -0
- data/lib/rodauth/features/active_sessions.rb +1 -0
- data/lib/rodauth/features/argon2.rb +13 -1
- data/lib/rodauth/features/internal_request.rb +4 -8
- data/lib/rodauth/features/json.rb +19 -0
- data/lib/rodauth/features/jwt_refresh.rb +2 -2
- data/lib/rodauth/features/login_password_requirements_base.rb +33 -3
- data/lib/rodauth/features/otp.rb +1 -1
- data/lib/rodauth/features/verify_account.rb +2 -4
- data/lib/rodauth/features/webauthn.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- data/lib/rodauth.rb +44 -35
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 534a50718fe362e695a9fbd8043d1ce05ca211de2049b1351207bd5d11cbf962
|
4
|
+
data.tar.gz: 9afd5a7d79dde11005b090ca18591661c55c2647387a151b0d732ef97f51f633
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f10082d21fad4783ad6193dc7e1dfe55bc5f57c98b33e1b6f6583dbaa0e921f4d40025e935f93aef9706078232956bcde2fec4e8838b1c2ee4f49a8885c22520
|
7
|
+
data.tar.gz: 8ca004055be7ee660a37f2657d6752dbe2318b30100204e8eb68c514229422158db3f513a1d9e90eb532535bdbdf5854f66834212cc43fb81f8f9b8872221af5
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
+
=== 2.20.0 (2022-01-24)
|
2
|
+
|
3
|
+
* Change the default implementation of webauth_rp_id to not include the port (jeremyevans) (#203)
|
4
|
+
|
5
|
+
* Make logout of all sessions in active_sessions plugin also remove remember key if using remember plugin (jeremyevans)
|
6
|
+
|
7
|
+
=== 2.19.0 (2021-12-22)
|
8
|
+
|
9
|
+
* Add login_maximum_bytes, setting the maximum number of bytes in a login, 255 by default (jeremyevans)
|
10
|
+
|
11
|
+
* Add password_maximum_bytes, setting the maximum number of bytes in a password, nil by default for no limit (jeremyevans)
|
12
|
+
|
13
|
+
* Add password_maximum_length, setting the maximum number of characters in a password, nil by default for no limit (jeremyevans)
|
14
|
+
|
15
|
+
* Support multi-level inheritance of Rodauth::Auth (janko) (#191)
|
16
|
+
|
17
|
+
* Allow internal_request feature to work correctly when loaded into custom Rodauth::Auth subclasses before loading into a Roda application (janko) (#190)
|
18
|
+
|
19
|
+
* Assign internal subclass created by internal_request feature to the InternalRequest constant (janko) (#187)
|
20
|
+
|
21
|
+
=== 2.18.0 (2021-11-23)
|
22
|
+
|
23
|
+
* Allow JSON API access to /multifactor-manage to get links to setup/disable multifactor authentication endpoints (jeremyevans)
|
24
|
+
|
25
|
+
* Allow JSON API access to /multifactor-auth to get links to possible multifactor authentication endpoints (jeremyevans)
|
26
|
+
|
27
|
+
* Set configuration_name on class passed via :auth_class option if not already set (janko, jeremyevans) (#181)
|
28
|
+
|
29
|
+
* Use viewbox: true option when creating QR code in otp feature, displays better and easier to style when using rqrcode 2+ (jeremyevans)
|
30
|
+
|
31
|
+
* Make argon2 feature work with argon2 2.1.0 (jeremyevans)
|
32
|
+
|
33
|
+
=== 2.17.0 (2021-09-24)
|
34
|
+
|
35
|
+
* Make jwt_refresh work correctly with verify_account_grace_period (jeremyevans)
|
36
|
+
|
37
|
+
* Use 4xx status code when attempting to login to or create an unverified account (janko) (#177, #178)
|
38
|
+
|
1
39
|
=== 2.16.0 (2021-08-23)
|
2
40
|
|
3
41
|
* Add Rodauth.lib for using Rodauth as a library (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -69,7 +69,8 @@ Website :: http://rodauth.jeremyevans.net
|
|
69
69
|
Demo Site :: http://rodauth-demo.jeremyevans.net
|
70
70
|
Source :: http://github.com/jeremyevans/rodauth
|
71
71
|
Bugs :: http://github.com/jeremyevans/rodauth/issues
|
72
|
-
|
72
|
+
Discussion Forum (GitHub Discussions) :: https://github.com/jeremyevans/rodauth/discussions
|
73
|
+
Alternate Discussion Forum (Google Groups) :: https://groups.google.com/forum/#!forum/rodauth
|
73
74
|
|
74
75
|
== Dependencies
|
75
76
|
|
@@ -422,9 +423,12 @@ Note that these migrations require Sequel 4.35.0+.
|
|
422
423
|
if db.database_type == :postgres
|
423
424
|
citext :email, :null=>false
|
424
425
|
constraint :valid_email, :email=>/^[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+$/
|
425
|
-
index :email, :unique=>true, :where=>{:status_id=>[1, 2]}
|
426
426
|
else
|
427
427
|
String :email, :null=>false
|
428
|
+
end
|
429
|
+
if db.supports_partial_indexes?
|
430
|
+
index :email, :unique=>true, :where=>{:status_id=>[1, 2]}
|
431
|
+
else
|
428
432
|
index :email, :unique=>true
|
429
433
|
end
|
430
434
|
end
|
data/doc/error_reasons.rdoc
CHANGED
@@ -44,6 +44,7 @@ Rodauth will call +set_error_reason+ with:
|
|
44
44
|
* :login_not_valid_email
|
45
45
|
* :login_required
|
46
46
|
* :login_too_long
|
47
|
+
* :login_too_many_bytes
|
47
48
|
* :login_too_short
|
48
49
|
* :logins_do_not_match
|
49
50
|
* :no_current_sms_code
|
@@ -56,6 +57,8 @@ Rodauth will call +set_error_reason+ with:
|
|
56
57
|
* :password_in_dictionary
|
57
58
|
* :password_is_one_of_the_most_common
|
58
59
|
* :password_same_as_previous_password
|
60
|
+
* :password_too_long
|
61
|
+
* :password_too_many_bytes
|
59
62
|
* :password_too_short
|
60
63
|
* :passwords_do_not_match
|
61
64
|
* :same_as_current_login
|
@@ -0,0 +1,19 @@
|
|
1
|
+
= Change table and column names
|
2
|
+
|
3
|
+
All tables that Rodauth uses will have a configuration method that ends with
|
4
|
+
+_table+ for configuring the table name. For example, if you store user accounts
|
5
|
+
in the +users+ table instead of +accounts+ table, you can use the following
|
6
|
+
in your configuration:
|
7
|
+
|
8
|
+
accounts_table :users
|
9
|
+
|
10
|
+
All columns that Rodauth uses will have a configuration method that ends with
|
11
|
+
+_column+ for configuring the column name. For example, if you are storing the
|
12
|
+
login for accounts in the +login+ column instead of the +email+ column, you
|
13
|
+
can use the following in your configuration:
|
14
|
+
|
15
|
+
login_column :login
|
16
|
+
|
17
|
+
Please see the documentation for Rodauth features for the names of the
|
18
|
+
configuration methods that you can use. You can see the default values for
|
19
|
+
the tables and columns in the {"Creating tables" section of the README}[rdoc-ref:README.rdoc].
|
data/doc/guides/i18n.rdoc
CHANGED
@@ -24,3 +24,6 @@ Your translation file may then look something like this:
|
|
24
24
|
require_login_error_flash: "Login is required for accessing this page"
|
25
25
|
no_matching_login_message: "user with this email address doesn't exist"
|
26
26
|
reset_password_email_subject: "Password Reset Instructions"
|
27
|
+
|
28
|
+
Alternatively, you can use the
|
29
|
+
{rodauth-i18n}[https://github.com/janko/rodauth-i18n] gem.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
= Share configuration via inheritance
|
2
|
+
|
3
|
+
If you have multiple configurations that needs to share some amount of
|
4
|
+
authentication behaviour, you can do so through inheritance. For example:
|
5
|
+
|
6
|
+
require "rodauth"
|
7
|
+
|
8
|
+
class RodauthBase < Rodauth::Auth
|
9
|
+
configure do
|
10
|
+
# common authentication configuration
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class RodauthMain < RodauthBase # inherit common configuration
|
15
|
+
configure do
|
16
|
+
# main-specific authentication configuration
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class RodauthAdmin < RodauthBase # inherit common configuration
|
21
|
+
configure do
|
22
|
+
# admin-specific authentication configuration
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class RodauthApp < Roda
|
27
|
+
plugin :rodauth, auth_class: RodauthMain
|
28
|
+
plugin :rodauth, auth_class: RodauthAdmin, name: :admin
|
29
|
+
# ...
|
30
|
+
end
|
31
|
+
|
32
|
+
However, when doing this, you need to be careful that you do not use a
|
33
|
+
configuration method in a superclass, and then load a feature in a subclass
|
34
|
+
that overrides the configuration you set in the superclass.
|
@@ -11,17 +11,23 @@ login_confirm_label :: The label to use for login confirmations.
|
|
11
11
|
login_confirm_param :: The parameter name to use for login confirmations.
|
12
12
|
login_does_not_meet_requirements_message :: The error message to display when the login does not meet the requirements you have set.
|
13
13
|
login_email_regexp :: The regular expression used to validate whether login is a valid email address.
|
14
|
-
|
15
|
-
|
14
|
+
login_maximum_bytes :: The maximum length for logins in bytes, 255 by default.
|
15
|
+
login_maximum_length :: The maximum length for logins in characters, 255 by default.
|
16
|
+
login_minimum_length :: The minimum length for logins in characters, 3 by default.
|
16
17
|
login_not_valid_email_message :: The error message to display when login is not a valid email address.
|
17
18
|
login_too_long_message :: The error message fragment to show if the login is too long.
|
19
|
+
login_too_many_bytes_message :: The error message fragment to show if the login has too many bytes.
|
18
20
|
login_too_short_message :: The error message fragment to show if the login is too short.
|
19
21
|
logins_do_not_match_message :: The error message to display when login and login confirmation do not match.
|
20
22
|
password_confirm_label :: The label to use for password confirmations.
|
21
23
|
password_confirm_param :: The parameter name to use for password confirmations.
|
22
24
|
password_does_not_meet_requirements_message :: The error message to display when the password does not meet the requirements you have set.
|
23
25
|
password_hash_cost :: The cost to use for the password hash algorithm. This should be an integer when using bcrypt (the default), and a hash if using argon2 (supported by the argon2 feature).
|
24
|
-
|
26
|
+
password_maximum_bytes :: The maximum length for passwords in bytes, nil by default for no limit. bcrypt only uses the first 72 bytes of the password when creating the password hash, so if you are using bcrypt as the password hash function, you may want to set this to 72.
|
27
|
+
password_maximum_length :: The maximum length for passwords in characters, nil by default for no limit.
|
28
|
+
password_minimum_length :: The minimum length for passwords in characters, 6 by default.
|
29
|
+
password_too_long_message :: The error message fragment to show if the password is too long.
|
30
|
+
password_too_many_bytes_message :: The error message fragment to show if the password is has too many bytes.
|
25
31
|
password_too_short_message :: The error message fragment to show if the password is too short.
|
26
32
|
passwords_do_not_match_message :: The error message to display when password and password confirmation do not match.
|
27
33
|
require_email_address_logins? :: Whether logins need to be valid email addresses, true by default.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
= Improvements
|
2
|
+
|
3
|
+
* The jwt_refresh feature now works for unverified accounts when using
|
4
|
+
the verify_account_grace_period feature.
|
5
|
+
|
6
|
+
* When trying to create an account that already exists but is
|
7
|
+
unverified, Rodauth now returns a 4xx response.
|
8
|
+
|
9
|
+
* When trying to login to an unverified account, Rodauth now returns a
|
10
|
+
4xx response.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* When using the json and multifactor auth features, the JSON API can
|
4
|
+
now access the multifactor-manage route to get lists of endpoints
|
5
|
+
for setting up and disabling supported multifactor authentication
|
6
|
+
methods. The JSON API can now also access the multifactor-auth
|
7
|
+
route to get a list of endpoints for multifactor authentication for
|
8
|
+
the currently logged in account.
|
9
|
+
|
10
|
+
= Other Improvements
|
11
|
+
|
12
|
+
* In the otp feature, the viewbox: true rqrcode option is now used
|
13
|
+
when creating the QR code. This results in a QR code that is
|
14
|
+
displayed better and is easier to style. This option only has
|
15
|
+
an effect when using rqrcode 2+.
|
16
|
+
|
17
|
+
* When using the :auth_class option when loading the rodauth plugin,
|
18
|
+
the configuration name is set in the provided auth class, unless the
|
19
|
+
auth class already has a configuration name set.
|
20
|
+
|
21
|
+
* The example migration now recommends using a partial index on the
|
22
|
+
email column in cases where the database supports partial indexes.
|
23
|
+
Previously, it only recommended it on PostgreSQL.
|
24
|
+
|
25
|
+
* The argon2 feature now works with argon2 2.1.0. Older versions of
|
26
|
+
Rodauth work with both earlier and later versions of argon2, but
|
27
|
+
not 2.1.0.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A login_maximum_bytes configuration method has been added, setting
|
4
|
+
the maximum bytes allowed in a login. This was added as
|
5
|
+
login_maximum_length sets the maximum length in characters. It's
|
6
|
+
possible a different number of maximum bytes than maximum
|
7
|
+
characters is desired by some applications, and since the database
|
8
|
+
column size may be enforced in bytes, it's useful to have a check
|
9
|
+
before trying a database query that would raise an exception. This
|
10
|
+
default value for login_maximum_bytes is 255, the same as the
|
11
|
+
default value for login_maximum_length.
|
12
|
+
|
13
|
+
A login_too_many_bytes_message configuration method has been added
|
14
|
+
for customizing the error message if a login has too many bytes.
|
15
|
+
|
16
|
+
* password_maximum_length and password_maximum_bytes configuration
|
17
|
+
methods have been added, specifying the maximum size of passwords
|
18
|
+
in characters and bytes, respectively. Both configurations default
|
19
|
+
to nil, meaning no limit, so there is no change in default behavior.
|
20
|
+
|
21
|
+
The bcrypt algorithm only uses the first 72 bytes of a password, and
|
22
|
+
in some environments it may be desirable to reject passwords over
|
23
|
+
that limit. password_too_long_message and
|
24
|
+
password_too_many_bytes_message configuration methods have been
|
25
|
+
added for customizing the error messages used for passwords that are
|
26
|
+
too long.
|
27
|
+
|
28
|
+
Note that in most environments, if you want to support passwords
|
29
|
+
over 72 bytes and have the entire password be considered, you should
|
30
|
+
probably use the argon2 feature.
|
31
|
+
|
32
|
+
= Other Improvements
|
33
|
+
|
34
|
+
* The subclass created by the internal_request feature is now set
|
35
|
+
to the InternalRequest constant on the superclass, mostly to
|
36
|
+
make identifying it easier in inspect output.
|
37
|
+
|
38
|
+
* Support has been improved for custom Rodauth::Auth subclasses that
|
39
|
+
load features before the subclass is loaded into Roda, by delaying
|
40
|
+
the call to post_configure until the subclass is loaded into Roda.
|
41
|
+
Among other things, this fixes the use of the internal_request
|
42
|
+
feature in such classes.
|
43
|
+
|
44
|
+
* Multi-level inheritance of Rodauth::Auth is now supported. This can
|
45
|
+
be useful as a way to share custom authentication settings between
|
46
|
+
multiple Rodauth configurations. However, users of multi-level
|
47
|
+
inheritance should be careful not to load features in subclasses
|
48
|
+
that override custom settings in superclasses.
|
49
|
+
|
50
|
+
= Other
|
51
|
+
|
52
|
+
* Rodauth's primary discussion forum is now GitHub Discussions. The
|
53
|
+
rodauth Google Group is still available for users who would prefer
|
54
|
+
to use that instead.
|
55
|
+
|
56
|
+
= Backwards Compatibility
|
57
|
+
|
58
|
+
* The addition of login_maximum_bytes with a default value of 255 is
|
59
|
+
backwards incompatible for applications that want to support logins
|
60
|
+
with multibyte characters where the number of characters in the
|
61
|
+
login is at or below 255, but the number of bytes is above 255.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
= Improvements
|
2
|
+
|
3
|
+
* When using the active_sessions and remember features together,
|
4
|
+
doing a global logout will automatically remove the remember key for
|
5
|
+
the account, so the account will no longer be able to automatically
|
6
|
+
create new sessions using the remember key.
|
7
|
+
|
8
|
+
* The default value of webauthn_rp_id now removes the port from the
|
9
|
+
origin if it exists, since the WebAuthn spec does not allow ports
|
10
|
+
in the relying party identifier.
|
@@ -16,6 +16,18 @@ module Rodauth
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
+
if Argon2::VERSION != '2.1.0'
|
20
|
+
def argon2_salt_option
|
21
|
+
:salt_do_not_supply
|
22
|
+
end
|
23
|
+
# :nocov:
|
24
|
+
else
|
25
|
+
def argon2_salt_option
|
26
|
+
:salt_for_testing_purposes_only
|
27
|
+
end
|
28
|
+
# :nocov:
|
29
|
+
end
|
30
|
+
|
19
31
|
def password_hash_cost
|
20
32
|
return super unless use_argon2?
|
21
33
|
argon2_hash_cost
|
@@ -35,7 +47,7 @@ module Rodauth
|
|
35
47
|
return super unless argon2_hash_algorithm?(salt)
|
36
48
|
|
37
49
|
argon2_params = Hash[extract_password_hash_cost(salt)]
|
38
|
-
argon2_params[
|
50
|
+
argon2_params[argon2_salt_option] = Base64.decode64(salt.split('$').last)
|
39
51
|
::Argon2::Password.new(argon2_params).create(password)
|
40
52
|
end
|
41
53
|
|
@@ -339,14 +339,7 @@ module Rodauth
|
|
339
339
|
return if is_a?(InternalRequestMethods)
|
340
340
|
|
341
341
|
klass = self.class
|
342
|
-
internal_class = Class.new(klass)
|
343
|
-
@roda_class = klass.roda_class
|
344
|
-
@features = klass.features.clone
|
345
|
-
@routes = klass.routes.clone
|
346
|
-
@route_hash = klass.route_hash.clone
|
347
|
-
@configuration = klass.configuration.clone
|
348
|
-
@configuration.instance_variable_set(:@auth, self)
|
349
|
-
end
|
342
|
+
internal_class = Class.new(klass)
|
350
343
|
|
351
344
|
if blocks = klass.instance_variable_get(:@internal_request_configuration_blocks)
|
352
345
|
configuration = internal_class.configuration
|
@@ -366,6 +359,9 @@ module Rodauth
|
|
366
359
|
end
|
367
360
|
end
|
368
361
|
end
|
362
|
+
|
363
|
+
klass.const_set(:InternalRequest, internal_class)
|
364
|
+
klass.private_constant :InternalRequest
|
369
365
|
end
|
370
366
|
end
|
371
367
|
end
|
@@ -67,6 +67,25 @@ module Rodauth
|
|
67
67
|
|
68
68
|
private
|
69
69
|
|
70
|
+
def before_two_factor_manage_route
|
71
|
+
super if defined?(super)
|
72
|
+
if use_json?
|
73
|
+
json_response[:setup_links] = two_factor_setup_links.sort.map{|_,link| link}
|
74
|
+
json_response[:remove_links] = two_factor_remove_links.sort.map{|_,link| link}
|
75
|
+
json_response[json_response_success_key] ||= "" if include_success_messages?
|
76
|
+
return_json_response
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def before_two_factor_auth_route
|
81
|
+
super if defined?(super)
|
82
|
+
if use_json?
|
83
|
+
json_response[:auth_links] = two_factor_auth_links.sort.map{|_,link| link}
|
84
|
+
json_response[json_response_success_key] ||= "" if include_success_messages?
|
85
|
+
return_json_response
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
70
89
|
def before_view_recovery_codes
|
71
90
|
super if defined?(super)
|
72
91
|
if use_json?
|
@@ -98,7 +98,7 @@ module Rodauth
|
|
98
98
|
# JWT is invalid for other reasons. Make sure the expiration is the
|
99
99
|
# only reason the JWT isn't valid before treating this as an expired token.
|
100
100
|
JWT.decode(jwt_token, jwt_secret, true, Hash[jwt_decode_opts].merge!(:verify_expiration=>false, :algorithm=>jwt_algorithm))[0]
|
101
|
-
rescue
|
101
|
+
rescue
|
102
102
|
else
|
103
103
|
json_response[json_response_error_key] = expired_jwt_access_token_message
|
104
104
|
response.status ||= expired_jwt_access_token_status
|
@@ -120,7 +120,7 @@ module Rodauth
|
|
120
120
|
end
|
121
121
|
|
122
122
|
ds = account_ds(id)
|
123
|
-
ds = ds.where(
|
123
|
+
ds = ds.where(account_session_status_filter) unless skip_status_checks?
|
124
124
|
ds.first
|
125
125
|
end
|
126
126
|
|
@@ -7,10 +7,13 @@ module Rodauth
|
|
7
7
|
auth_value_method :login_email_regexp, /\A[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+\z/
|
8
8
|
auth_value_method :login_minimum_length, 3
|
9
9
|
auth_value_method :login_maximum_length, 255
|
10
|
+
auth_value_method :login_maximum_bytes, 255
|
10
11
|
translatable_method :login_not_valid_email_message, 'not a valid email address'
|
11
12
|
translatable_method :logins_do_not_match_message, 'logins do not match'
|
12
13
|
auth_value_method :password_confirm_param, 'password-confirm'
|
13
14
|
auth_value_method :password_minimum_length, 6
|
15
|
+
auth_value_method :password_maximum_bytes, nil
|
16
|
+
auth_value_method :password_maximum_length, nil
|
14
17
|
translatable_method :passwords_do_not_match_message, 'passwords do not match'
|
15
18
|
auth_value_method :require_email_address_logins?, true
|
16
19
|
auth_value_method :require_login_confirmation?, true
|
@@ -22,10 +25,13 @@ module Rodauth
|
|
22
25
|
:login_confirm_label,
|
23
26
|
:login_does_not_meet_requirements_message,
|
24
27
|
:login_too_long_message,
|
28
|
+
:login_too_many_bytes_message,
|
25
29
|
:login_too_short_message,
|
26
30
|
:password_confirm_label,
|
27
31
|
:password_does_not_meet_requirements_message,
|
28
32
|
:password_hash_cost,
|
33
|
+
:password_too_long_message,
|
34
|
+
:password_too_many_bytes_message,
|
29
35
|
:password_too_short_message
|
30
36
|
)
|
31
37
|
|
@@ -78,6 +84,14 @@ module Rodauth
|
|
78
84
|
"invalid password, does not meet requirements#{" (#{password_requirement_message})" if password_requirement_message}"
|
79
85
|
end
|
80
86
|
|
87
|
+
def password_too_long_message
|
88
|
+
"maximum #{password_maximum_length} characters"
|
89
|
+
end
|
90
|
+
|
91
|
+
def password_too_many_bytes_message
|
92
|
+
"maximum #{password_maximum_bytes} bytes"
|
93
|
+
end
|
94
|
+
|
81
95
|
def password_too_short_message
|
82
96
|
"minimum #{password_minimum_length} characters"
|
83
97
|
end
|
@@ -95,6 +109,10 @@ module Rodauth
|
|
95
109
|
"maximum #{login_maximum_length} characters"
|
96
110
|
end
|
97
111
|
|
112
|
+
def login_too_many_bytes_message
|
113
|
+
"maximum #{login_maximum_bytes} bytes"
|
114
|
+
end
|
115
|
+
|
98
116
|
def login_too_short_message
|
99
117
|
"minimum #{login_minimum_length} characters"
|
100
118
|
end
|
@@ -111,6 +129,9 @@ module Rodauth
|
|
111
129
|
elsif login_maximum_length < login.length
|
112
130
|
set_login_requirement_error_message(:login_too_long, login_too_long_message)
|
113
131
|
false
|
132
|
+
elsif login_maximum_bytes < login.bytesize
|
133
|
+
set_login_requirement_error_message(:login_too_many_bytes, login_too_many_bytes_message)
|
134
|
+
false
|
114
135
|
else
|
115
136
|
true
|
116
137
|
end
|
@@ -128,9 +149,18 @@ module Rodauth
|
|
128
149
|
end
|
129
150
|
|
130
151
|
def password_meets_length_requirements?(password)
|
131
|
-
|
132
|
-
|
133
|
-
|
152
|
+
if password_minimum_length > password.length
|
153
|
+
set_password_requirement_error_message(:password_too_short, password_too_short_message)
|
154
|
+
false
|
155
|
+
elsif password_maximum_length && password_maximum_length < password.length
|
156
|
+
set_password_requirement_error_message(:password_too_long, password_too_long_message)
|
157
|
+
false
|
158
|
+
elsif password_maximum_bytes && password_maximum_bytes < password.bytesize
|
159
|
+
set_password_requirement_error_message(:password_too_many_bytes, password_too_many_bytes_message)
|
160
|
+
false
|
161
|
+
else
|
162
|
+
true
|
163
|
+
end
|
134
164
|
end
|
135
165
|
|
136
166
|
def password_does_not_contain_null_byte?(password)
|
data/lib/rodauth/features/otp.rb
CHANGED
@@ -196,8 +196,7 @@ module Rodauth
|
|
196
196
|
|
197
197
|
def new_account(login)
|
198
198
|
if account_from_login(login) && allow_resending_verify_account_email?
|
199
|
-
|
200
|
-
set_error_reason :already_an_unverified_account_with_this_login
|
199
|
+
set_response_error_reason_status(:already_an_unverified_account_with_this_login, unopen_account_error_status)
|
201
200
|
set_error_flash attempt_to_create_unverified_account_error_flash
|
202
201
|
response.write resend_verify_account_view
|
203
202
|
request.halt
|
@@ -274,8 +273,7 @@ module Rodauth
|
|
274
273
|
|
275
274
|
def before_login_attempt
|
276
275
|
unless open_account?
|
277
|
-
|
278
|
-
set_error_reason :unverified_account
|
276
|
+
set_response_error_reason_status(:unverified_account, unopen_account_error_status)
|
279
277
|
set_error_flash attempt_to_login_to_unverified_account_error_flash
|
280
278
|
response.write resend_verify_account_view
|
281
279
|
request.halt
|
data/lib/rodauth/version.rb
CHANGED
data/lib/rodauth.rb
CHANGED
@@ -50,14 +50,16 @@ module Rodauth
|
|
50
50
|
else
|
51
51
|
json_opt != :only
|
52
52
|
end
|
53
|
-
auth_class = (app.opts[:rodauths] ||= {})[opts[:name]] ||= opts[:auth_class] || Class.new(Auth)
|
53
|
+
auth_class = (app.opts[:rodauths] ||= {})[opts[:name]] ||= opts[:auth_class] || Class.new(Auth)
|
54
54
|
if !auth_class.roda_class
|
55
55
|
auth_class.roda_class = app
|
56
56
|
elsif auth_class.roda_class != app
|
57
|
-
auth_class = app.opts[:rodauths][opts[:name]] = Class.new(auth_class)
|
57
|
+
auth_class = app.opts[:rodauths][opts[:name]] = Class.new(auth_class)
|
58
58
|
auth_class.roda_class = app
|
59
59
|
end
|
60
|
+
auth_class.class_eval{@configuration_name = opts[:name] unless defined?(@configuration_name)}
|
60
61
|
auth_class.configure(&block) if block
|
62
|
+
auth_class.allocate.post_configure if auth_class.method_defined?(:post_configure)
|
61
63
|
end
|
62
64
|
|
63
65
|
FEATURES = {}
|
@@ -270,38 +272,6 @@ module Rodauth
|
|
270
272
|
end
|
271
273
|
end
|
272
274
|
|
273
|
-
class Auth
|
274
|
-
class << self
|
275
|
-
attr_accessor :roda_class
|
276
|
-
attr_reader :features
|
277
|
-
attr_reader :routes
|
278
|
-
attr_accessor :route_hash
|
279
|
-
attr_reader :configuration_name
|
280
|
-
attr_reader :configuration
|
281
|
-
end
|
282
|
-
|
283
|
-
def self.inherited(subclass)
|
284
|
-
super
|
285
|
-
subclass.instance_exec do
|
286
|
-
@features = []
|
287
|
-
@routes = []
|
288
|
-
@route_hash = {}
|
289
|
-
@configuration = Configuration.new(self)
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def self.configure(&block)
|
294
|
-
@configuration.apply(&block)
|
295
|
-
end
|
296
|
-
|
297
|
-
def self.freeze
|
298
|
-
@features.freeze
|
299
|
-
@routes.freeze
|
300
|
-
@route_hash.freeze
|
301
|
-
super
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
275
|
class Configuration
|
306
276
|
attr_reader :auth
|
307
277
|
|
@@ -317,7 +287,6 @@ module Rodauth
|
|
317
287
|
def apply(&block)
|
318
288
|
load_feature(:base)
|
319
289
|
instance_exec(&block)
|
320
|
-
auth.allocate.post_configure
|
321
290
|
end
|
322
291
|
|
323
292
|
def enable(*features)
|
@@ -341,6 +310,46 @@ module Rodauth
|
|
341
310
|
end
|
342
311
|
end
|
343
312
|
|
313
|
+
class Auth
|
314
|
+
@features = []
|
315
|
+
@routes = []
|
316
|
+
@route_hash = {}
|
317
|
+
@configuration = Configuration.new(self)
|
318
|
+
|
319
|
+
class << self
|
320
|
+
attr_accessor :roda_class
|
321
|
+
attr_reader :features
|
322
|
+
attr_reader :routes
|
323
|
+
attr_accessor :route_hash
|
324
|
+
attr_reader :configuration_name
|
325
|
+
attr_reader :configuration
|
326
|
+
end
|
327
|
+
|
328
|
+
def self.inherited(subclass)
|
329
|
+
super
|
330
|
+
superclass = self
|
331
|
+
subclass.instance_exec do
|
332
|
+
@roda_class = superclass.roda_class
|
333
|
+
@features = superclass.features.clone
|
334
|
+
@routes = superclass.routes.clone
|
335
|
+
@route_hash = superclass.route_hash.clone
|
336
|
+
@configuration = superclass.configuration.clone
|
337
|
+
@configuration.instance_variable_set(:@auth, self)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def self.configure(&block)
|
342
|
+
@configuration.apply(&block)
|
343
|
+
end
|
344
|
+
|
345
|
+
def self.freeze
|
346
|
+
@features.freeze
|
347
|
+
@routes.freeze
|
348
|
+
@route_hash.freeze
|
349
|
+
super
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
344
353
|
module InstanceMethods
|
345
354
|
def rodauth(name=nil)
|
346
355
|
if name
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -330,7 +330,11 @@ extra_rdoc_files:
|
|
330
330
|
- doc/release_notes/2.14.0.txt
|
331
331
|
- doc/release_notes/2.15.0.txt
|
332
332
|
- doc/release_notes/2.16.0.txt
|
333
|
+
- doc/release_notes/2.17.0.txt
|
334
|
+
- doc/release_notes/2.18.0.txt
|
335
|
+
- doc/release_notes/2.19.0.txt
|
333
336
|
- doc/release_notes/2.2.0.txt
|
337
|
+
- doc/release_notes/2.20.0.txt
|
334
338
|
- doc/release_notes/2.3.0.txt
|
335
339
|
- doc/release_notes/2.4.0.txt
|
336
340
|
- doc/release_notes/2.5.0.txt
|
@@ -362,6 +366,7 @@ files:
|
|
362
366
|
- doc/guides/admin_activation.rdoc
|
363
367
|
- doc/guides/already_authenticated.rdoc
|
364
368
|
- doc/guides/alternative_login.rdoc
|
369
|
+
- doc/guides/change_table_and_column_names.rdoc
|
365
370
|
- doc/guides/create_account_programmatically.rdoc
|
366
371
|
- doc/guides/delay_password.rdoc
|
367
372
|
- doc/guides/email_only.rdoc
|
@@ -379,6 +384,7 @@ files:
|
|
379
384
|
- doc/guides/registration_field.rdoc
|
380
385
|
- doc/guides/require_mfa.rdoc
|
381
386
|
- doc/guides/reset_password_autologin.rdoc
|
387
|
+
- doc/guides/share_configuration.rdoc
|
382
388
|
- doc/guides/status_column.rdoc
|
383
389
|
- doc/guides/totp_or_recovery.rdoc
|
384
390
|
- doc/http_basic_auth.rdoc
|
@@ -431,7 +437,11 @@ files:
|
|
431
437
|
- doc/release_notes/2.14.0.txt
|
432
438
|
- doc/release_notes/2.15.0.txt
|
433
439
|
- doc/release_notes/2.16.0.txt
|
440
|
+
- doc/release_notes/2.17.0.txt
|
441
|
+
- doc/release_notes/2.18.0.txt
|
442
|
+
- doc/release_notes/2.19.0.txt
|
434
443
|
- doc/release_notes/2.2.0.txt
|
444
|
+
- doc/release_notes/2.20.0.txt
|
435
445
|
- doc/release_notes/2.3.0.txt
|
436
446
|
- doc/release_notes/2.4.0.txt
|
437
447
|
- doc/release_notes/2.5.0.txt
|
@@ -562,7 +572,7 @@ metadata:
|
|
562
572
|
bug_tracker_uri: https://github.com/jeremyevans/rodauth/issues
|
563
573
|
changelog_uri: http://rodauth.jeremyevans.net/rdoc/files/CHANGELOG.html
|
564
574
|
documentation_uri: http://rodauth.jeremyevans.net/documentation.html
|
565
|
-
mailing_list_uri: https://
|
575
|
+
mailing_list_uri: https://github.com/jeremyevans/rodauth/discussions
|
566
576
|
source_code_uri: https://github.com/jeremyevans/rodauth
|
567
577
|
post_install_message:
|
568
578
|
rdoc_options:
|
@@ -586,7 +596,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
586
596
|
- !ruby/object:Gem::Version
|
587
597
|
version: '0'
|
588
598
|
requirements: []
|
589
|
-
rubygems_version: 3.
|
599
|
+
rubygems_version: 3.3.3
|
590
600
|
signing_key:
|
591
601
|
specification_version: 4
|
592
602
|
summary: Authentication and Account Management Framework for Rack Applications
|