authlogic 4.4.2 → 5.0.3
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/lib/authlogic.rb +4 -28
- data/lib/authlogic/acts_as_authentic/base.rb +3 -18
- data/lib/authlogic/acts_as_authentic/email.rb +3 -170
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +3 -1
- data/lib/authlogic/acts_as_authentic/login.rb +7 -174
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +7 -4
- data/lib/authlogic/acts_as_authentic/password.rb +54 -253
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +8 -5
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -4
- data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
- data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +36 -20
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +8 -6
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +10 -8
- data/lib/authlogic/config.rb +9 -1
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +7 -4
- data/lib/authlogic/controller_adapters/rack_adapter.rb +2 -0
- data/lib/authlogic/controller_adapters/rails_adapter.rb +19 -19
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +6 -0
- data/lib/authlogic/cookie_credentials.rb +63 -0
- data/lib/authlogic/crypto_providers.rb +5 -20
- data/lib/authlogic/crypto_providers/bcrypt.rb +3 -3
- data/lib/authlogic/crypto_providers/md5.rb +3 -6
- data/lib/authlogic/crypto_providers/scrypt.rb +2 -0
- data/lib/authlogic/crypto_providers/sha1.rb +4 -6
- data/lib/authlogic/crypto_providers/sha256.rb +2 -0
- data/lib/authlogic/crypto_providers/sha512.rb +6 -5
- data/lib/authlogic/i18n.rb +3 -1
- data/lib/authlogic/i18n/translator.rb +3 -0
- data/lib/authlogic/random.rb +2 -0
- data/lib/authlogic/session/base.rb +2087 -39
- data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
- data/lib/authlogic/test_case.rb +4 -0
- data/lib/authlogic/test_case/mock_controller.rb +2 -0
- data/lib/authlogic/test_case/mock_cookie_jar.rb +7 -0
- data/lib/authlogic/test_case/mock_logger.rb +2 -0
- data/lib/authlogic/test_case/mock_request.rb +2 -0
- data/lib/authlogic/test_case/rails_request_adapter.rb +2 -0
- data/lib/authlogic/version.rb +2 -1
- metadata +136 -182
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -28
- data/.github/ISSUE_TEMPLATE/feature_proposal.md +0 -32
- data/.github/triage.md +0 -86
- data/.gitignore +0 -15
- data/.rubocop.yml +0 -133
- data/.rubocop_todo.yml +0 -74
- data/.travis.yml +0 -24
- data/CHANGELOG.md +0 -326
- data/CONTRIBUTING.md +0 -91
- data/Gemfile +0 -6
- data/LICENSE +0 -20
- data/README.md +0 -439
- data/Rakefile +0 -21
- data/UPGRADING.md +0 -22
- data/authlogic.gemspec +0 -40
- data/doc/use_normal_rails_validation.md +0 -82
- data/gemfiles/Gemfile.rails-4.2.x +0 -6
- data/gemfiles/Gemfile.rails-5.1.x +0 -6
- data/gemfiles/Gemfile.rails-5.2.x +0 -6
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -106
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -35
- data/lib/authlogic/authenticates_many/association.rb +0 -50
- data/lib/authlogic/authenticates_many/base.rb +0 -81
- data/lib/authlogic/crypto_providers/aes256.rb +0 -71
- data/lib/authlogic/crypto_providers/wordpress.rb +0 -72
- data/lib/authlogic/regex.rb +0 -79
- data/lib/authlogic/session/activation.rb +0 -73
- data/lib/authlogic/session/active_record_trickery.rb +0 -65
- data/lib/authlogic/session/brute_force_protection.rb +0 -127
- data/lib/authlogic/session/callbacks.rb +0 -153
- data/lib/authlogic/session/cookies.rb +0 -296
- data/lib/authlogic/session/existence.rb +0 -103
- data/lib/authlogic/session/foundation.rb +0 -105
- data/lib/authlogic/session/http_auth.rb +0 -107
- data/lib/authlogic/session/id.rb +0 -53
- data/lib/authlogic/session/klass.rb +0 -73
- data/lib/authlogic/session/magic_columns.rb +0 -119
- data/lib/authlogic/session/magic_states.rb +0 -82
- data/lib/authlogic/session/params.rb +0 -130
- data/lib/authlogic/session/password.rb +0 -318
- data/lib/authlogic/session/perishable_token.rb +0 -24
- data/lib/authlogic/session/persistence.rb +0 -77
- data/lib/authlogic/session/priority_record.rb +0 -38
- data/lib/authlogic/session/scopes.rb +0 -138
- data/lib/authlogic/session/session.rb +0 -77
- data/lib/authlogic/session/timeout.rb +0 -103
- data/lib/authlogic/session/unauthorized_record.rb +0 -56
- data/lib/authlogic/session/validation.rb +0 -93
- data/test/acts_as_authentic_test/base_test.rb +0 -27
- data/test/acts_as_authentic_test/email_test.rb +0 -241
- data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -64
- data/test/acts_as_authentic_test/login_test.rb +0 -153
- data/test/acts_as_authentic_test/magic_columns_test.rb +0 -29
- data/test/acts_as_authentic_test/password_test.rb +0 -263
- data/test/acts_as_authentic_test/perishable_token_test.rb +0 -98
- data/test/acts_as_authentic_test/persistence_token_test.rb +0 -62
- data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -48
- data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -150
- data/test/acts_as_authentic_test/single_access_test.rb +0 -46
- data/test/adapter_test.rb +0 -23
- data/test/authenticates_many_test.rb +0 -33
- data/test/config_test.rb +0 -38
- data/test/crypto_provider_test/aes256_test.rb +0 -16
- data/test/crypto_provider_test/bcrypt_test.rb +0 -16
- data/test/crypto_provider_test/scrypt_test.rb +0 -16
- data/test/crypto_provider_test/sha1_test.rb +0 -25
- data/test/crypto_provider_test/sha256_test.rb +0 -16
- data/test/crypto_provider_test/sha512_test.rb +0 -16
- data/test/crypto_provider_test/wordpress_test.rb +0 -26
- data/test/fixtures/companies.yml +0 -5
- data/test/fixtures/employees.yml +0 -17
- data/test/fixtures/projects.yml +0 -3
- data/test/fixtures/users.yml +0 -41
- data/test/i18n/lol.yml +0 -4
- data/test/i18n_test.rb +0 -35
- data/test/libs/affiliate.rb +0 -9
- data/test/libs/company.rb +0 -8
- data/test/libs/employee.rb +0 -9
- data/test/libs/employee_session.rb +0 -4
- data/test/libs/ldaper.rb +0 -5
- data/test/libs/project.rb +0 -5
- data/test/libs/user.rb +0 -9
- data/test/libs/user_session.rb +0 -27
- data/test/random_test.rb +0 -15
- data/test/session_test/activation_test.rb +0 -45
- data/test/session_test/active_record_trickery_test.rb +0 -78
- data/test/session_test/brute_force_protection_test.rb +0 -110
- data/test/session_test/callbacks_test.rb +0 -42
- data/test/session_test/cookies_test.rb +0 -226
- data/test/session_test/credentials_test.rb +0 -0
- data/test/session_test/existence_test.rb +0 -88
- data/test/session_test/foundation_test.rb +0 -24
- data/test/session_test/http_auth_test.rb +0 -60
- data/test/session_test/id_test.rb +0 -19
- data/test/session_test/klass_test.rb +0 -42
- data/test/session_test/magic_columns_test.rb +0 -62
- data/test/session_test/magic_states_test.rb +0 -60
- data/test/session_test/params_test.rb +0 -61
- data/test/session_test/password_test.rb +0 -107
- data/test/session_test/perishability_test.rb +0 -17
- data/test/session_test/persistence_test.rb +0 -35
- data/test/session_test/scopes_test.rb +0 -68
- data/test/session_test/session_test.rb +0 -80
- data/test/session_test/timeout_test.rb +0 -84
- data/test/session_test/unauthorized_record_test.rb +0 -15
- data/test/session_test/validation_test.rb +0 -25
- data/test/test_helper.rb +0 -272
@@ -1,24 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Maintains the perishable token, which is helpful for confirming records or
|
4
|
-
# authorizing records to reset their password. All that this module does is
|
5
|
-
# reset it after a session have been saved, just keep it changing. The more
|
6
|
-
# it changes, the tighter the security.
|
7
|
-
#
|
8
|
-
# See Authlogic::ActsAsAuthentic::PerishableToken for more information.
|
9
|
-
module PerishableToken
|
10
|
-
def self.included(klass)
|
11
|
-
klass.after_save :reset_perishable_token!
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def reset_perishable_token!
|
17
|
-
if record.respond_to?(:reset_perishable_token) &&
|
18
|
-
!record.disable_perishable_token_maintenance?
|
19
|
-
record.reset_perishable_token
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Responsible for allowing you to persist your sessions.
|
4
|
-
module Persistence
|
5
|
-
def self.included(klass)
|
6
|
-
klass.class_eval do
|
7
|
-
extend ClassMethods
|
8
|
-
include InstanceMethods
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
# This is how you persist a session. This finds the record for the
|
14
|
-
# current session using a variety of methods. It basically tries to "log
|
15
|
-
# in" the user without the user having to explicitly log in. Check out
|
16
|
-
# the other Authlogic::Session modules for more information.
|
17
|
-
#
|
18
|
-
# The best way to use this method is something like:
|
19
|
-
#
|
20
|
-
# helper_method :current_user_session, :current_user
|
21
|
-
#
|
22
|
-
# def current_user_session
|
23
|
-
# return @current_user_session if defined?(@current_user_session)
|
24
|
-
# @current_user_session = UserSession.find
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
# def current_user
|
28
|
-
# return @current_user if defined?(@current_user)
|
29
|
-
# @current_user = current_user_session && current_user_session.user
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# Also, this method accepts a single parameter as the id, to find
|
33
|
-
# session that you marked with an id:
|
34
|
-
#
|
35
|
-
# UserSession.find(:secure)
|
36
|
-
#
|
37
|
-
# See the id method for more information on ids.
|
38
|
-
def find(id = nil, priority_record = nil)
|
39
|
-
session = new({ priority_record: priority_record }, id)
|
40
|
-
session.priority_record = priority_record
|
41
|
-
if session.persisting?
|
42
|
-
session
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
module InstanceMethods
|
48
|
-
# Returns boolean indicating if the session is being persisted or not,
|
49
|
-
# meaning the user does not have to explicitly log in in order to be
|
50
|
-
# logged in.
|
51
|
-
#
|
52
|
-
# If the session has no associated record, it will try to find a record
|
53
|
-
# and persist the session.
|
54
|
-
#
|
55
|
-
# This is the method that the class level method find uses to ultimately
|
56
|
-
# persist the session.
|
57
|
-
def persisting?
|
58
|
-
return true unless record.nil?
|
59
|
-
self.attempted_record = nil
|
60
|
-
self.remember_me = cookie_credentials_remember_me?
|
61
|
-
before_persisting
|
62
|
-
persist
|
63
|
-
ensure_authentication_attempted
|
64
|
-
if errors.empty? && !attempted_record.nil?
|
65
|
-
self.record = attempted_record
|
66
|
-
after_persisting
|
67
|
-
save_record
|
68
|
-
self.new_session = false
|
69
|
-
true
|
70
|
-
else
|
71
|
-
false
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# The point of this module is to avoid the StaleObjectError raised when
|
4
|
-
# lock_version is implemented in ActiveRecord. We accomplish this by using a
|
5
|
-
# "priority record". Meaning this record is used if possible, it gets
|
6
|
-
# priority. This way we don't save a record behind the scenes thus making an
|
7
|
-
# object being used stale.
|
8
|
-
module PriorityRecord
|
9
|
-
def self.included(klass)
|
10
|
-
klass.class_eval do
|
11
|
-
attr_accessor :priority_record
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# Setting priority record if it is passed. The only way it can be passed
|
16
|
-
# is through an array:
|
17
|
-
#
|
18
|
-
# session.credentials = [real_user_object, priority_user_object]
|
19
|
-
def credentials=(value)
|
20
|
-
super
|
21
|
-
values = value.is_a?(Array) ? value : [value]
|
22
|
-
self.priority_record = values[1] if values[1].class < ::ActiveRecord::Base
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def attempted_record=(value)
|
28
|
-
value = priority_record if value == priority_record
|
29
|
-
super
|
30
|
-
end
|
31
|
-
|
32
|
-
def save_record(alternate_record = nil)
|
33
|
-
r = alternate_record || record
|
34
|
-
super if r != priority_record
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,138 +0,0 @@
|
|
1
|
-
require "request_store"
|
2
|
-
|
3
|
-
module Authlogic
|
4
|
-
module Session
|
5
|
-
# Authentication can be scoped, and it's easy, you just need to define how you want to
|
6
|
-
# scope everything. This should help you:
|
7
|
-
#
|
8
|
-
# 1. Want to scope by a parent object? Ex: An account has many users.
|
9
|
-
# Checkout Authlogic::AuthenticatesMany
|
10
|
-
# 2. Want to scope the validations in your model? Ex: 2 users can have the same login
|
11
|
-
# under different accounts. See Authlogic::ActsAsAuthentic::Scope
|
12
|
-
module Scopes # :nodoc:
|
13
|
-
def self.included(klass)
|
14
|
-
klass.class_eval do
|
15
|
-
extend ClassMethods
|
16
|
-
include InstanceMethods
|
17
|
-
attr_writer :scope
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# = Scopes
|
22
|
-
module ClassMethods
|
23
|
-
# The current scope set, should be used in the block passed to with_scope.
|
24
|
-
def scope
|
25
|
-
RequestStore.store[:authlogic_scope]
|
26
|
-
end
|
27
|
-
|
28
|
-
# What with_scopes focuses on is scoping the query when finding the
|
29
|
-
# object and the name of the cookie / session. It works very similar to
|
30
|
-
# ActiveRecord::Base#with_scopes. It accepts a hash with any of the
|
31
|
-
# following options:
|
32
|
-
#
|
33
|
-
# * <tt>find_options:</tt> any options you can pass into ActiveRecord::Base.find.
|
34
|
-
# This is used when trying to find the record.
|
35
|
-
# * <tt>id:</tt> The id of the session, this gets merged with the real id. For
|
36
|
-
# information ids see the id method.
|
37
|
-
#
|
38
|
-
# Here is how you use it:
|
39
|
-
#
|
40
|
-
# ```
|
41
|
-
# UserSession.with_scope(find_options: {conditions: "account_id = 2"}, id: "account_2") do
|
42
|
-
# UserSession.find
|
43
|
-
# end
|
44
|
-
# ```
|
45
|
-
#
|
46
|
-
# Essentially what the above does is scope the searching of the object
|
47
|
-
# with the sql you provided. So instead of:
|
48
|
-
#
|
49
|
-
# ```
|
50
|
-
# User.where("login = 'ben'").first
|
51
|
-
# ```
|
52
|
-
#
|
53
|
-
# it would be:
|
54
|
-
#
|
55
|
-
# ```
|
56
|
-
# User.where("login = 'ben' and account_id = 2").first
|
57
|
-
# ```
|
58
|
-
#
|
59
|
-
# You will also notice the :id option. This works just like the id
|
60
|
-
# method. It scopes your cookies. So the name of your cookie will be:
|
61
|
-
#
|
62
|
-
# account_2_user_credentials
|
63
|
-
#
|
64
|
-
# instead of:
|
65
|
-
#
|
66
|
-
# user_credentials
|
67
|
-
#
|
68
|
-
# What is also nifty about scoping with an :id is that it merges your
|
69
|
-
# id's. So if you do:
|
70
|
-
#
|
71
|
-
# UserSession.with_scope(
|
72
|
-
# find_options: { conditions: "account_id = 2"},
|
73
|
-
# id: "account_2"
|
74
|
-
# ) do
|
75
|
-
# session = UserSession.new
|
76
|
-
# session.id = :secure
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# The name of your cookies will be:
|
80
|
-
#
|
81
|
-
# secure_account_2_user_credentials
|
82
|
-
def with_scope(options = {})
|
83
|
-
raise ArgumentError.new("You must provide a block") unless block_given?
|
84
|
-
self.scope = options
|
85
|
-
result = yield
|
86
|
-
self.scope = nil
|
87
|
-
result
|
88
|
-
end
|
89
|
-
|
90
|
-
private
|
91
|
-
|
92
|
-
def scope=(value)
|
93
|
-
RequestStore.store[:authlogic_scope] = value
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
module InstanceMethods
|
98
|
-
# Setting the scope if it exists upon instantiation.
|
99
|
-
def initialize(*args)
|
100
|
-
self.scope = self.class.scope
|
101
|
-
super
|
102
|
-
end
|
103
|
-
|
104
|
-
# The scope of the current object
|
105
|
-
def scope
|
106
|
-
@scope ||= {}
|
107
|
-
end
|
108
|
-
|
109
|
-
private
|
110
|
-
|
111
|
-
# Used for things like cookie_key, session_key, etc.
|
112
|
-
def build_key(last_part)
|
113
|
-
[scope[:id], super].compact.join("_")
|
114
|
-
end
|
115
|
-
|
116
|
-
# `args[0]` is the name of an AR method, like
|
117
|
-
# `find_by_single_access_token`.
|
118
|
-
def search_for_record(*args)
|
119
|
-
search_scope.scoping do
|
120
|
-
klass.send(*args)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# Returns an AR relation representing the scope of the search. The
|
125
|
-
# relation is either provided directly by, or defined by
|
126
|
-
# `find_options`.
|
127
|
-
def search_scope
|
128
|
-
if scope[:find_options].is_a?(ActiveRecord::Relation)
|
129
|
-
scope[:find_options]
|
130
|
-
else
|
131
|
-
conditions = scope[:find_options] && scope[:find_options][:conditions] || {}
|
132
|
-
klass.send(:where, conditions)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Handles all parts of authentication that deal with sessions. Such as persisting a
|
4
|
-
# session and saving / destroy a session.
|
5
|
-
module Session
|
6
|
-
def self.included(klass)
|
7
|
-
klass.class_eval do
|
8
|
-
extend Config
|
9
|
-
include InstanceMethods
|
10
|
-
persist :persist_by_session
|
11
|
-
after_save :update_session
|
12
|
-
after_destroy :update_session
|
13
|
-
after_persisting :update_session, unless: :single_access?
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Configuration for the session feature.
|
18
|
-
module Config
|
19
|
-
# Works exactly like cookie_key, but for sessions. See cookie_key for more info.
|
20
|
-
#
|
21
|
-
# * <tt>Default:</tt> cookie_key
|
22
|
-
# * <tt>Accepts:</tt> Symbol or String
|
23
|
-
def session_key(value = nil)
|
24
|
-
rw_config(:session_key, value, cookie_key)
|
25
|
-
end
|
26
|
-
alias_method :session_key=, :session_key
|
27
|
-
end
|
28
|
-
|
29
|
-
# Instance methods for the session feature.
|
30
|
-
module InstanceMethods
|
31
|
-
private
|
32
|
-
|
33
|
-
# Tries to validate the session from information in the session
|
34
|
-
def persist_by_session
|
35
|
-
persistence_token, record_id = session_credentials
|
36
|
-
if !persistence_token.nil?
|
37
|
-
record = persist_by_session_search(persistence_token, record_id)
|
38
|
-
if record && record.persistence_token == persistence_token
|
39
|
-
self.unauthorized_record = record
|
40
|
-
end
|
41
|
-
valid?
|
42
|
-
else
|
43
|
-
false
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Allow finding by persistence token, because when records are created
|
48
|
-
# the session is maintained in a before_save, when there is no id.
|
49
|
-
# This is done for performance reasons and to save on queries.
|
50
|
-
def persist_by_session_search(persistence_token, record_id)
|
51
|
-
if record_id.nil?
|
52
|
-
search_for_record("find_by_persistence_token", persistence_token.to_s)
|
53
|
-
else
|
54
|
-
search_for_record("find_by_#{klass.primary_key}", record_id.to_s)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def session_credentials
|
59
|
-
[
|
60
|
-
controller.session[session_key],
|
61
|
-
controller.session["#{session_key}_#{klass.primary_key}"]
|
62
|
-
].collect { |i| i.nil? ? i : i.to_s }.compact
|
63
|
-
end
|
64
|
-
|
65
|
-
def session_key
|
66
|
-
build_key(self.class.session_key)
|
67
|
-
end
|
68
|
-
|
69
|
-
def update_session
|
70
|
-
controller.session[session_key] = record && record.persistence_token
|
71
|
-
compound_key = "#{session_key}_#{klass.primary_key}"
|
72
|
-
controller.session[compound_key] = record && record.send(record.class.primary_key)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
module Authlogic
|
2
|
-
module Session
|
3
|
-
# Think about financial websites, if you are inactive for a certain period
|
4
|
-
# of time you will be asked to log back in on your next request. You can do
|
5
|
-
# this with Authlogic easily, there are 2 parts to this:
|
6
|
-
#
|
7
|
-
# 1. Define the timeout threshold:
|
8
|
-
#
|
9
|
-
# acts_as_authentic do |c|
|
10
|
-
# c.logged_in_timeout = 10.minutes # default is 10.minutes
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# 2. Enable logging out on timeouts
|
14
|
-
#
|
15
|
-
# class UserSession < Authlogic::Session::Base
|
16
|
-
# logout_on_timeout true # default if false
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# This will require a user to log back in if they are inactive for more than
|
20
|
-
# 10 minutes. In order for this feature to be used you must have a
|
21
|
-
# last_request_at datetime column in your table for whatever model you are
|
22
|
-
# authenticating with.
|
23
|
-
module Timeout
|
24
|
-
def self.included(klass)
|
25
|
-
klass.class_eval do
|
26
|
-
extend Config
|
27
|
-
include InstanceMethods
|
28
|
-
before_persisting :reset_stale_state
|
29
|
-
after_persisting :enforce_timeout
|
30
|
-
attr_accessor :stale_record
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Configuration for the timeout feature.
|
35
|
-
module Config
|
36
|
-
# With acts_as_authentic you get a :logged_in_timeout configuration
|
37
|
-
# option. If this is set, after this amount of time has passed the user
|
38
|
-
# will be marked as logged out. Obviously, since web based apps are on a
|
39
|
-
# per request basis, we have to define a time limit threshold that
|
40
|
-
# determines when we consider a user to be "logged out". Meaning, if
|
41
|
-
# they login and then leave the website, when do mark them as logged
|
42
|
-
# out? I recommend just using this as a fun feature on your website or
|
43
|
-
# reports, giving you a ballpark number of users logged in and active.
|
44
|
-
# This is not meant to be a dead accurate representation of a user's
|
45
|
-
# logged in state, since there is really no real way to do this with web
|
46
|
-
# based apps. Think about a user that logs in and doesn't log out. There
|
47
|
-
# is no action that tells you that the user isn't technically still
|
48
|
-
# logged in and active.
|
49
|
-
#
|
50
|
-
# That being said, you can use that feature to require a new login if
|
51
|
-
# their session times out. Similar to how financial sites work. Just set
|
52
|
-
# this option to true and if your record returns true for stale? then
|
53
|
-
# they will be required to log back in.
|
54
|
-
#
|
55
|
-
# Lastly, UserSession.find will still return an object if the session is
|
56
|
-
# stale, but you will not get a record. This allows you to determine if
|
57
|
-
# the user needs to log back in because their session went stale, or
|
58
|
-
# because they just aren't logged in. Just call
|
59
|
-
# current_user_session.stale? as your flag.
|
60
|
-
#
|
61
|
-
# * <tt>Default:</tt> false
|
62
|
-
# * <tt>Accepts:</tt> Boolean
|
63
|
-
def logout_on_timeout(value = nil)
|
64
|
-
rw_config(:logout_on_timeout, value, false)
|
65
|
-
end
|
66
|
-
alias_method :logout_on_timeout=, :logout_on_timeout
|
67
|
-
end
|
68
|
-
|
69
|
-
# Instance methods for the timeout feature.
|
70
|
-
module InstanceMethods
|
71
|
-
# Tells you if the record is stale or not. Meaning the record has timed
|
72
|
-
# out. This will only return true if you set logout_on_timeout to true
|
73
|
-
# in your configuration. Basically how a bank website works. If you
|
74
|
-
# aren't active over a certain period of time your session becomes stale
|
75
|
-
# and requires you to log back in.
|
76
|
-
def stale?
|
77
|
-
if remember_me?
|
78
|
-
remember_me_expired?
|
79
|
-
else
|
80
|
-
!stale_record.nil? || (logout_on_timeout? && record && record.logged_out?)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
private
|
85
|
-
|
86
|
-
def reset_stale_state
|
87
|
-
self.stale_record = nil
|
88
|
-
end
|
89
|
-
|
90
|
-
def enforce_timeout
|
91
|
-
if stale?
|
92
|
-
self.stale_record = record
|
93
|
-
self.record = nil
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def logout_on_timeout?
|
98
|
-
self.class.logout_on_timeout == true
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|