authlogic 3.4.6 → 4.2.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 +5 -5
- data/.github/ISSUE_TEMPLATE.md +13 -0
- data/.github/triage.md +87 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +127 -0
- data/.rubocop_todo.yml +65 -0
- data/.travis.yml +18 -10
- data/CHANGELOG.md +156 -6
- data/CONTRIBUTING.md +71 -3
- data/Gemfile +2 -2
- data/README.md +386 -0
- data/Rakefile +13 -7
- data/UPGRADING.md +22 -0
- data/authlogic.gemspec +33 -22
- data/lib/authlogic.rb +60 -52
- data/lib/authlogic/acts_as_authentic/base.rb +40 -26
- data/lib/authlogic/acts_as_authentic/email.rb +96 -32
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +36 -12
- data/lib/authlogic/acts_as_authentic/login.rb +114 -49
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
- data/lib/authlogic/acts_as_authentic/password.rb +296 -139
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +34 -20
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +20 -24
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +67 -0
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +68 -23
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +128 -85
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +41 -25
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +8 -8
- data/lib/authlogic/authenticates_many/association.rb +22 -14
- data/lib/authlogic/authenticates_many/base.rb +35 -16
- data/lib/authlogic/config.rb +10 -10
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +40 -12
- data/lib/authlogic/controller_adapters/rack_adapter.rb +15 -8
- data/lib/authlogic/controller_adapters/rails_adapter.rb +42 -22
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +3 -3
- data/lib/authlogic/crypto_providers.rb +91 -0
- data/lib/authlogic/crypto_providers/aes256.rb +42 -14
- data/lib/authlogic/crypto_providers/bcrypt.rb +35 -20
- data/lib/authlogic/crypto_providers/md5.rb +11 -9
- data/lib/authlogic/crypto_providers/scrypt.rb +26 -13
- data/lib/authlogic/crypto_providers/sha1.rb +14 -8
- data/lib/authlogic/crypto_providers/sha256.rb +16 -12
- data/lib/authlogic/crypto_providers/sha512.rb +8 -24
- data/lib/authlogic/crypto_providers/wordpress.rb +44 -15
- data/lib/authlogic/i18n.rb +33 -20
- data/lib/authlogic/i18n/translator.rb +1 -1
- data/lib/authlogic/random.rb +12 -29
- data/lib/authlogic/regex.rb +59 -27
- data/lib/authlogic/session/activation.rb +36 -23
- data/lib/authlogic/session/active_record_trickery.rb +13 -10
- data/lib/authlogic/session/base.rb +20 -8
- data/lib/authlogic/session/brute_force_protection.rb +87 -56
- data/lib/authlogic/session/callbacks.rb +99 -49
- data/lib/authlogic/session/cookies.rb +128 -59
- data/lib/authlogic/session/existence.rb +29 -19
- data/lib/authlogic/session/foundation.rb +70 -16
- data/lib/authlogic/session/http_auth.rb +39 -31
- data/lib/authlogic/session/id.rb +27 -15
- data/lib/authlogic/session/klass.rb +17 -13
- data/lib/authlogic/session/magic_columns.rb +78 -59
- data/lib/authlogic/session/magic_states.rb +50 -27
- data/lib/authlogic/session/params.rb +79 -50
- data/lib/authlogic/session/password.rb +197 -118
- data/lib/authlogic/session/perishable_token.rb +12 -6
- data/lib/authlogic/session/persistence.rb +20 -14
- data/lib/authlogic/session/priority_record.rb +20 -16
- data/lib/authlogic/session/scopes.rb +63 -33
- data/lib/authlogic/session/session.rb +40 -25
- data/lib/authlogic/session/timeout.rb +51 -34
- data/lib/authlogic/session/unauthorized_record.rb +24 -18
- data/lib/authlogic/session/validation.rb +32 -21
- data/lib/authlogic/test_case.rb +123 -35
- data/lib/authlogic/test_case/mock_controller.rb +14 -13
- data/lib/authlogic/test_case/mock_cookie_jar.rb +14 -5
- data/lib/authlogic/test_case/mock_logger.rb +1 -1
- data/lib/authlogic/test_case/mock_request.rb +9 -4
- data/lib/authlogic/test_case/rails_request_adapter.rb +8 -7
- data/lib/authlogic/version.rb +21 -0
- data/test/acts_as_authentic_test/base_test.rb +1 -1
- data/test/acts_as_authentic_test/email_test.rb +80 -63
- data/test/acts_as_authentic_test/logged_in_status_test.rb +14 -8
- data/test/acts_as_authentic_test/login_test.rb +91 -49
- data/test/acts_as_authentic_test/magic_columns_test.rb +13 -13
- data/test/acts_as_authentic_test/password_test.rb +82 -60
- data/test/acts_as_authentic_test/perishable_token_test.rb +31 -25
- data/test/acts_as_authentic_test/persistence_token_test.rb +9 -5
- data/test/acts_as_authentic_test/restful_authentication_test.rb +18 -9
- data/test/acts_as_authentic_test/session_maintenance_test.rb +86 -22
- data/test/acts_as_authentic_test/single_access_test.rb +15 -15
- data/test/adapter_test.rb +21 -0
- data/test/authenticates_many_test.rb +26 -11
- data/test/config_test.rb +9 -9
- data/test/crypto_provider_test/aes256_test.rb +3 -3
- data/test/crypto_provider_test/bcrypt_test.rb +1 -1
- data/test/crypto_provider_test/scrypt_test.rb +2 -2
- data/test/crypto_provider_test/sha1_test.rb +4 -4
- data/test/crypto_provider_test/sha256_test.rb +2 -2
- data/test/crypto_provider_test/sha512_test.rb +3 -3
- data/test/crypto_provider_test/wordpress_test.rb +24 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +2 -2
- data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
- data/test/gemfiles/Gemfile.rails-5.1.x +6 -0
- data/test/gemfiles/Gemfile.rails-5.2.x +6 -0
- data/test/gemfiles/Gemfile.rails-master +6 -0
- data/test/i18n_test.rb +9 -9
- data/test/libs/affiliate.rb +2 -2
- data/test/libs/company.rb +4 -4
- data/test/libs/employee.rb +2 -2
- data/test/libs/employee_session.rb +1 -1
- data/test/libs/ldaper.rb +1 -1
- data/test/libs/project.rb +1 -1
- data/test/libs/user_session.rb +2 -2
- data/test/random_test.rb +9 -38
- data/test/session_test/activation_test.rb +7 -7
- data/test/session_test/active_record_trickery_test.rb +9 -6
- data/test/session_test/brute_force_protection_test.rb +26 -21
- data/test/session_test/callbacks_test.rb +10 -4
- data/test/session_test/cookies_test.rb +54 -20
- data/test/session_test/existence_test.rb +45 -23
- data/test/session_test/foundation_test.rb +17 -1
- data/test/session_test/http_auth_test.rb +11 -12
- data/test/session_test/id_test.rb +3 -3
- data/test/session_test/klass_test.rb +2 -2
- data/test/session_test/magic_columns_test.rb +15 -17
- data/test/session_test/magic_states_test.rb +17 -19
- data/test/session_test/params_test.rb +26 -20
- data/test/session_test/password_test.rb +11 -12
- data/test/session_test/perishability_test.rb +5 -5
- data/test/session_test/persistence_test.rb +4 -3
- data/test/session_test/scopes_test.rb +15 -9
- data/test/session_test/session_test.rb +7 -6
- data/test/session_test/timeout_test.rb +16 -14
- data/test/session_test/unauthorized_record_test.rb +3 -3
- data/test/session_test/validation_test.rb +5 -5
- data/test/test_helper.rb +115 -49
- metadata +107 -36
- data/README.rdoc +0 -232
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
- data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
@@ -1,31 +1,35 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Handles all authentication that deals with basic HTTP auth. Which is
|
3
|
+
# Handles all authentication that deals with basic HTTP auth. Which is
|
4
|
+
# authentication built into the HTTP protocol:
|
4
5
|
#
|
5
6
|
# http://username:password@whatever.com
|
6
7
|
#
|
7
|
-
# Also, if you are not comfortable letting users pass their raw username and
|
8
|
-
#
|
8
|
+
# Also, if you are not comfortable letting users pass their raw username and
|
9
|
+
# password you can always use the single access token. See
|
10
|
+
# Authlogic::Session::Params for more info.
|
9
11
|
module HttpAuth
|
10
12
|
def self.included(klass)
|
11
13
|
klass.class_eval do
|
12
14
|
extend Config
|
13
15
|
include InstanceMethods
|
14
|
-
persist :persist_by_http_auth, :
|
16
|
+
persist :persist_by_http_auth, if: :persist_by_http_auth?
|
15
17
|
end
|
16
18
|
end
|
17
|
-
|
19
|
+
|
18
20
|
# Configuration for the HTTP basic auth feature of Authlogic.
|
19
21
|
module Config
|
20
22
|
# Do you want to allow your users to log in via HTTP basic auth?
|
21
23
|
#
|
22
|
-
# I recommend keeping this enabled. The only time I feel this should be
|
23
|
-
#
|
24
|
+
# I recommend keeping this enabled. The only time I feel this should be
|
25
|
+
# disabled is if you are not comfortable having your users provide their
|
26
|
+
# raw username and password. Whatever the reason, you can disable it
|
27
|
+
# here.
|
24
28
|
#
|
25
29
|
# * <tt>Default:</tt> true
|
26
30
|
# * <tt>Accepts:</tt> Boolean
|
27
31
|
def allow_http_basic_auth(value = nil)
|
28
|
-
rw_config(:allow_http_basic_auth, value,
|
32
|
+
rw_config(:allow_http_basic_auth, value, false)
|
29
33
|
end
|
30
34
|
alias_method :allow_http_basic_auth=, :allow_http_basic_auth
|
31
35
|
|
@@ -60,39 +64,43 @@ module Authlogic
|
|
60
64
|
# * <tt>Default:</tt> 'Application'
|
61
65
|
# * <tt>Accepts:</tt> String
|
62
66
|
def http_basic_auth_realm(value = nil)
|
63
|
-
rw_config(:http_basic_auth_realm, value,
|
67
|
+
rw_config(:http_basic_auth_realm, value, "Application")
|
64
68
|
end
|
65
69
|
alias_method :http_basic_auth_realm=, :http_basic_auth_realm
|
66
70
|
end
|
67
|
-
|
71
|
+
|
68
72
|
# Instance methods for the HTTP basic auth feature of authlogic.
|
69
73
|
module InstanceMethods
|
70
74
|
private
|
71
|
-
def persist_by_http_auth?
|
72
|
-
allow_http_basic_auth? && login_field && password_field
|
73
|
-
end
|
74
|
-
|
75
|
-
def persist_by_http_auth
|
76
|
-
login_proc = Proc.new do |login, password|
|
77
|
-
if !login.blank? && !password.blank?
|
78
|
-
send("#{login_field}=", login)
|
79
|
-
send("#{password_field}=", password)
|
80
|
-
valid?
|
81
|
-
end
|
82
|
-
end
|
83
75
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
76
|
+
def persist_by_http_auth?
|
77
|
+
allow_http_basic_auth? && login_field && password_field
|
78
|
+
end
|
79
|
+
|
80
|
+
def persist_by_http_auth
|
81
|
+
login_proc = proc do |login, password|
|
82
|
+
if !login.blank? && !password.blank?
|
83
|
+
send("#{login_field}=", login)
|
84
|
+
send("#{password_field}=", password)
|
85
|
+
valid?
|
88
86
|
end
|
89
|
-
|
90
|
-
false
|
91
87
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
88
|
+
|
89
|
+
if self.class.request_http_basic_auth
|
90
|
+
controller.authenticate_or_request_with_http_basic(
|
91
|
+
self.class.http_basic_auth_realm,
|
92
|
+
&login_proc
|
93
|
+
)
|
94
|
+
else
|
95
|
+
controller.authenticate_with_http_basic(&login_proc)
|
95
96
|
end
|
97
|
+
|
98
|
+
false
|
99
|
+
end
|
100
|
+
|
101
|
+
def allow_http_basic_auth?
|
102
|
+
self.class.allow_http_basic_auth == true
|
103
|
+
end
|
96
104
|
end
|
97
105
|
end
|
98
106
|
end
|
data/lib/authlogic/session/id.rb
CHANGED
@@ -1,41 +1,53 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Allows you to separate sessions with an id, ultimately letting you create
|
3
|
+
# Allows you to separate sessions with an id, ultimately letting you create
|
4
|
+
# multiple sessions for the same user.
|
4
5
|
module Id
|
6
|
+
def initialize(*args)
|
7
|
+
@id = nil
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
5
11
|
def self.included(klass)
|
6
12
|
klass.class_eval do
|
7
13
|
attr_writer :id
|
8
14
|
end
|
9
15
|
end
|
10
|
-
|
16
|
+
|
11
17
|
# Setting the id if it is passed in the credentials.
|
12
18
|
def credentials=(value)
|
13
19
|
super
|
14
20
|
values = value.is_a?(Array) ? value : [value]
|
15
21
|
self.id = values.last if values.last.is_a?(Symbol)
|
16
22
|
end
|
17
|
-
|
18
|
-
# Allows you to set a unique identifier for your session, so that you can
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
23
|
+
|
24
|
+
# Allows you to set a unique identifier for your session, so that you can
|
25
|
+
# have more than 1 session at a time. A good example when this might be
|
26
|
+
# needed is when you want to have a normal user session and a "secure"
|
27
|
+
# user session. The secure user session would be created only when they
|
28
|
+
# want to modify their billing information, or other sensitive
|
29
|
+
# information. Similar to me.com. This requires 2 user sessions. Just use
|
30
|
+
# an id for the "secure" session and you should be good.
|
22
31
|
#
|
23
|
-
# You can set the id during initialization (see initialize for more
|
32
|
+
# You can set the id during initialization (see initialize for more
|
33
|
+
# information), or as an attribute:
|
24
34
|
#
|
25
35
|
# session.id = :my_id
|
26
36
|
#
|
27
37
|
# Just be sure and set your id before you save your session.
|
28
38
|
#
|
29
|
-
# Lastly, to retrieve your session with the id check out the find class
|
39
|
+
# Lastly, to retrieve your session with the id check out the find class
|
40
|
+
# method.
|
30
41
|
def id
|
31
42
|
@id
|
32
43
|
end
|
33
|
-
|
44
|
+
|
34
45
|
private
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
46
|
+
|
47
|
+
# Used for things like cookie_key, session_key, etc.
|
48
|
+
def build_key(last_part)
|
49
|
+
[id, super].compact.join("_")
|
50
|
+
end
|
39
51
|
end
|
40
52
|
end
|
41
|
-
end
|
53
|
+
end
|
@@ -16,7 +16,8 @@ module Authlogic
|
|
16
16
|
module Config
|
17
17
|
# Lets you change which model to use for authentication.
|
18
18
|
#
|
19
|
-
# * <tt>Default:</tt> inferred from the class name. UserSession would
|
19
|
+
# * <tt>Default:</tt> inferred from the class name. UserSession would
|
20
|
+
# automatically try User
|
20
21
|
# * <tt>Accepts:</tt> an ActiveRecord class
|
21
22
|
def authenticate_with(klass)
|
22
23
|
@klass_name = klass.name
|
@@ -24,9 +25,10 @@ module Authlogic
|
|
24
25
|
end
|
25
26
|
alias_method :authenticate_with=, :authenticate_with
|
26
27
|
|
27
|
-
# The name of the class that this session is authenticating with. For
|
28
|
-
#
|
29
|
-
#
|
28
|
+
# The name of the class that this session is authenticating with. For
|
29
|
+
# example, the UserSession class will authenticate with the User class
|
30
|
+
# unless you specify otherwise in your configuration. See
|
31
|
+
# authenticate_with for information on how to change this value.
|
30
32
|
def klass
|
31
33
|
@klass ||= klass_name ? klass_name.constantize : nil
|
32
34
|
end
|
@@ -40,7 +42,8 @@ module Authlogic
|
|
40
42
|
end
|
41
43
|
|
42
44
|
module InstanceMethods
|
43
|
-
# Creating an alias method for the "record" method based on the klass
|
45
|
+
# Creating an alias method for the "record" method based on the klass
|
46
|
+
# name, so that we can do:
|
44
47
|
#
|
45
48
|
# session.user
|
46
49
|
#
|
@@ -48,7 +51,7 @@ module Authlogic
|
|
48
51
|
#
|
49
52
|
# session.record
|
50
53
|
def initialize(*args)
|
51
|
-
|
54
|
+
unless self.class.configured_klass_methods
|
52
55
|
self.class.send(:alias_method, klass_name.demodulize.underscore.to_sym, :record)
|
53
56
|
self.class.configured_klass_methods = true
|
54
57
|
end
|
@@ -56,14 +59,15 @@ module Authlogic
|
|
56
59
|
end
|
57
60
|
|
58
61
|
private
|
59
|
-
def klass
|
60
|
-
self.class.klass
|
61
|
-
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
def klass
|
64
|
+
self.class.klass
|
65
|
+
end
|
66
|
+
|
67
|
+
def klass_name
|
68
|
+
self.class.klass_name
|
69
|
+
end
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
69
|
-
end
|
73
|
+
end
|
@@ -1,33 +1,39 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Just like ActiveRecord has "magic" columns, such as: created_at and updated_at.
|
3
|
+
# Just like ActiveRecord has "magic" columns, such as: created_at and updated_at.
|
4
|
+
# Authlogic has its own "magic" columns too:
|
4
5
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
6
|
+
# * login_count - Increased every time an explicit login is made. This will *NOT*
|
7
|
+
# increase if logging in by a session, cookie, or basic http auth
|
8
|
+
# * failed_login_count - This increases for each consecutive failed login. See
|
9
|
+
# Authlogic::Session::BruteForceProtection and the consecutive_failed_logins_limit
|
10
|
+
# config option for more details.
|
11
|
+
# * last_request_at - Updates every time the user logs in, either by explicitly
|
12
|
+
# logging in, or logging in by cookie, session, or http auth
|
13
|
+
# * current_login_at - Updates with the current time when an explicit login is made.
|
14
|
+
# * last_login_at - Updates with the value of current_login_at before it is reset.
|
15
|
+
# * current_login_ip - Updates with the request ip when an explicit login is made.
|
16
|
+
# * last_login_ip - Updates with the value of current_login_ip before it is reset.
|
13
17
|
module MagicColumns
|
14
18
|
def self.included(klass)
|
15
19
|
klass.class_eval do
|
16
20
|
extend Config
|
17
21
|
include InstanceMethods
|
18
|
-
after_persisting :set_last_request_at, :
|
22
|
+
after_persisting :set_last_request_at, if: :set_last_request_at?
|
19
23
|
validate :increase_failed_login_count
|
20
24
|
before_save :update_info
|
21
|
-
before_save :set_last_request_at, :
|
25
|
+
before_save :set_last_request_at, if: :set_last_request_at?
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
25
29
|
# Configuration for the magic columns feature.
|
26
30
|
module Config
|
27
|
-
# Every time a session is found the last_request_at field for that record is
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
+
# Every time a session is found the last_request_at field for that record is
|
32
|
+
# updated with the current time, if that field exists. If you want to limit how
|
33
|
+
# frequent that field is updated specify the threshold here. For example, if your
|
34
|
+
# user is making a request every 5 seconds, and you feel this is too frequent, and
|
35
|
+
# feel a minute is a good threshold. Set this to 1.minute. Once a minute has
|
36
|
+
# passed in between requests the field will be updated.
|
31
37
|
#
|
32
38
|
# * <tt>Default:</tt> 0
|
33
39
|
# * <tt>Accepts:</tt> integer representing time in seconds
|
@@ -37,63 +43,76 @@ module Authlogic
|
|
37
43
|
alias_method :last_request_at_threshold=, :last_request_at_threshold
|
38
44
|
end
|
39
45
|
|
40
|
-
# The methods available for an Authlogic::Session::Base object that make
|
46
|
+
# The methods available for an Authlogic::Session::Base object that make
|
47
|
+
# up the magic columns feature.
|
41
48
|
module InstanceMethods
|
42
49
|
private
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
50
|
+
|
51
|
+
def clear_failed_login_count
|
52
|
+
if record.respond_to?(:failed_login_count)
|
53
|
+
record.failed_login_count = 0
|
48
54
|
end
|
55
|
+
end
|
49
56
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
57
|
+
def increase_failed_login_count
|
58
|
+
if invalid_password? && attempted_record.respond_to?(:failed_login_count)
|
59
|
+
attempted_record.failed_login_count ||= 0
|
60
|
+
attempted_record.failed_login_count += 1
|
61
|
+
end
|
62
|
+
end
|
54
63
|
|
55
|
-
|
56
|
-
|
57
|
-
|
64
|
+
def increment_login_cout
|
65
|
+
if record.respond_to?(:login_count)
|
66
|
+
record.login_count = (record.login_count.blank? ? 1 : record.login_count + 1)
|
67
|
+
end
|
68
|
+
end
|
58
69
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
70
|
+
def update_info
|
71
|
+
increment_login_cout
|
72
|
+
clear_failed_login_count
|
73
|
+
update_login_timestamps
|
74
|
+
update_login_ip_addresses
|
75
|
+
end
|
63
76
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
77
|
+
def update_login_ip_addresses
|
78
|
+
if record.respond_to?(:current_login_ip)
|
79
|
+
record.last_login_ip = record.current_login_ip if record.respond_to?(:last_login_ip)
|
80
|
+
record.current_login_ip = controller.request.ip
|
68
81
|
end
|
82
|
+
end
|
69
83
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
# For example, what if you had a javascript function that polled the server updating how much time is left in their
|
76
|
-
# session before it times out. Obviously you would want to ignore this request, because then the user would never time out.
|
77
|
-
# So you can do something like this in your controller:
|
78
|
-
#
|
79
|
-
# def last_request_update_allowed?
|
80
|
-
# action_name != "update_session_time_left"
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
# You can do whatever you want with that method.
|
84
|
-
def set_last_request_at? # :doc:
|
85
|
-
return false if !record || !klass.column_names.include?("last_request_at")
|
86
|
-
return controller.last_request_update_allowed? if controller.responds_to_last_request_update_allowed?
|
87
|
-
record.last_request_at.blank? || last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
|
84
|
+
def update_login_timestamps
|
85
|
+
if record.respond_to?(:current_login_at)
|
86
|
+
record.last_login_at = record.current_login_at if record.respond_to?(:last_login_at)
|
87
|
+
record.current_login_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
|
88
88
|
end
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
91
|
+
# This method lets authlogic know whether it should allow the
|
92
|
+
# last_request_at field to be updated with the current time.
|
93
|
+
#
|
94
|
+
# See also `last_request_update_allowed?` in
|
95
|
+
# `Authlogic::ControllerAdapters::AbstractAdapter`
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
def set_last_request_at?
|
99
|
+
if !record || !klass.column_names.include?("last_request_at")
|
100
|
+
return false
|
92
101
|
end
|
93
|
-
|
94
|
-
|
95
|
-
self.class.last_request_at_threshold
|
102
|
+
unless controller.last_request_update_allowed?
|
103
|
+
return false
|
96
104
|
end
|
105
|
+
record.last_request_at.blank? ||
|
106
|
+
last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
|
107
|
+
end
|
108
|
+
|
109
|
+
def set_last_request_at
|
110
|
+
record.last_request_at = klass.default_timezone == :utc ? Time.now.utc : Time.now
|
111
|
+
end
|
112
|
+
|
113
|
+
def last_request_at_threshold
|
114
|
+
self.class.last_request_at_threshold
|
115
|
+
end
|
97
116
|
end
|
98
117
|
end
|
99
118
|
end
|
@@ -1,32 +1,41 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Authlogic tries to check the state of the record before creating the session. If
|
3
|
+
# Authlogic tries to check the state of the record before creating the session. If
|
4
|
+
# your record responds to the following methods and any of them return false,
|
5
|
+
# validation will fail:
|
4
6
|
#
|
5
7
|
# Method name Description
|
6
8
|
# active? Is the record marked as active?
|
7
9
|
# approved? Has the record been approved?
|
8
|
-
# confirmed? Has the record been
|
10
|
+
# confirmed? Has the record been confirmed?
|
9
11
|
#
|
10
|
-
# Authlogic does nothing to define these methods for you, its up to you to define what
|
12
|
+
# Authlogic does nothing to define these methods for you, its up to you to define what
|
13
|
+
# they mean. If your object responds to these methods Authlogic will use them,
|
14
|
+
# otherwise they are ignored.
|
11
15
|
#
|
12
|
-
# What's neat about this is that these are checked upon any type of login. When
|
13
|
-
#
|
16
|
+
# What's neat about this is that these are checked upon any type of login. When
|
17
|
+
# logging in explicitly, by cookie, session, or basic http auth. So if you mark a user
|
18
|
+
# inactive in the middle of their session they wont be logged back in next time they
|
19
|
+
# refresh the page. Giving you complete control.
|
14
20
|
#
|
15
|
-
# Need Authlogic to check your own "state"? No problem, check out the hooks section
|
21
|
+
# Need Authlogic to check your own "state"? No problem, check out the hooks section
|
22
|
+
# below. Add in a before_validation to do your own checking. The sky is the limit.
|
16
23
|
module MagicStates
|
17
24
|
def self.included(klass)
|
18
25
|
klass.class_eval do
|
19
26
|
extend Config
|
20
27
|
include InstanceMethods
|
21
|
-
validate :validate_magic_states, :
|
28
|
+
validate :validate_magic_states, unless: :disable_magic_states?
|
22
29
|
end
|
23
30
|
end
|
24
|
-
|
31
|
+
|
25
32
|
# Configuration for the magic states feature.
|
26
33
|
module Config
|
27
|
-
# Set this to true if you want to disable the checking of active?, approved?, and
|
28
|
-
#
|
29
|
-
#
|
34
|
+
# Set this to true if you want to disable the checking of active?, approved?, and
|
35
|
+
# confirmed? on your record. This is more or less of a convenience feature, since
|
36
|
+
# 99% of the time if those methods exist and return false you will not want the
|
37
|
+
# user logging in. You could easily accomplish this same thing with a
|
38
|
+
# before_validation method or other callbacks.
|
30
39
|
#
|
31
40
|
# * <tt>Default:</tt> false
|
32
41
|
# * <tt>Accepts:</tt> Boolean
|
@@ -35,25 +44,39 @@ module Authlogic
|
|
35
44
|
end
|
36
45
|
alias_method :disable_magic_states=, :disable_magic_states
|
37
46
|
end
|
38
|
-
|
39
|
-
# The methods available for an Authlogic::Session::Base object that make up the
|
47
|
+
|
48
|
+
# The methods available for an Authlogic::Session::Base object that make up the
|
49
|
+
# magic states feature.
|
40
50
|
module InstanceMethods
|
41
51
|
private
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
|
53
|
+
def disable_magic_states?
|
54
|
+
self.class.disable_magic_states == true
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api private
|
58
|
+
def required_magic_states_for(record)
|
59
|
+
%i[active approved confirmed].select { |state|
|
60
|
+
record.respond_to?("#{state}?")
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_magic_states
|
65
|
+
return true if attempted_record.nil?
|
66
|
+
required_magic_states_for(attempted_record).each do |required_status|
|
67
|
+
next if attempted_record.send("#{required_status}?")
|
68
|
+
errors.add(
|
69
|
+
:base,
|
70
|
+
I18n.t(
|
71
|
+
"error_messages.not_#{required_status}",
|
72
|
+
default: "Your account is not #{required_status}"
|
73
|
+
)
|
74
|
+
)
|
75
|
+
return false
|
55
76
|
end
|
77
|
+
true
|
78
|
+
end
|
56
79
|
end
|
57
80
|
end
|
58
81
|
end
|
59
|
-
end
|
82
|
+
end
|