rodauth 2.18.0 → 2.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +14 -0
- data/README.rdoc +2 -1
- data/doc/error_reasons.rdoc +3 -0
- data/doc/guides/change_table_and_column_names.rdoc +19 -0
- data/doc/guides/share_configuration.rdoc +34 -0
- data/doc/login_password_requirements_base.rdoc +9 -3
- data/doc/release_notes/2.19.0.txt +61 -0
- data/lib/rodauth/features/internal_request.rb +4 -8
- data/lib/rodauth/features/login_password_requirements_base.rb +33 -3
- data/lib/rodauth/version.rb +1 -1
- data/lib/rodauth.rb +41 -33
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0defa94cb0c58b317997853eda1775694a8b0bb89e3bb75f8de50af57a2223fe
|
4
|
+
data.tar.gz: 977738446cb7d8ac53a7edeab2587c07e7a9b9407d2584daa80fe6d47147f395
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e8833fc2ac01f3a917b8c267642b92472969531df33dc90dcae6e90d5b62befbf2f948ca75cafcd84353b4b9d629f1dec8d70e3e77cc2387cc0791cee551773
|
7
|
+
data.tar.gz: 03ff22811e9679b26f1dc83c676ca19145c762d26c216a9aafae816d3bad67cd39a68430fbd72c55f17e77117fbcd65690eb6d71f3b05f72860833a2205f2fe7
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
=== 2.19.0 (2021-12-22)
|
2
|
+
|
3
|
+
* Add login_maximum_bytes, setting the maximum number of bytes in a login, 255 by default (jeremyevans)
|
4
|
+
|
5
|
+
* Add password_maximum_bytes, setting the maximum number of bytes in a password, nil by default for no limit (jeremyevans)
|
6
|
+
|
7
|
+
* Add password_maximum_length, setting the maximum number of characters in a password, nil by default for no limit (jeremyevans)
|
8
|
+
|
9
|
+
* Support multi-level inheritance of Rodauth::Auth (janko) (#191)
|
10
|
+
|
11
|
+
* Allow internal_request feature to work correctly when loaded into custom Rodauth::Auth subclasses before loading into a Roda application (janko) (#190)
|
12
|
+
|
13
|
+
* Assign internal subclass created by internal_request feature to the InternalRequest constant (janko) (#187)
|
14
|
+
|
1
15
|
=== 2.18.0 (2021-11-23)
|
2
16
|
|
3
17
|
* Allow JSON API access to /multifactor-manage to get links to setup/disable multifactor authentication endpoints (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
|
|
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].
|
@@ -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,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.
|
@@ -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
|
@@ -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/version.rb
CHANGED
data/lib/rodauth.rb
CHANGED
@@ -59,6 +59,7 @@ module Rodauth
|
|
59
59
|
end
|
60
60
|
auth_class.class_eval{@configuration_name = opts[:name] unless defined?(@configuration_name)}
|
61
61
|
auth_class.configure(&block) if block
|
62
|
+
auth_class.allocate.post_configure if auth_class.method_defined?(:post_configure)
|
62
63
|
end
|
63
64
|
|
64
65
|
FEATURES = {}
|
@@ -271,38 +272,6 @@ module Rodauth
|
|
271
272
|
end
|
272
273
|
end
|
273
274
|
|
274
|
-
class Auth
|
275
|
-
class << self
|
276
|
-
attr_accessor :roda_class
|
277
|
-
attr_reader :features
|
278
|
-
attr_reader :routes
|
279
|
-
attr_accessor :route_hash
|
280
|
-
attr_reader :configuration_name
|
281
|
-
attr_reader :configuration
|
282
|
-
end
|
283
|
-
|
284
|
-
def self.inherited(subclass)
|
285
|
-
super
|
286
|
-
subclass.instance_exec do
|
287
|
-
@features = []
|
288
|
-
@routes = []
|
289
|
-
@route_hash = {}
|
290
|
-
@configuration = Configuration.new(self)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
def self.configure(&block)
|
295
|
-
@configuration.apply(&block)
|
296
|
-
end
|
297
|
-
|
298
|
-
def self.freeze
|
299
|
-
@features.freeze
|
300
|
-
@routes.freeze
|
301
|
-
@route_hash.freeze
|
302
|
-
super
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
275
|
class Configuration
|
307
276
|
attr_reader :auth
|
308
277
|
|
@@ -318,7 +287,6 @@ module Rodauth
|
|
318
287
|
def apply(&block)
|
319
288
|
load_feature(:base)
|
320
289
|
instance_exec(&block)
|
321
|
-
auth.allocate.post_configure
|
322
290
|
end
|
323
291
|
|
324
292
|
def enable(*features)
|
@@ -342,6 +310,46 @@ module Rodauth
|
|
342
310
|
end
|
343
311
|
end
|
344
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
|
+
|
345
353
|
module InstanceMethods
|
346
354
|
def rodauth(name=nil)
|
347
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.19.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: 2021-
|
11
|
+
date: 2021-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -332,6 +332,7 @@ extra_rdoc_files:
|
|
332
332
|
- doc/release_notes/2.16.0.txt
|
333
333
|
- doc/release_notes/2.17.0.txt
|
334
334
|
- doc/release_notes/2.18.0.txt
|
335
|
+
- doc/release_notes/2.19.0.txt
|
335
336
|
- doc/release_notes/2.2.0.txt
|
336
337
|
- doc/release_notes/2.3.0.txt
|
337
338
|
- doc/release_notes/2.4.0.txt
|
@@ -364,6 +365,7 @@ files:
|
|
364
365
|
- doc/guides/admin_activation.rdoc
|
365
366
|
- doc/guides/already_authenticated.rdoc
|
366
367
|
- doc/guides/alternative_login.rdoc
|
368
|
+
- doc/guides/change_table_and_column_names.rdoc
|
367
369
|
- doc/guides/create_account_programmatically.rdoc
|
368
370
|
- doc/guides/delay_password.rdoc
|
369
371
|
- doc/guides/email_only.rdoc
|
@@ -381,6 +383,7 @@ files:
|
|
381
383
|
- doc/guides/registration_field.rdoc
|
382
384
|
- doc/guides/require_mfa.rdoc
|
383
385
|
- doc/guides/reset_password_autologin.rdoc
|
386
|
+
- doc/guides/share_configuration.rdoc
|
384
387
|
- doc/guides/status_column.rdoc
|
385
388
|
- doc/guides/totp_or_recovery.rdoc
|
386
389
|
- doc/http_basic_auth.rdoc
|
@@ -435,6 +438,7 @@ files:
|
|
435
438
|
- doc/release_notes/2.16.0.txt
|
436
439
|
- doc/release_notes/2.17.0.txt
|
437
440
|
- doc/release_notes/2.18.0.txt
|
441
|
+
- doc/release_notes/2.19.0.txt
|
438
442
|
- doc/release_notes/2.2.0.txt
|
439
443
|
- doc/release_notes/2.3.0.txt
|
440
444
|
- doc/release_notes/2.4.0.txt
|
@@ -566,7 +570,7 @@ metadata:
|
|
566
570
|
bug_tracker_uri: https://github.com/jeremyevans/rodauth/issues
|
567
571
|
changelog_uri: http://rodauth.jeremyevans.net/rdoc/files/CHANGELOG.html
|
568
572
|
documentation_uri: http://rodauth.jeremyevans.net/documentation.html
|
569
|
-
mailing_list_uri: https://
|
573
|
+
mailing_list_uri: https://github.com/jeremyevans/rodauth/discussions
|
570
574
|
source_code_uri: https://github.com/jeremyevans/rodauth
|
571
575
|
post_install_message:
|
572
576
|
rdoc_options:
|
@@ -590,7 +594,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
590
594
|
- !ruby/object:Gem::Version
|
591
595
|
version: '0'
|
592
596
|
requirements: []
|
593
|
-
rubygems_version: 3.2.
|
597
|
+
rubygems_version: 3.2.32
|
594
598
|
signing_key:
|
595
599
|
specification_version: 4
|
596
600
|
summary: Authentication and Account Management Framework for Rack Applications
|