authlogic 5.2.0 → 6.4.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.
- checksums.yaml +4 -4
- data/lib/authlogic.rb +1 -0
- data/lib/authlogic/acts_as_authentic/base.rb +16 -1
- data/lib/authlogic/acts_as_authentic/password.rb +15 -5
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +5 -3
- data/lib/authlogic/controller_adapters/rails_adapter.rb +1 -1
- data/lib/authlogic/crypto_providers/md5.rb +3 -0
- data/lib/authlogic/crypto_providers/md5/v2.rb +35 -0
- data/lib/authlogic/crypto_providers/sha1.rb +3 -0
- data/lib/authlogic/crypto_providers/sha1/v2.rb +41 -0
- data/lib/authlogic/crypto_providers/sha256.rb +3 -0
- data/lib/authlogic/crypto_providers/sha256/v2.rb +58 -0
- data/lib/authlogic/crypto_providers/sha512.rb +3 -0
- data/lib/authlogic/crypto_providers/sha512/v2.rb +39 -0
- data/lib/authlogic/errors.rb +50 -0
- data/lib/authlogic/i18n/translator.rb +1 -1
- data/lib/authlogic/session/base.rb +142 -82
- data/lib/authlogic/test_case.rb +1 -0
- data/lib/authlogic/test_case/mock_api_controller.rb +52 -0
- data/lib/authlogic/test_case/mock_controller.rb +1 -1
- data/lib/authlogic/test_case/mock_cookie_jar.rb +25 -6
- data/lib/authlogic/test_case/mock_request.rb +4 -0
- data/lib/authlogic/test_case/rails_request_adapter.rb +7 -1
- data/lib/authlogic/version.rb +1 -1
- metadata +53 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa943f509bfe67c9cd576f8201f0fce5f0dd8c417458a629185590257a34f0af
|
4
|
+
data.tar.gz: 01bb91b140d913dc7c75c1c78d70b70ae23ea3254c01c8165a2c29e785a00a9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: efb0ecbdb2a535817297ccbb3d687b25387353a02aaa7ee5d0d05a1cc629adc5e52d81edb7a166ef74f071cf9e584bd4a3f994690f4a82e60c7f54fc9a1df880
|
7
|
+
data.tar.gz: 85de14bc97e1e3eecb6f77b346d7953e1f64504c9e91373167555dbb9e352b59cc61a85933135d6b358b049a0b482268f630e9ea6aed1fb341554dd6b7ab6feb
|
data/lib/authlogic.rb
CHANGED
@@ -31,8 +31,8 @@ module Authlogic
|
|
31
31
|
#
|
32
32
|
# See the various sub modules for the configuration they provide.
|
33
33
|
def acts_as_authentic
|
34
|
-
return unless db_setup?
|
35
34
|
yield self if block_given?
|
35
|
+
return unless db_setup?
|
36
36
|
acts_as_authentic_modules.each { |mod| include mod }
|
37
37
|
end
|
38
38
|
|
@@ -65,12 +65,27 @@ module Authlogic
|
|
65
65
|
self.acts_as_authentic_modules = modules
|
66
66
|
end
|
67
67
|
|
68
|
+
# Some Authlogic modules requires a database connection with a existing
|
69
|
+
# users table by the moment when you call the `acts_as_authentic`
|
70
|
+
# method. If you try to call `acts_as_authentic` without a database
|
71
|
+
# connection, it will raise a `Authlogic::ModelSetupError`.
|
72
|
+
#
|
73
|
+
# If you rely on the User model before the database is setup correctly,
|
74
|
+
# set this field to false.
|
75
|
+
# * <tt>Default:</tt> false
|
76
|
+
# * <tt>Accepts:</tt> Boolean
|
77
|
+
def raise_on_model_setup_error(value = nil)
|
78
|
+
rw_config(:raise_on_model_setup_error, value, false)
|
79
|
+
end
|
80
|
+
alias raise_on_model_setup_error= raise_on_model_setup_error
|
81
|
+
|
68
82
|
private
|
69
83
|
|
70
84
|
def db_setup?
|
71
85
|
column_names
|
72
86
|
true
|
73
87
|
rescue StandardError
|
88
|
+
raise ModelSetupError if raise_on_model_setup_error
|
74
89
|
false
|
75
90
|
end
|
76
91
|
|
@@ -102,20 +102,30 @@ module Authlogic
|
|
102
102
|
# The family of adaptive hash functions (BCrypt, SCrypt, PBKDF2) is the
|
103
103
|
# best choice for password storage today. We recommend SCrypt. Other
|
104
104
|
# one-way functions like SHA512 are inferior, but widely used.
|
105
|
-
#
|
105
|
+
# Reversible functions like AES256 are the worst choice, and we no
|
106
106
|
# longer support them.
|
107
107
|
#
|
108
108
|
# You can use the `transition_from_crypto_providers` option to gradually
|
109
109
|
# transition to a better crypto provider without causing your users any
|
110
110
|
# pain.
|
111
111
|
#
|
112
|
-
# * <tt>Default:</tt>
|
112
|
+
# * <tt>Default:</tt> There is no longer a default value. Prior to
|
113
|
+
# Authlogic 6, the default was `CryptoProviders::SCrypt`. If you try
|
114
|
+
# to read this config option before setting it, it will raise a
|
115
|
+
# `NilCryptoProvider` error. See that error's message for further
|
116
|
+
# details, and rationale for this change.
|
113
117
|
# * <tt>Accepts:</tt> Class
|
114
|
-
def crypto_provider
|
118
|
+
def crypto_provider
|
119
|
+
acts_as_authentic_config[:crypto_provider].tap { |provider|
|
120
|
+
raise NilCryptoProvider if provider.nil?
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
def crypto_provider=(value)
|
125
|
+
raise NilCryptoProvider if value.nil?
|
115
126
|
CryptoProviders::Guidance.new(value).impart_wisdom
|
116
|
-
rw_config(:crypto_provider, value
|
127
|
+
rw_config(:crypto_provider, value)
|
117
128
|
end
|
118
|
-
alias crypto_provider= crypto_provider
|
119
129
|
|
120
130
|
# Let's say you originally encrypted your passwords with Sha1. Sha1 is
|
121
131
|
# starting to join the party with MD5 and you want to switch to
|
@@ -93,9 +93,9 @@ module Authlogic
|
|
93
93
|
end
|
94
94
|
|
95
95
|
# Save the record and skip session maintenance all together.
|
96
|
-
def save_without_session_maintenance(
|
96
|
+
def save_without_session_maintenance(**options)
|
97
97
|
self.skip_session_maintenance = true
|
98
|
-
result = save(
|
98
|
+
result = save(**options)
|
99
99
|
self.skip_session_maintenance = false
|
100
100
|
result
|
101
101
|
end
|
@@ -176,7 +176,9 @@ module Authlogic
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def log_in_after_password_change?
|
179
|
-
|
179
|
+
persisted? &&
|
180
|
+
will_save_change_to_persistence_token? &&
|
181
|
+
self.class.log_in_after_password_change
|
180
182
|
end
|
181
183
|
end
|
182
184
|
end
|
@@ -14,7 +14,7 @@ module Authlogic
|
|
14
14
|
# Returns a `ActionDispatch::Cookies::CookieJar`. See the AC guide
|
15
15
|
# http://guides.rubyonrails.org/action_controller_overview.html#cookies
|
16
16
|
def cookies
|
17
|
-
controller.send(:cookies)
|
17
|
+
controller.respond_to?(:cookies, true) ? controller.send(:cookies) : nil
|
18
18
|
end
|
19
19
|
|
20
20
|
def cookie_domain
|
@@ -6,6 +6,9 @@ module Authlogic
|
|
6
6
|
module CryptoProviders
|
7
7
|
# A poor choice. There are known attacks against this algorithm.
|
8
8
|
class MD5
|
9
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
10
|
+
autoload :V2, File.join(__dir__, "md5", "v2")
|
11
|
+
|
9
12
|
class << self
|
10
13
|
attr_accessor :join_token
|
11
14
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/md5"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
module CryptoProviders
|
7
|
+
class MD5
|
8
|
+
# A poor choice. There are known attacks against this algorithm.
|
9
|
+
class V2
|
10
|
+
class << self
|
11
|
+
attr_accessor :join_token
|
12
|
+
|
13
|
+
# The number of times to loop through the encryption.
|
14
|
+
def stretches
|
15
|
+
@stretches ||= 1
|
16
|
+
end
|
17
|
+
attr_writer :stretches
|
18
|
+
|
19
|
+
# Turns your raw password into a MD5 hash.
|
20
|
+
def encrypt(*tokens)
|
21
|
+
digest = tokens.flatten.join(join_token)
|
22
|
+
stretches.times { digest = Digest::MD5.digest(digest) }
|
23
|
+
digest.unpack1("H*")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
27
|
+
# were used to encrypt.
|
28
|
+
def matches?(crypted, *tokens)
|
29
|
+
encrypt(*tokens) == crypted
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -6,6 +6,9 @@ module Authlogic
|
|
6
6
|
module CryptoProviders
|
7
7
|
# A poor choice. There are known attacks against this algorithm.
|
8
8
|
class Sha1
|
9
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
10
|
+
autoload :V2, File.join(__dir__, "sha1", "v2")
|
11
|
+
|
9
12
|
class << self
|
10
13
|
def join_token
|
11
14
|
@join_token ||= "--"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/sha1"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
module CryptoProviders
|
7
|
+
class Sha1
|
8
|
+
# A poor choice. There are known attacks against this algorithm.
|
9
|
+
class V2
|
10
|
+
class << self
|
11
|
+
def join_token
|
12
|
+
@join_token ||= "--"
|
13
|
+
end
|
14
|
+
attr_writer :join_token
|
15
|
+
|
16
|
+
# The number of times to loop through the encryption.
|
17
|
+
def stretches
|
18
|
+
@stretches ||= 10
|
19
|
+
end
|
20
|
+
attr_writer :stretches
|
21
|
+
|
22
|
+
# Turns your raw password into a Sha1 hash.
|
23
|
+
def encrypt(*tokens)
|
24
|
+
tokens = tokens.flatten
|
25
|
+
digest = tokens.shift
|
26
|
+
stretches.times do
|
27
|
+
digest = Digest::SHA1.digest([digest, *tokens].join(join_token))
|
28
|
+
end
|
29
|
+
digest.unpack1("H*")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
33
|
+
# were used to encrypt.
|
34
|
+
def matches?(crypted, *tokens)
|
35
|
+
encrypt(*tokens) == crypted
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -29,6 +29,9 @@ module Authlogic
|
|
29
29
|
#
|
30
30
|
# Uses the Sha256 hash algorithm to encrypt passwords.
|
31
31
|
class Sha256
|
32
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
33
|
+
autoload :V2, File.join(__dir__, "sha256", "v2")
|
34
|
+
|
32
35
|
class << self
|
33
36
|
attr_accessor :join_token
|
34
37
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/sha2"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
# The acts_as_authentic method has a crypto_provider option. This allows you
|
7
|
+
# to use any type of encryption you like. Just create a class with a class
|
8
|
+
# level encrypt and matches? method. See example below.
|
9
|
+
#
|
10
|
+
# === Example
|
11
|
+
#
|
12
|
+
# class MyAwesomeEncryptionMethod
|
13
|
+
# def self.encrypt(*tokens)
|
14
|
+
# # the tokens passed will be an array of objects, what type of object
|
15
|
+
# # is irrelevant, just do what you need to do with them and return a
|
16
|
+
# # single encrypted string. for example, you will most likely join all
|
17
|
+
# # of the objects into a single string and then encrypt that string
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def self.matches?(crypted, *tokens)
|
21
|
+
# # return true if the crypted string matches the tokens. Depending on
|
22
|
+
# # your algorithm you might decrypt the string then compare it to the
|
23
|
+
# # token, or you might encrypt the tokens and make sure it matches the
|
24
|
+
# # crypted string, its up to you.
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
module CryptoProviders
|
28
|
+
class Sha256
|
29
|
+
# = Sha256
|
30
|
+
#
|
31
|
+
# Uses the Sha256 hash algorithm to encrypt passwords.
|
32
|
+
class V2
|
33
|
+
class << self
|
34
|
+
attr_accessor :join_token
|
35
|
+
|
36
|
+
# The number of times to loop through the encryption.
|
37
|
+
def stretches
|
38
|
+
@stretches ||= 20
|
39
|
+
end
|
40
|
+
attr_writer :stretches
|
41
|
+
|
42
|
+
# Turns your raw password into a Sha256 hash.
|
43
|
+
def encrypt(*tokens)
|
44
|
+
digest = tokens.flatten.join(join_token)
|
45
|
+
stretches.times { digest = Digest::SHA256.digest(digest) }
|
46
|
+
digest.unpack1("H*")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
50
|
+
# were used to encrypt.
|
51
|
+
def matches?(crypted, *tokens)
|
52
|
+
encrypt(*tokens) == crypted
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -8,6 +8,9 @@ module Authlogic
|
|
8
8
|
# there are better choices. We recommend transitioning to a more secure,
|
9
9
|
# adaptive hashing algorithm, like scrypt.
|
10
10
|
class Sha512
|
11
|
+
# V2 hashes the digest bytes in repeated stretches instead of hex characters.
|
12
|
+
autoload :V2, File.join(__dir__, "sha512", "v2")
|
13
|
+
|
11
14
|
class << self
|
12
15
|
attr_accessor :join_token
|
13
16
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest/sha2"
|
4
|
+
|
5
|
+
module Authlogic
|
6
|
+
module CryptoProviders
|
7
|
+
class Sha512
|
8
|
+
# SHA-512 does not have any practical known attacks against it. However,
|
9
|
+
# there are better choices. We recommend transitioning to a more secure,
|
10
|
+
# adaptive hashing algorithm, like scrypt.
|
11
|
+
class V2
|
12
|
+
class << self
|
13
|
+
attr_accessor :join_token
|
14
|
+
|
15
|
+
# The number of times to loop through the encryption.
|
16
|
+
def stretches
|
17
|
+
@stretches ||= 20
|
18
|
+
end
|
19
|
+
attr_writer :stretches
|
20
|
+
|
21
|
+
# Turns your raw password into a Sha512 hash.
|
22
|
+
def encrypt(*tokens)
|
23
|
+
digest = tokens.flatten.join(join_token)
|
24
|
+
stretches.times do
|
25
|
+
digest = Digest::SHA512.digest(digest)
|
26
|
+
end
|
27
|
+
digest.unpack1("H*")
|
28
|
+
end
|
29
|
+
|
30
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
31
|
+
# were used to encrypt.
|
32
|
+
def matches?(crypted, *tokens)
|
33
|
+
encrypt(*tokens) == crypted
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authlogic
|
4
|
+
# Parent class of all Authlogic errors.
|
5
|
+
class Error < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
# :nodoc:
|
9
|
+
class InvalidCryptoProvider < Error
|
10
|
+
end
|
11
|
+
|
12
|
+
# :nodoc:
|
13
|
+
class NilCryptoProvider < InvalidCryptoProvider
|
14
|
+
def message
|
15
|
+
<<~EOS
|
16
|
+
In version 5, Authlogic used SCrypt by default. As of version 6, there
|
17
|
+
is no default. We still recommend SCrypt. If you previously relied on
|
18
|
+
this default, then, in your User model (or equivalent), please set the
|
19
|
+
following:
|
20
|
+
|
21
|
+
acts_as_authentic do |c|
|
22
|
+
c.crypto_provider = ::Authlogic::CryptoProviders::SCrypt
|
23
|
+
end
|
24
|
+
|
25
|
+
Furthermore, the authlogic gem no longer depends on the scrypt gem. In
|
26
|
+
your Gemfile, please add scrypt.
|
27
|
+
|
28
|
+
gem "scrypt", "~> 3.0"
|
29
|
+
|
30
|
+
We have made this change in Authlogic 6 so that users of other crypto
|
31
|
+
providers no longer need to install the scrypt gem.
|
32
|
+
EOS
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# :nodoc:
|
37
|
+
class ModelSetupError < Error
|
38
|
+
def message
|
39
|
+
<<-EOS
|
40
|
+
You must establish a database connection and run the migrations before
|
41
|
+
using acts_as_authentic. If you need to load the User model before the
|
42
|
+
database is set up correctly, please set the following:
|
43
|
+
|
44
|
+
acts_as_authentic do |c|
|
45
|
+
c.raise_on_model_setup_error = false
|
46
|
+
end
|
47
|
+
EOS
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -198,7 +198,7 @@ module Authlogic
|
|
198
198
|
# 2. Enable logging out on timeouts
|
199
199
|
#
|
200
200
|
# class UserSession < Authlogic::Session::Base
|
201
|
-
# logout_on_timeout true # default
|
201
|
+
# logout_on_timeout true # default is false
|
202
202
|
# end
|
203
203
|
#
|
204
204
|
# This will require a user to log back in if they are inactive for more than
|
@@ -351,6 +351,13 @@ module Authlogic
|
|
351
351
|
- https://github.com/binarylogic/authlogic/pull/558
|
352
352
|
- https://github.com/binarylogic/authlogic/pull/577
|
353
353
|
EOS
|
354
|
+
E_DPR_FIND_BY_LOGIN_METHOD = <<~EOS.squish.freeze
|
355
|
+
find_by_login_method is deprecated in favor of record_selection_method,
|
356
|
+
to avoid confusion with ActiveRecord's "Dynamic Finders".
|
357
|
+
(https://guides.rubyonrails.org/v6.0/active_record_querying.html#dynamic-finders)
|
358
|
+
For example, rubocop-rails is confused by the deprecated method.
|
359
|
+
(https://github.com/rubocop-hq/rubocop-rails/blob/master/lib/rubocop/cop/rails/dynamic_find_by.rb)
|
360
|
+
EOS
|
354
361
|
VALID_SAME_SITE_VALUES = [nil, "Lax", "Strict", "None"].freeze
|
355
362
|
|
356
363
|
# Callbacks
|
@@ -415,10 +422,10 @@ module Authlogic
|
|
415
422
|
before_save :set_last_request_at
|
416
423
|
|
417
424
|
after_save :reset_perishable_token!
|
418
|
-
after_save :save_cookie
|
425
|
+
after_save :save_cookie, if: :cookie_enabled?
|
419
426
|
after_save :update_session
|
420
427
|
|
421
|
-
after_destroy :destroy_cookie
|
428
|
+
after_destroy :destroy_cookie, if: :cookie_enabled?
|
422
429
|
after_destroy :update_session
|
423
430
|
|
424
431
|
# `validate` callbacks, in deliberate order. For example,
|
@@ -438,8 +445,7 @@ module Authlogic
|
|
438
445
|
|
439
446
|
class << self
|
440
447
|
attr_accessor(
|
441
|
-
:configured_password_methods
|
442
|
-
:configured_klass_methods
|
448
|
+
:configured_password_methods
|
443
449
|
)
|
444
450
|
end
|
445
451
|
attr_accessor(
|
@@ -472,14 +478,9 @@ module Authlogic
|
|
472
478
|
!controller.nil?
|
473
479
|
end
|
474
480
|
|
475
|
-
#
|
476
|
-
#
|
477
|
-
# I recommend keeping this enabled. The only time I feel this should be
|
478
|
-
# disabled is if you are not comfortable having your users provide their
|
479
|
-
# raw username and password. Whatever the reason, you can disable it
|
480
|
-
# here.
|
481
|
+
# Allow users to log in via HTTP basic authentication.
|
481
482
|
#
|
482
|
-
# * <tt>Default:</tt>
|
483
|
+
# * <tt>Default:</tt> false
|
483
484
|
# * <tt>Accepts:</tt> Boolean
|
484
485
|
def allow_http_basic_auth(value = nil)
|
485
486
|
rw_config(:allow_http_basic_auth, value, false)
|
@@ -669,35 +670,10 @@ module Authlogic
|
|
669
670
|
end
|
670
671
|
end
|
671
672
|
|
672
|
-
#
|
673
|
-
# validation is actually finding the user and making sure it exists.
|
674
|
-
# What method it uses the do this is up to you.
|
675
|
-
#
|
676
|
-
# Let's say you have a UserSession that is authenticating a User. By
|
677
|
-
# default UserSession will call User.find_by_login(login). You can
|
678
|
-
# change what method UserSession calls by specifying it here. Then in
|
679
|
-
# your User model you can make that method do anything you want, giving
|
680
|
-
# you complete control of how users are found by the UserSession.
|
681
|
-
#
|
682
|
-
# Let's take an example: You want to allow users to login by username or
|
683
|
-
# email. Set this to the name of the class method that does this in the
|
684
|
-
# User model. Let's call it "find_by_username_or_email"
|
685
|
-
#
|
686
|
-
# class User < ActiveRecord::Base
|
687
|
-
# def self.find_by_username_or_email(login)
|
688
|
-
# find_by_username(login) || find_by_email(login)
|
689
|
-
# end
|
690
|
-
# end
|
691
|
-
#
|
692
|
-
# Now just specify the name of this method for this configuration option
|
693
|
-
# and you are all set. You can do anything you want here. Maybe you
|
694
|
-
# allow users to have multiple logins and you want to search a has_many
|
695
|
-
# relationship, etc. The sky is the limit.
|
696
|
-
#
|
697
|
-
# * <tt>Default:</tt> "find_by_smart_case_login_field"
|
698
|
-
# * <tt>Accepts:</tt> Symbol or String
|
673
|
+
# @deprecated in favor of record_selection_method
|
699
674
|
def find_by_login_method(value = nil)
|
700
|
-
|
675
|
+
::ActiveSupport::Deprecation.warn(E_DPR_FIND_BY_LOGIN_METHOD)
|
676
|
+
record_selection_method(value)
|
701
677
|
end
|
702
678
|
alias find_by_login_method= find_by_login_method
|
703
679
|
|
@@ -782,15 +758,23 @@ module Authlogic
|
|
782
758
|
# example, the UserSession class will authenticate with the User class
|
783
759
|
# unless you specify otherwise in your configuration. See
|
784
760
|
# authenticate_with for information on how to change this value.
|
761
|
+
#
|
762
|
+
# @api public
|
785
763
|
def klass
|
786
764
|
@klass ||= klass_name ? klass_name.constantize : nil
|
787
765
|
end
|
788
766
|
|
789
|
-
# The
|
767
|
+
# The model name, guessed from the session class name, e.g. "User",
|
768
|
+
# from "UserSession".
|
769
|
+
#
|
770
|
+
# TODO: This method can return nil. We should explore this. It seems
|
771
|
+
# likely to cause a NoMethodError later, so perhaps we should raise an
|
772
|
+
# error instead.
|
773
|
+
#
|
774
|
+
# @api private
|
790
775
|
def klass_name
|
791
|
-
return @klass_name if
|
792
|
-
@klass_name = name.scan(/(.*)Session/)[0]
|
793
|
-
@klass_name = klass_name ? klass_name[0] : nil
|
776
|
+
return @klass_name if instance_variable_defined?(:@klass_name)
|
777
|
+
@klass_name = name.scan(/(.*)Session/)[0]&.first
|
794
778
|
end
|
795
779
|
|
796
780
|
# The name of the method you want Authlogic to create for storing the
|
@@ -798,8 +782,8 @@ module Authlogic
|
|
798
782
|
# Authlogic::Session, if you want it can be something completely
|
799
783
|
# different than the field in your model. So if you wanted people to
|
800
784
|
# login with a field called "login" and then find users by email this is
|
801
|
-
# completely doable. See the
|
802
|
-
# for
|
785
|
+
# completely doable. See the `record_selection_method` configuration
|
786
|
+
# option for details.
|
803
787
|
#
|
804
788
|
# * <tt>Default:</tt> klass.login_field || klass.email_field
|
805
789
|
# * <tt>Accepts:</tt> Symbol or String
|
@@ -882,6 +866,47 @@ module Authlogic
|
|
882
866
|
end
|
883
867
|
alias password_field= password_field
|
884
868
|
|
869
|
+
# Authlogic tries to validate the credentials passed to it. One part of
|
870
|
+
# validation is actually finding the user and making sure it exists.
|
871
|
+
# What method it uses the do this is up to you.
|
872
|
+
#
|
873
|
+
# ```
|
874
|
+
# # user_session.rb
|
875
|
+
# record_selection_method :find_by_email
|
876
|
+
# ```
|
877
|
+
#
|
878
|
+
# This is the recommended way to find the user by email address.
|
879
|
+
# The resulting query will be `User.find_by_email(send(login_field))`.
|
880
|
+
# (`login_field` will fall back to `email_field` if there's no `login`
|
881
|
+
# or `username` column).
|
882
|
+
#
|
883
|
+
# In your User model you can make that method do anything you want,
|
884
|
+
# giving you complete control of how users are found by the UserSession.
|
885
|
+
#
|
886
|
+
# Let's take an example: You want to allow users to login by username or
|
887
|
+
# email. Set this to the name of the class method that does this in the
|
888
|
+
# User model. Let's call it "find_by_username_or_email"
|
889
|
+
#
|
890
|
+
# ```
|
891
|
+
# class User < ActiveRecord::Base
|
892
|
+
# def self.find_by_username_or_email(login)
|
893
|
+
# find_by_username(login) || find_by_email(login)
|
894
|
+
# end
|
895
|
+
# end
|
896
|
+
# ```
|
897
|
+
#
|
898
|
+
# Now just specify the name of this method for this configuration option
|
899
|
+
# and you are all set. You can do anything you want here. Maybe you
|
900
|
+
# allow users to have multiple logins and you want to search a has_many
|
901
|
+
# relationship, etc. The sky is the limit.
|
902
|
+
#
|
903
|
+
# * <tt>Default:</tt> "find_by_smart_case_login_field"
|
904
|
+
# * <tt>Accepts:</tt> Symbol or String
|
905
|
+
def record_selection_method(value = nil)
|
906
|
+
rw_config(:record_selection_method, value, "find_by_smart_case_login_field")
|
907
|
+
end
|
908
|
+
alias record_selection_method= record_selection_method
|
909
|
+
|
885
910
|
# Whether or not to request HTTP authentication
|
886
911
|
#
|
887
912
|
# If set to true and no HTTP authentication credentials are sent with
|
@@ -954,7 +979,7 @@ module Authlogic
|
|
954
979
|
# Should the cookie be signed? If the controller adapter supports it, this is a
|
955
980
|
# measure against cookie tampering.
|
956
981
|
def sign_cookie(value = nil)
|
957
|
-
if value && !controller.cookies.respond_to?(:signed)
|
982
|
+
if value && controller && !controller.cookies.respond_to?(:signed)
|
958
983
|
raise "Signed cookies not supported with #{controller.class}!"
|
959
984
|
end
|
960
985
|
rw_config(:sign_cookie, value, false)
|
@@ -964,7 +989,7 @@ module Authlogic
|
|
964
989
|
# Should the cookie be encrypted? If the controller adapter supports it, this is a
|
965
990
|
# measure to hide the contents of the cookie (e.g. persistence_token)
|
966
991
|
def encrypt_cookie(value = nil)
|
967
|
-
if value && !controller.cookies.respond_to?(:encrypted)
|
992
|
+
if value && controller && !controller.cookies.respond_to?(:encrypted)
|
968
993
|
raise "Encrypted cookies not supported with #{controller.class}!"
|
969
994
|
end
|
970
995
|
if value && sign_cookie
|
@@ -973,7 +998,7 @@ module Authlogic
|
|
973
998
|
end
|
974
999
|
rw_config(:encrypt_cookie, value, false)
|
975
1000
|
end
|
976
|
-
|
1001
|
+
alias encrypt_cookie= encrypt_cookie
|
977
1002
|
|
978
1003
|
# Works exactly like cookie_key, but for sessions. See cookie_key for more info.
|
979
1004
|
#
|
@@ -1079,24 +1104,10 @@ module Authlogic
|
|
1079
1104
|
# Constructor
|
1080
1105
|
# ===========
|
1081
1106
|
|
1082
|
-
# rubocop:disable Metrics/AbcSize
|
1083
1107
|
def initialize(*args)
|
1084
1108
|
@id = nil
|
1085
1109
|
self.scope = self.class.scope
|
1086
|
-
|
1087
|
-
# Creating an alias method for the "record" method based on the klass
|
1088
|
-
# name, so that we can do:
|
1089
|
-
#
|
1090
|
-
# session.user
|
1091
|
-
#
|
1092
|
-
# instead of:
|
1093
|
-
#
|
1094
|
-
# session.record
|
1095
|
-
unless self.class.configured_klass_methods
|
1096
|
-
self.class.send(:alias_method, klass_name.demodulize.underscore.to_sym, :record)
|
1097
|
-
self.class.configured_klass_methods = true
|
1098
|
-
end
|
1099
|
-
|
1110
|
+
define_record_alias_method
|
1100
1111
|
raise Activation::NotActivatedError unless self.class.activated?
|
1101
1112
|
unless self.class.configured_password_methods
|
1102
1113
|
configure_password_methods
|
@@ -1105,7 +1116,6 @@ module Authlogic
|
|
1105
1116
|
instance_variable_set("@#{password_field}", nil)
|
1106
1117
|
self.credentials = args
|
1107
1118
|
end
|
1108
|
-
# rubocop:enable Metrics/AbcSize
|
1109
1119
|
|
1110
1120
|
# Public instance methods
|
1111
1121
|
# =======================
|
@@ -1528,24 +1538,21 @@ module Authlogic
|
|
1528
1538
|
# Determines if the information you provided for authentication is valid
|
1529
1539
|
# or not. If there is a problem with the information provided errors will
|
1530
1540
|
# be added to the errors object and this method will return false.
|
1541
|
+
#
|
1542
|
+
# @api public
|
1531
1543
|
def valid?
|
1532
1544
|
errors.clear
|
1533
1545
|
self.attempted_record = nil
|
1534
|
-
|
1535
|
-
run_callbacks(:before_validation)
|
1536
|
-
run_callbacks(new_session? ? :before_validation_on_create : :before_validation_on_update)
|
1546
|
+
run_the_before_validation_callbacks
|
1537
1547
|
|
1538
1548
|
# Run the `validate` callbacks, eg. `validate_by_password`.
|
1539
1549
|
# This is when `attempted_record` is set.
|
1540
1550
|
run_callbacks(:validate)
|
1541
1551
|
|
1542
1552
|
ensure_authentication_attempted
|
1543
|
-
|
1544
1553
|
if errors.empty?
|
1545
|
-
|
1546
|
-
run_callbacks(:after_validation)
|
1554
|
+
run_the_after_validation_callbacks
|
1547
1555
|
end
|
1548
|
-
|
1549
1556
|
save_record(attempted_record)
|
1550
1557
|
errors.empty?
|
1551
1558
|
end
|
@@ -1647,12 +1654,18 @@ module Authlogic
|
|
1647
1654
|
# @api private
|
1648
1655
|
# @return ::Authlogic::CookieCredentials or if no cookie is found, nil
|
1649
1656
|
def cookie_credentials
|
1657
|
+
return unless cookie_enabled?
|
1658
|
+
|
1650
1659
|
cookie_value = cookie_jar[cookie_key]
|
1651
1660
|
unless cookie_value.nil?
|
1652
1661
|
::Authlogic::CookieCredentials.parse(cookie_value)
|
1653
1662
|
end
|
1654
1663
|
end
|
1655
1664
|
|
1665
|
+
def cookie_enabled?
|
1666
|
+
!controller.cookies.nil?
|
1667
|
+
end
|
1668
|
+
|
1656
1669
|
def cookie_jar
|
1657
1670
|
if self.class.encrypt_cookie
|
1658
1671
|
controller.cookies.encrypted
|
@@ -1674,15 +1687,23 @@ module Authlogic
|
|
1674
1687
|
self.class.send(:attr_reader, login_field) unless respond_to?(login_field)
|
1675
1688
|
end
|
1676
1689
|
|
1690
|
+
# @api private
|
1677
1691
|
def define_password_field_methods
|
1678
1692
|
return unless password_field
|
1679
|
-
|
1680
|
-
|
1693
|
+
define_password_field_writer_method
|
1694
|
+
define_password_field_reader_methods
|
1695
|
+
end
|
1681
1696
|
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1697
|
+
# The password should not be accessible publicly. This way forms using
|
1698
|
+
# form_for don't fill the password with the attempted password. To prevent
|
1699
|
+
# this we just create this method that is private.
|
1700
|
+
#
|
1701
|
+
# @api private
|
1702
|
+
def define_password_field_reader_methods
|
1703
|
+
unless respond_to?(password_field)
|
1704
|
+
# Deliberate no-op method, see rationale above.
|
1705
|
+
self.class.send(:define_method, password_field) {}
|
1706
|
+
end
|
1686
1707
|
self.class.class_eval(
|
1687
1708
|
<<-EOS, __FILE__, __LINE__ + 1
|
1688
1709
|
private
|
@@ -1693,6 +1714,28 @@ module Authlogic
|
|
1693
1714
|
)
|
1694
1715
|
end
|
1695
1716
|
|
1717
|
+
def define_password_field_writer_method
|
1718
|
+
unless respond_to?("#{password_field}=")
|
1719
|
+
self.class.send(:attr_writer, password_field)
|
1720
|
+
end
|
1721
|
+
end
|
1722
|
+
|
1723
|
+
# Creating an alias method for the "record" method based on the klass
|
1724
|
+
# name, so that we can do:
|
1725
|
+
#
|
1726
|
+
# session.user
|
1727
|
+
#
|
1728
|
+
# instead of:
|
1729
|
+
#
|
1730
|
+
# session.record
|
1731
|
+
#
|
1732
|
+
# @api private
|
1733
|
+
def define_record_alias_method
|
1734
|
+
noun = klass_name.demodulize.underscore.to_sym
|
1735
|
+
return if respond_to?(noun)
|
1736
|
+
self.class.send(:alias_method, noun, :record)
|
1737
|
+
end
|
1738
|
+
|
1696
1739
|
def destroy_cookie
|
1697
1740
|
controller.cookies.delete cookie_key, domain: controller.cookie_domain
|
1698
1741
|
end
|
@@ -1728,8 +1771,10 @@ module Authlogic
|
|
1728
1771
|
attempted_record.failed_login_count >= consecutive_failed_logins_limit
|
1729
1772
|
end
|
1730
1773
|
|
1774
|
+
# @deprecated in favor of `self.class.record_selection_method`
|
1731
1775
|
def find_by_login_method
|
1732
|
-
|
1776
|
+
::ActiveSupport::Deprecation.warn(E_DPR_FIND_BY_LOGIN_METHOD)
|
1777
|
+
self.class.record_selection_method
|
1733
1778
|
end
|
1734
1779
|
|
1735
1780
|
def generalize_credentials_error_messages?
|
@@ -1783,7 +1828,7 @@ module Authlogic
|
|
1783
1828
|
end
|
1784
1829
|
end
|
1785
1830
|
|
1786
|
-
def
|
1831
|
+
def increment_login_count
|
1787
1832
|
if record.respond_to?(:login_count)
|
1788
1833
|
record.login_count = (record.login_count.blank? ? 1 : record.login_count + 1)
|
1789
1834
|
end
|
@@ -1934,6 +1979,18 @@ module Authlogic
|
|
1934
1979
|
attempted_record.failed_login_count = 0
|
1935
1980
|
end
|
1936
1981
|
|
1982
|
+
# @api private
|
1983
|
+
def run_the_after_validation_callbacks
|
1984
|
+
run_callbacks(new_session? ? :after_validation_on_create : :after_validation_on_update)
|
1985
|
+
run_callbacks(:after_validation)
|
1986
|
+
end
|
1987
|
+
|
1988
|
+
# @api private
|
1989
|
+
def run_the_before_validation_callbacks
|
1990
|
+
run_callbacks(:before_validation)
|
1991
|
+
run_callbacks(new_session? ? :before_validation_on_create : :before_validation_on_update)
|
1992
|
+
end
|
1993
|
+
|
1937
1994
|
# `args[0]` is the name of a model method, like
|
1938
1995
|
# `find_by_single_access_token` or `find_by_smart_case_login_field`.
|
1939
1996
|
def search_for_record(*args)
|
@@ -2001,7 +2058,7 @@ module Authlogic
|
|
2001
2058
|
end
|
2002
2059
|
|
2003
2060
|
def update_info
|
2004
|
-
|
2061
|
+
increment_login_count
|
2005
2062
|
clear_failed_login_count
|
2006
2063
|
update_login_timestamps
|
2007
2064
|
update_login_ip_addresses
|
@@ -2048,7 +2105,10 @@ module Authlogic
|
|
2048
2105
|
self.invalid_password = false
|
2049
2106
|
validate_by_password__blank_fields
|
2050
2107
|
return if errors.count > 0
|
2051
|
-
self.attempted_record = search_for_record(
|
2108
|
+
self.attempted_record = search_for_record(
|
2109
|
+
self.class.record_selection_method,
|
2110
|
+
send(login_field)
|
2111
|
+
)
|
2052
2112
|
if attempted_record.blank?
|
2053
2113
|
add_login_not_found_error
|
2054
2114
|
return
|
data/lib/authlogic/test_case.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require File.dirname(__FILE__) + "/test_case/rails_request_adapter"
|
4
|
+
require File.dirname(__FILE__) + "/test_case/mock_api_controller"
|
4
5
|
require File.dirname(__FILE__) + "/test_case/mock_cookie_jar"
|
5
6
|
require File.dirname(__FILE__) + "/test_case/mock_controller"
|
6
7
|
require File.dirname(__FILE__) + "/test_case/mock_logger"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Authlogic
|
4
|
+
module TestCase
|
5
|
+
# Basically acts like an API controller but doesn't do anything.
|
6
|
+
# Authlogic can interact with this, do it's thing and then you can look at
|
7
|
+
# the controller object to see if anything changed.
|
8
|
+
class MockAPIController < ControllerAdapters::AbstractAdapter
|
9
|
+
attr_writer :request_content_type
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
end
|
13
|
+
|
14
|
+
# Expected API controller has no cookies method.
|
15
|
+
undef :cookies
|
16
|
+
|
17
|
+
def cookie_domain
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def logger
|
22
|
+
@logger ||= MockLogger.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def params
|
26
|
+
@params ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def request
|
30
|
+
@request ||= MockRequest.new(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
def request_content_type
|
34
|
+
@request_content_type ||= "text/html"
|
35
|
+
end
|
36
|
+
|
37
|
+
def session
|
38
|
+
@session ||= {}
|
39
|
+
end
|
40
|
+
|
41
|
+
# If method is defined, it causes below behavior...
|
42
|
+
# controller = Authlogic::ControllerAdapters::RailsAdapter.new(
|
43
|
+
# Authlogic::TestCase::MockAPIController.new
|
44
|
+
# )
|
45
|
+
# controller.responds_to_single_access_allowed? #=> true
|
46
|
+
# controller.single_access_allowed?
|
47
|
+
# #=> NoMethodError: undefined method `single_access_allowed?' for nil:NilClass
|
48
|
+
#
|
49
|
+
undef :single_access_allowed?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Authlogic
|
4
4
|
module TestCase
|
5
5
|
# A mock of `ActionDispatch::Cookies::CookieJar`.
|
6
|
+
# See action_dispatch/middleware/cookies.rb
|
6
7
|
class MockCookieJar < Hash # :nodoc:
|
7
8
|
attr_accessor :set_cookies
|
8
9
|
|
@@ -11,9 +12,12 @@ module Authlogic
|
|
11
12
|
hash && hash[:value]
|
12
13
|
end
|
13
14
|
|
15
|
+
# @param options - "the cookie's value [usually a string] or a hash of
|
16
|
+
# options as documented above [in action_dispatch/middleware/cookies.rb]"
|
14
17
|
def []=(key, options)
|
15
|
-
|
16
|
-
|
18
|
+
opt = cookie_options_to_hash(options)
|
19
|
+
(@set_cookies ||= {})[key.to_s] = opt
|
20
|
+
super(key, opt)
|
17
21
|
end
|
18
22
|
|
19
23
|
def delete(key, _options = {})
|
@@ -27,6 +31,17 @@ module Authlogic
|
|
27
31
|
def encrypted
|
28
32
|
@encrypted ||= MockEncryptedCookieJar.new(self)
|
29
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# @api private
|
38
|
+
def cookie_options_to_hash(options)
|
39
|
+
if options.is_a?(Hash)
|
40
|
+
options
|
41
|
+
else
|
42
|
+
{ value: options }
|
43
|
+
end
|
44
|
+
end
|
30
45
|
end
|
31
46
|
|
32
47
|
# A mock of `ActionDispatch::Cookies::SignedKeyRotatingCookieJar`
|
@@ -52,11 +67,14 @@ module Authlogic
|
|
52
67
|
end
|
53
68
|
|
54
69
|
def []=(key, options)
|
55
|
-
|
56
|
-
|
70
|
+
opt = cookie_options_to_hash(options)
|
71
|
+
opt[:value] = "#{opt[:value]}--#{Digest::SHA1.hexdigest opt[:value]}"
|
72
|
+
@parent_jar[key] = opt
|
57
73
|
end
|
58
74
|
end
|
59
75
|
|
76
|
+
# Which ActionDispatch class is this a mock of?
|
77
|
+
# TODO: Document as with other mocks above.
|
60
78
|
class MockEncryptedCookieJar < MockCookieJar
|
61
79
|
attr_reader :parent_jar # helper for testing
|
62
80
|
|
@@ -73,8 +91,9 @@ module Authlogic
|
|
73
91
|
end
|
74
92
|
|
75
93
|
def []=(key, options)
|
76
|
-
|
77
|
-
|
94
|
+
opt = cookie_options_to_hash(options)
|
95
|
+
opt[:value] = self.class.encrypt(opt[:value])
|
96
|
+
@parent_jar[key] = opt
|
78
97
|
end
|
79
98
|
|
80
99
|
# simple caesar cipher for testing
|
@@ -12,7 +12,7 @@ module Authlogic
|
|
12
12
|
def cookies
|
13
13
|
new_cookies = MockCookieJar.new
|
14
14
|
super.each do |key, value|
|
15
|
-
new_cookies[key] = value
|
15
|
+
new_cookies[key] = cookie_value(value)
|
16
16
|
end
|
17
17
|
new_cookies
|
18
18
|
end
|
@@ -28,6 +28,12 @@ module Authlogic
|
|
28
28
|
def request_content_type
|
29
29
|
request.format.to_s
|
30
30
|
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def cookie_value(value)
|
35
|
+
value.is_a?(Hash) ? value[:value] : value
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
data/lib/authlogic/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authlogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Johnson
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-12-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activemodel
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '5.2'
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: '6.
|
24
|
+
version: '6.2'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
version: '5.2'
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '6.
|
34
|
+
version: '6.2'
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: activerecord
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -41,7 +41,7 @@ dependencies:
|
|
41
41
|
version: '5.2'
|
42
42
|
- - "<"
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: '6.
|
44
|
+
version: '6.2'
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
47
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -51,7 +51,7 @@ dependencies:
|
|
51
51
|
version: '5.2'
|
52
52
|
- - "<"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '6.
|
54
|
+
version: '6.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: activesupport
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -61,7 +61,7 @@ dependencies:
|
|
61
61
|
version: '5.2'
|
62
62
|
- - "<"
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: '6.
|
64
|
+
version: '6.2'
|
65
65
|
type: :runtime
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -71,7 +71,7 @@ dependencies:
|
|
71
71
|
version: '5.2'
|
72
72
|
- - "<"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '6.
|
74
|
+
version: '6.2'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: request_store
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,26 +86,6 @@ dependencies:
|
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '1.0'
|
89
|
-
- !ruby/object:Gem::Dependency
|
90
|
-
name: scrypt
|
91
|
-
requirement: !ruby/object:Gem::Requirement
|
92
|
-
requirements:
|
93
|
-
- - ">="
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
version: '1.2'
|
96
|
-
- - "<"
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
version: '4.0'
|
99
|
-
type: :runtime
|
100
|
-
prerelease: false
|
101
|
-
version_requirements: !ruby/object:Gem::Requirement
|
102
|
-
requirements:
|
103
|
-
- - ">="
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
version: '1.2'
|
106
|
-
- - "<"
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: '4.0'
|
109
89
|
- !ruby/object:Gem::Dependency
|
110
90
|
name: bcrypt
|
111
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -190,20 +170,34 @@ dependencies:
|
|
190
170
|
- - "~>"
|
191
171
|
- !ruby/object:Gem::Version
|
192
172
|
version: 1.1.4
|
173
|
+
- !ruby/object:Gem::Dependency
|
174
|
+
name: rake
|
175
|
+
requirement: !ruby/object:Gem::Requirement
|
176
|
+
requirements:
|
177
|
+
- - "~>"
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '13.0'
|
180
|
+
type: :development
|
181
|
+
prerelease: false
|
182
|
+
version_requirements: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - "~>"
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '13.0'
|
193
187
|
- !ruby/object:Gem::Dependency
|
194
188
|
name: rubocop
|
195
189
|
requirement: !ruby/object:Gem::Requirement
|
196
190
|
requirements:
|
197
191
|
- - "~>"
|
198
192
|
- !ruby/object:Gem::Version
|
199
|
-
version: 0.
|
193
|
+
version: 0.80.1
|
200
194
|
type: :development
|
201
195
|
prerelease: false
|
202
196
|
version_requirements: !ruby/object:Gem::Requirement
|
203
197
|
requirements:
|
204
198
|
- - "~>"
|
205
199
|
- !ruby/object:Gem::Version
|
206
|
-
version: 0.
|
200
|
+
version: 0.80.1
|
207
201
|
- !ruby/object:Gem::Dependency
|
208
202
|
name: rubocop-performance
|
209
203
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,6 +212,26 @@ dependencies:
|
|
218
212
|
- - "~>"
|
219
213
|
- !ruby/object:Gem::Version
|
220
214
|
version: '1.1'
|
215
|
+
- !ruby/object:Gem::Dependency
|
216
|
+
name: scrypt
|
217
|
+
requirement: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - ">="
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '1.2'
|
222
|
+
- - "<"
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '4.0'
|
225
|
+
type: :development
|
226
|
+
prerelease: false
|
227
|
+
version_requirements: !ruby/object:Gem::Requirement
|
228
|
+
requirements:
|
229
|
+
- - ">="
|
230
|
+
- !ruby/object:Gem::Version
|
231
|
+
version: '1.2'
|
232
|
+
- - "<"
|
233
|
+
- !ruby/object:Gem::Version
|
234
|
+
version: '4.0'
|
221
235
|
- !ruby/object:Gem::Dependency
|
222
236
|
name: simplecov
|
223
237
|
requirement: !ruby/object:Gem::Requirement
|
@@ -252,14 +266,14 @@ dependencies:
|
|
252
266
|
requirements:
|
253
267
|
- - "~>"
|
254
268
|
- !ruby/object:Gem::Version
|
255
|
-
version: 1.
|
269
|
+
version: 1.4.0
|
256
270
|
type: :development
|
257
271
|
prerelease: false
|
258
272
|
version_requirements: !ruby/object:Gem::Requirement
|
259
273
|
requirements:
|
260
274
|
- - "~>"
|
261
275
|
- !ruby/object:Gem::Version
|
262
|
-
version: 1.
|
276
|
+
version: 1.4.0
|
263
277
|
- !ruby/object:Gem::Dependency
|
264
278
|
name: timecop
|
265
279
|
requirement: !ruby/object:Gem::Requirement
|
@@ -305,16 +319,22 @@ files:
|
|
305
319
|
- lib/authlogic/crypto_providers.rb
|
306
320
|
- lib/authlogic/crypto_providers/bcrypt.rb
|
307
321
|
- lib/authlogic/crypto_providers/md5.rb
|
322
|
+
- lib/authlogic/crypto_providers/md5/v2.rb
|
308
323
|
- lib/authlogic/crypto_providers/scrypt.rb
|
309
324
|
- lib/authlogic/crypto_providers/sha1.rb
|
325
|
+
- lib/authlogic/crypto_providers/sha1/v2.rb
|
310
326
|
- lib/authlogic/crypto_providers/sha256.rb
|
327
|
+
- lib/authlogic/crypto_providers/sha256/v2.rb
|
311
328
|
- lib/authlogic/crypto_providers/sha512.rb
|
329
|
+
- lib/authlogic/crypto_providers/sha512/v2.rb
|
330
|
+
- lib/authlogic/errors.rb
|
312
331
|
- lib/authlogic/i18n.rb
|
313
332
|
- lib/authlogic/i18n/translator.rb
|
314
333
|
- lib/authlogic/random.rb
|
315
334
|
- lib/authlogic/session/base.rb
|
316
335
|
- lib/authlogic/session/magic_column/assigns_last_request_at.rb
|
317
336
|
- lib/authlogic/test_case.rb
|
337
|
+
- lib/authlogic/test_case/mock_api_controller.rb
|
318
338
|
- lib/authlogic/test_case/mock_controller.rb
|
319
339
|
- lib/authlogic/test_case/mock_cookie_jar.rb
|
320
340
|
- lib/authlogic/test_case/mock_logger.rb
|
@@ -333,7 +353,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
333
353
|
requirements:
|
334
354
|
- - ">="
|
335
355
|
- !ruby/object:Gem::Version
|
336
|
-
version: 2.
|
356
|
+
version: 2.4.0
|
337
357
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
338
358
|
requirements:
|
339
359
|
- - ">="
|