authlogic 5.1.0 → 6.3.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 +184 -92
- 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 +37 -0
- data/lib/authlogic/test_case/mock_request.rb +4 -0
- data/lib/authlogic/version.rb +1 -1
- metadata +39 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f51d7731ff8fa94fae297857416a4f8e2d3ff6a36be6c95151100928f4bde5a1
|
4
|
+
data.tar.gz: 1cc8a04722128c14023fb31b2109ad31138e74b887a8e89bf4a7400b841cc708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb9684e8af955d1bff59dd4f3b4f803cea8e405f411d3faff59d47fd228520be810bc220a1d39434539b416b844ce901044c742f3dc4a4a6fa0fdcbdc4637f89
|
7
|
+
data.tar.gz: b0a2dba042bd7802dc33d837c14fa103f5e7f0f0eb28d1c26f66eb0d5dd8ce950aab37cddca7d75956b2afa9e4c6588b3790cd781157200c4b1fee7394d1232b
|
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,13 +979,27 @@ 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)
|
961
986
|
end
|
962
987
|
alias sign_cookie= sign_cookie
|
963
988
|
|
989
|
+
# Should the cookie be encrypted? If the controller adapter supports it, this is a
|
990
|
+
# measure to hide the contents of the cookie (e.g. persistence_token)
|
991
|
+
def encrypt_cookie(value = nil)
|
992
|
+
if value && controller && !controller.cookies.respond_to?(:encrypted)
|
993
|
+
raise "Encrypted cookies not supported with #{controller.class}!"
|
994
|
+
end
|
995
|
+
if value && sign_cookie
|
996
|
+
raise "It is recommended to use encrypt_cookie instead of sign_cookie. " \
|
997
|
+
"You may not enable both options."
|
998
|
+
end
|
999
|
+
rw_config(:encrypt_cookie, value, false)
|
1000
|
+
end
|
1001
|
+
alias encrypt_cookie= encrypt_cookie
|
1002
|
+
|
964
1003
|
# Works exactly like cookie_key, but for sessions. See cookie_key for more info.
|
965
1004
|
#
|
966
1005
|
# * <tt>Default:</tt> cookie_key
|
@@ -1065,24 +1104,10 @@ module Authlogic
|
|
1065
1104
|
# Constructor
|
1066
1105
|
# ===========
|
1067
1106
|
|
1068
|
-
# rubocop:disable Metrics/AbcSize
|
1069
1107
|
def initialize(*args)
|
1070
1108
|
@id = nil
|
1071
1109
|
self.scope = self.class.scope
|
1072
|
-
|
1073
|
-
# Creating an alias method for the "record" method based on the klass
|
1074
|
-
# name, so that we can do:
|
1075
|
-
#
|
1076
|
-
# session.user
|
1077
|
-
#
|
1078
|
-
# instead of:
|
1079
|
-
#
|
1080
|
-
# session.record
|
1081
|
-
unless self.class.configured_klass_methods
|
1082
|
-
self.class.send(:alias_method, klass_name.demodulize.underscore.to_sym, :record)
|
1083
|
-
self.class.configured_klass_methods = true
|
1084
|
-
end
|
1085
|
-
|
1110
|
+
define_record_alias_method
|
1086
1111
|
raise Activation::NotActivatedError unless self.class.activated?
|
1087
1112
|
unless self.class.configured_password_methods
|
1088
1113
|
configure_password_methods
|
@@ -1091,7 +1116,6 @@ module Authlogic
|
|
1091
1116
|
instance_variable_set("@#{password_field}", nil)
|
1092
1117
|
self.credentials = args
|
1093
1118
|
end
|
1094
|
-
# rubocop:enable Metrics/AbcSize
|
1095
1119
|
|
1096
1120
|
# Public instance methods
|
1097
1121
|
# =======================
|
@@ -1480,6 +1504,23 @@ module Authlogic
|
|
1480
1504
|
sign_cookie == true || sign_cookie == "true" || sign_cookie == "1"
|
1481
1505
|
end
|
1482
1506
|
|
1507
|
+
# If the cookie should be encrypted
|
1508
|
+
def encrypt_cookie
|
1509
|
+
return @encrypt_cookie if defined?(@encrypt_cookie)
|
1510
|
+
@encrypt_cookie = self.class.encrypt_cookie
|
1511
|
+
end
|
1512
|
+
|
1513
|
+
# Accepts a boolean as to whether the cookie should be encrypted. If true
|
1514
|
+
# the cookie will be saved in an encrypted state.
|
1515
|
+
def encrypt_cookie=(value)
|
1516
|
+
@encrypt_cookie = value
|
1517
|
+
end
|
1518
|
+
|
1519
|
+
# See encrypt_cookie
|
1520
|
+
def encrypt_cookie?
|
1521
|
+
encrypt_cookie == true || encrypt_cookie == "true" || encrypt_cookie == "1"
|
1522
|
+
end
|
1523
|
+
|
1483
1524
|
# The scope of the current object
|
1484
1525
|
def scope
|
1485
1526
|
@scope ||= {}
|
@@ -1497,24 +1538,21 @@ module Authlogic
|
|
1497
1538
|
# Determines if the information you provided for authentication is valid
|
1498
1539
|
# or not. If there is a problem with the information provided errors will
|
1499
1540
|
# be added to the errors object and this method will return false.
|
1541
|
+
#
|
1542
|
+
# @api public
|
1500
1543
|
def valid?
|
1501
1544
|
errors.clear
|
1502
1545
|
self.attempted_record = nil
|
1503
|
-
|
1504
|
-
run_callbacks(:before_validation)
|
1505
|
-
run_callbacks(new_session? ? :before_validation_on_create : :before_validation_on_update)
|
1546
|
+
run_the_before_validation_callbacks
|
1506
1547
|
|
1507
1548
|
# Run the `validate` callbacks, eg. `validate_by_password`.
|
1508
1549
|
# This is when `attempted_record` is set.
|
1509
1550
|
run_callbacks(:validate)
|
1510
1551
|
|
1511
1552
|
ensure_authentication_attempted
|
1512
|
-
|
1513
1553
|
if errors.empty?
|
1514
|
-
|
1515
|
-
run_callbacks(:after_validation)
|
1554
|
+
run_the_after_validation_callbacks
|
1516
1555
|
end
|
1517
|
-
|
1518
1556
|
save_record(attempted_record)
|
1519
1557
|
errors.empty?
|
1520
1558
|
end
|
@@ -1616,14 +1654,22 @@ module Authlogic
|
|
1616
1654
|
# @api private
|
1617
1655
|
# @return ::Authlogic::CookieCredentials or if no cookie is found, nil
|
1618
1656
|
def cookie_credentials
|
1657
|
+
return unless cookie_enabled?
|
1658
|
+
|
1619
1659
|
cookie_value = cookie_jar[cookie_key]
|
1620
1660
|
unless cookie_value.nil?
|
1621
1661
|
::Authlogic::CookieCredentials.parse(cookie_value)
|
1622
1662
|
end
|
1623
1663
|
end
|
1624
1664
|
|
1665
|
+
def cookie_enabled?
|
1666
|
+
!controller.cookies.nil?
|
1667
|
+
end
|
1668
|
+
|
1625
1669
|
def cookie_jar
|
1626
|
-
if self.class.
|
1670
|
+
if self.class.encrypt_cookie
|
1671
|
+
controller.cookies.encrypted
|
1672
|
+
elsif self.class.sign_cookie
|
1627
1673
|
controller.cookies.signed
|
1628
1674
|
else
|
1629
1675
|
controller.cookies
|
@@ -1641,15 +1687,23 @@ module Authlogic
|
|
1641
1687
|
self.class.send(:attr_reader, login_field) unless respond_to?(login_field)
|
1642
1688
|
end
|
1643
1689
|
|
1690
|
+
# @api private
|
1644
1691
|
def define_password_field_methods
|
1645
1692
|
return unless password_field
|
1646
|
-
|
1647
|
-
|
1693
|
+
define_password_field_writer_method
|
1694
|
+
define_password_field_reader_methods
|
1695
|
+
end
|
1648
1696
|
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
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
|
1653
1707
|
self.class.class_eval(
|
1654
1708
|
<<-EOS, __FILE__, __LINE__ + 1
|
1655
1709
|
private
|
@@ -1660,6 +1714,28 @@ module Authlogic
|
|
1660
1714
|
)
|
1661
1715
|
end
|
1662
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
|
+
|
1663
1739
|
def destroy_cookie
|
1664
1740
|
controller.cookies.delete cookie_key, domain: controller.cookie_domain
|
1665
1741
|
end
|
@@ -1695,8 +1771,10 @@ module Authlogic
|
|
1695
1771
|
attempted_record.failed_login_count >= consecutive_failed_logins_limit
|
1696
1772
|
end
|
1697
1773
|
|
1774
|
+
# @deprecated in favor of `self.class.record_selection_method`
|
1698
1775
|
def find_by_login_method
|
1699
|
-
|
1776
|
+
::ActiveSupport::Deprecation.warn(E_DPR_FIND_BY_LOGIN_METHOD)
|
1777
|
+
self.class.record_selection_method
|
1700
1778
|
end
|
1701
1779
|
|
1702
1780
|
def generalize_credentials_error_messages?
|
@@ -1705,13 +1783,8 @@ module Authlogic
|
|
1705
1783
|
|
1706
1784
|
# @api private
|
1707
1785
|
def generate_cookie_for_saving
|
1708
|
-
creds = ::Authlogic::CookieCredentials.new(
|
1709
|
-
record.persistence_token,
|
1710
|
-
record.send(record.class.primary_key),
|
1711
|
-
remember_me? ? remember_me_until : nil
|
1712
|
-
)
|
1713
1786
|
{
|
1714
|
-
value:
|
1787
|
+
value: generate_cookie_value.to_s,
|
1715
1788
|
expires: remember_me_until,
|
1716
1789
|
secure: secure,
|
1717
1790
|
httponly: httponly,
|
@@ -1720,6 +1793,14 @@ module Authlogic
|
|
1720
1793
|
}
|
1721
1794
|
end
|
1722
1795
|
|
1796
|
+
def generate_cookie_value
|
1797
|
+
::Authlogic::CookieCredentials.new(
|
1798
|
+
record.persistence_token,
|
1799
|
+
record.send(record.class.primary_key),
|
1800
|
+
remember_me? ? remember_me_until : nil
|
1801
|
+
)
|
1802
|
+
end
|
1803
|
+
|
1723
1804
|
# Returns a Proc to be executed by
|
1724
1805
|
# `ActionController::HttpAuthentication::Basic` when credentials are
|
1725
1806
|
# present in the HTTP request.
|
@@ -1747,7 +1828,7 @@ module Authlogic
|
|
1747
1828
|
end
|
1748
1829
|
end
|
1749
1830
|
|
1750
|
-
def
|
1831
|
+
def increment_login_count
|
1751
1832
|
if record.respond_to?(:login_count)
|
1752
1833
|
record.login_count = (record.login_count.blank? ? 1 : record.login_count + 1)
|
1753
1834
|
end
|
@@ -1898,6 +1979,18 @@ module Authlogic
|
|
1898
1979
|
attempted_record.failed_login_count = 0
|
1899
1980
|
end
|
1900
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
|
+
|
1901
1994
|
# `args[0]` is the name of a model method, like
|
1902
1995
|
# `find_by_single_access_token` or `find_by_smart_case_login_field`.
|
1903
1996
|
def search_for_record(*args)
|
@@ -1935,11 +2028,7 @@ module Authlogic
|
|
1935
2028
|
end
|
1936
2029
|
|
1937
2030
|
def save_cookie
|
1938
|
-
|
1939
|
-
controller.cookies.signed[cookie_key] = generate_cookie_for_saving
|
1940
|
-
else
|
1941
|
-
controller.cookies[cookie_key] = generate_cookie_for_saving
|
1942
|
-
end
|
2031
|
+
cookie_jar[cookie_key] = generate_cookie_for_saving
|
1943
2032
|
end
|
1944
2033
|
|
1945
2034
|
# @api private
|
@@ -1969,7 +2058,7 @@ module Authlogic
|
|
1969
2058
|
end
|
1970
2059
|
|
1971
2060
|
def update_info
|
1972
|
-
|
2061
|
+
increment_login_count
|
1973
2062
|
clear_failed_login_count
|
1974
2063
|
update_login_timestamps
|
1975
2064
|
update_login_ip_addresses
|
@@ -2016,7 +2105,10 @@ module Authlogic
|
|
2016
2105
|
self.invalid_password = false
|
2017
2106
|
validate_by_password__blank_fields
|
2018
2107
|
return if errors.count > 0
|
2019
|
-
self.attempted_record = search_for_record(
|
2108
|
+
self.attempted_record = search_for_record(
|
2109
|
+
self.class.record_selection_method,
|
2110
|
+
send(login_field)
|
2111
|
+
)
|
2020
2112
|
if attempted_record.blank?
|
2021
2113
|
add_login_not_found_error
|
2022
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
|
@@ -23,6 +23,10 @@ module Authlogic
|
|
23
23
|
def signed
|
24
24
|
@signed ||= MockSignedCookieJar.new(self)
|
25
25
|
end
|
26
|
+
|
27
|
+
def encrypted
|
28
|
+
@encrypted ||= MockEncryptedCookieJar.new(self)
|
29
|
+
end
|
26
30
|
end
|
27
31
|
|
28
32
|
# A mock of `ActionDispatch::Cookies::SignedKeyRotatingCookieJar`
|
@@ -35,6 +39,7 @@ module Authlogic
|
|
35
39
|
|
36
40
|
def initialize(parent_jar)
|
37
41
|
@parent_jar = parent_jar
|
42
|
+
parent_jar.each { |k, v| self[k] = v }
|
38
43
|
end
|
39
44
|
|
40
45
|
def [](val)
|
@@ -51,5 +56,37 @@ module Authlogic
|
|
51
56
|
@parent_jar[key] = options
|
52
57
|
end
|
53
58
|
end
|
59
|
+
|
60
|
+
# Which ActionDispatch class is this a mock of?
|
61
|
+
# TODO: Document as with other mocks above.
|
62
|
+
class MockEncryptedCookieJar < MockCookieJar
|
63
|
+
attr_reader :parent_jar # helper for testing
|
64
|
+
|
65
|
+
def initialize(parent_jar)
|
66
|
+
@parent_jar = parent_jar
|
67
|
+
parent_jar.each { |k, v| self[k] = v }
|
68
|
+
end
|
69
|
+
|
70
|
+
def [](val)
|
71
|
+
encrypted_message = @parent_jar[val]
|
72
|
+
if encrypted_message
|
73
|
+
self.class.decrypt(encrypted_message)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def []=(key, options)
|
78
|
+
options[:value] = self.class.encrypt(options[:value])
|
79
|
+
@parent_jar[key] = options
|
80
|
+
end
|
81
|
+
|
82
|
+
# simple caesar cipher for testing
|
83
|
+
def self.encrypt(str)
|
84
|
+
str.unpack("U*").map(&:succ).pack("U*")
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.decrypt(str)
|
88
|
+
str.unpack("U*").map(&:pred).pack("U*")
|
89
|
+
end
|
90
|
+
end
|
54
91
|
end
|
55
92
|
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.3.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-18 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
|
@@ -196,14 +176,14 @@ dependencies:
|
|
196
176
|
requirements:
|
197
177
|
- - "~>"
|
198
178
|
- !ruby/object:Gem::Version
|
199
|
-
version: 0.
|
179
|
+
version: 0.80.1
|
200
180
|
type: :development
|
201
181
|
prerelease: false
|
202
182
|
version_requirements: !ruby/object:Gem::Requirement
|
203
183
|
requirements:
|
204
184
|
- - "~>"
|
205
185
|
- !ruby/object:Gem::Version
|
206
|
-
version: 0.
|
186
|
+
version: 0.80.1
|
207
187
|
- !ruby/object:Gem::Dependency
|
208
188
|
name: rubocop-performance
|
209
189
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,6 +198,26 @@ dependencies:
|
|
218
198
|
- - "~>"
|
219
199
|
- !ruby/object:Gem::Version
|
220
200
|
version: '1.1'
|
201
|
+
- !ruby/object:Gem::Dependency
|
202
|
+
name: scrypt
|
203
|
+
requirement: !ruby/object:Gem::Requirement
|
204
|
+
requirements:
|
205
|
+
- - ">="
|
206
|
+
- !ruby/object:Gem::Version
|
207
|
+
version: '1.2'
|
208
|
+
- - "<"
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '4.0'
|
211
|
+
type: :development
|
212
|
+
prerelease: false
|
213
|
+
version_requirements: !ruby/object:Gem::Requirement
|
214
|
+
requirements:
|
215
|
+
- - ">="
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: '1.2'
|
218
|
+
- - "<"
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
version: '4.0'
|
221
221
|
- !ruby/object:Gem::Dependency
|
222
222
|
name: simplecov
|
223
223
|
requirement: !ruby/object:Gem::Requirement
|
@@ -252,14 +252,14 @@ dependencies:
|
|
252
252
|
requirements:
|
253
253
|
- - "~>"
|
254
254
|
- !ruby/object:Gem::Version
|
255
|
-
version: 1.
|
255
|
+
version: 1.4.0
|
256
256
|
type: :development
|
257
257
|
prerelease: false
|
258
258
|
version_requirements: !ruby/object:Gem::Requirement
|
259
259
|
requirements:
|
260
260
|
- - "~>"
|
261
261
|
- !ruby/object:Gem::Version
|
262
|
-
version: 1.
|
262
|
+
version: 1.4.0
|
263
263
|
- !ruby/object:Gem::Dependency
|
264
264
|
name: timecop
|
265
265
|
requirement: !ruby/object:Gem::Requirement
|
@@ -305,16 +305,22 @@ files:
|
|
305
305
|
- lib/authlogic/crypto_providers.rb
|
306
306
|
- lib/authlogic/crypto_providers/bcrypt.rb
|
307
307
|
- lib/authlogic/crypto_providers/md5.rb
|
308
|
+
- lib/authlogic/crypto_providers/md5/v2.rb
|
308
309
|
- lib/authlogic/crypto_providers/scrypt.rb
|
309
310
|
- lib/authlogic/crypto_providers/sha1.rb
|
311
|
+
- lib/authlogic/crypto_providers/sha1/v2.rb
|
310
312
|
- lib/authlogic/crypto_providers/sha256.rb
|
313
|
+
- lib/authlogic/crypto_providers/sha256/v2.rb
|
311
314
|
- lib/authlogic/crypto_providers/sha512.rb
|
315
|
+
- lib/authlogic/crypto_providers/sha512/v2.rb
|
316
|
+
- lib/authlogic/errors.rb
|
312
317
|
- lib/authlogic/i18n.rb
|
313
318
|
- lib/authlogic/i18n/translator.rb
|
314
319
|
- lib/authlogic/random.rb
|
315
320
|
- lib/authlogic/session/base.rb
|
316
321
|
- lib/authlogic/session/magic_column/assigns_last_request_at.rb
|
317
322
|
- lib/authlogic/test_case.rb
|
323
|
+
- lib/authlogic/test_case/mock_api_controller.rb
|
318
324
|
- lib/authlogic/test_case/mock_controller.rb
|
319
325
|
- lib/authlogic/test_case/mock_cookie_jar.rb
|
320
326
|
- lib/authlogic/test_case/mock_logger.rb
|
@@ -333,7 +339,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
333
339
|
requirements:
|
334
340
|
- - ">="
|
335
341
|
- !ruby/object:Gem::Version
|
336
|
-
version: 2.
|
342
|
+
version: 2.4.0
|
337
343
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
338
344
|
requirements:
|
339
345
|
- - ">="
|