authlogic 3.5.0 → 3.8.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.
- data/.github/ISSUE_TEMPLATE.md +13 -0
- data/.rubocop_todo.yml +1 -37
- data/.travis.yml +15 -6
- data/CHANGELOG.md +2 -130
- data/CONTRIBUTING.md +13 -2
- data/README.md +2 -3
- data/authlogic.gemspec +4 -5
- data/lib/authlogic/acts_as_authentic/base.rb +4 -2
- data/lib/authlogic/acts_as_authentic/email.rb +8 -3
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +21 -3
- data/lib/authlogic/acts_as_authentic/login.rb +44 -25
- data/lib/authlogic/acts_as_authentic/password.rb +28 -12
- data/lib/authlogic/acts_as_authentic/perishable_token.rb +21 -12
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +16 -9
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +5 -3
- data/lib/authlogic/authenticates_many/association.rb +11 -4
- data/lib/authlogic/authenticates_many/base.rb +5 -4
- data/lib/authlogic/controller_adapters/rack_adapter.rb +6 -2
- data/lib/authlogic/controller_adapters/rails_adapter.rb +11 -8
- data/lib/authlogic/crypto_providers/aes256.rb +21 -2
- data/lib/authlogic/crypto_providers/bcrypt.rb +4 -1
- data/lib/authlogic/crypto_providers/sha512.rb +15 -10
- data/lib/authlogic/regex.rb +7 -6
- data/lib/authlogic/session/activation.rb +19 -10
- data/lib/authlogic/session/cookies.rb +3 -1
- data/lib/authlogic/session/id.rb +13 -7
- data/lib/authlogic/session/magic_columns.rb +19 -10
- data/lib/authlogic/session/magic_states.rb +7 -1
- data/lib/authlogic/session/password.rb +82 -35
- data/lib/authlogic/session/perishable_token.rb +7 -3
- data/lib/authlogic/session/validation.rb +13 -11
- data/lib/authlogic/test_case.rb +52 -32
- data/lib/authlogic.rb +6 -0
- data/test/acts_as_authentic_test/email_test.rb +33 -27
- data/test/acts_as_authentic_test/logged_in_status_test.rb +2 -2
- data/test/acts_as_authentic_test/login_test.rb +50 -37
- data/test/acts_as_authentic_test/magic_columns_test.rb +8 -8
- data/test/acts_as_authentic_test/password_test.rb +14 -14
- data/test/acts_as_authentic_test/perishable_token_test.rb +5 -5
- data/test/acts_as_authentic_test/persistence_token_test.rb +4 -4
- data/test/acts_as_authentic_test/restful_authentication_test.rb +6 -6
- data/test/acts_as_authentic_test/session_maintenance_test.rb +15 -10
- data/test/acts_as_authentic_test/single_access_test.rb +6 -6
- data/test/authenticates_many_test.rb +21 -6
- data/test/gemfiles/Gemfile.rails-5.1.x +6 -0
- data/test/gemfiles/Gemfile.rails-5.2.x +6 -0
- data/test/libs/company.rb +1 -1
- data/test/session_test/activation_test.rb +1 -1
- data/test/session_test/active_record_trickery_test.rb +3 -3
- data/test/session_test/brute_force_protection_test.rb +19 -14
- data/test/session_test/cookies_test.rb +21 -12
- data/test/session_test/existence_test.rb +15 -10
- data/test/session_test/http_auth_test.rb +2 -2
- data/test/session_test/magic_columns_test.rb +7 -4
- data/test/session_test/magic_states_test.rb +7 -9
- data/test/session_test/params_test.rb +6 -6
- data/test/session_test/password_test.rb +2 -2
- data/test/session_test/perishability_test.rb +1 -1
- data/test/session_test/persistence_test.rb +2 -2
- data/test/session_test/timeout_test.rb +7 -5
- data/test/session_test/validation_test.rb +1 -1
- data/test/test_helper.rb +37 -6
- metadata +57 -36
- checksums.yaml +0 -7
@@ -1,9 +1,13 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module ActsAsAuthentic
|
3
|
-
# This provides a handy token that is "perishable". Meaning the token is
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
3
|
+
# This provides a handy token that is "perishable". Meaning the token is
|
4
|
+
# only good for a certain amount of time. This is perfect for resetting
|
5
|
+
# password, confirming accounts, etc. Typically during these actions you
|
6
|
+
# send them this token in via their email. Once they use the token and do
|
7
|
+
# what they need to do, that token should expire. Don't worry about
|
8
|
+
# maintaining this, changing it, or expiring it yourself. Authlogic does all
|
9
|
+
# of this for you. See the sub modules for all of the tools Authlogic
|
10
|
+
# provides to you.
|
7
11
|
module PerishableToken
|
8
12
|
def self.included(klass)
|
9
13
|
klass.class_eval do
|
@@ -14,8 +18,9 @@ module Authlogic
|
|
14
18
|
|
15
19
|
# Change how the perishable token works.
|
16
20
|
module Config
|
17
|
-
# When using the find_using_perishable_token method the token can
|
18
|
-
#
|
21
|
+
# When using the find_using_perishable_token method the token can
|
22
|
+
# expire. If the token is expired, no record will be returned. Use this
|
23
|
+
# option to specify how long the token is valid for.
|
19
24
|
#
|
20
25
|
# * <tt>Default:</tt> 10.minutes
|
21
26
|
# * <tt>Accepts:</tt> Fixnum
|
@@ -24,9 +29,10 @@ module Authlogic
|
|
24
29
|
end
|
25
30
|
alias_method :perishable_token_valid_for=, :perishable_token_valid_for
|
26
31
|
|
27
|
-
# Authlogic tries to expire and change the perishable token as much as
|
28
|
-
# it's purpose. This is for security
|
29
|
-
#
|
32
|
+
# Authlogic tries to expire and change the perishable token as much as
|
33
|
+
# possible, without compromising it's purpose. This is for security
|
34
|
+
# reasons. If you want to manage it yourself, you can stop Authlogic
|
35
|
+
# from getting your in way by setting this to true.
|
30
36
|
#
|
31
37
|
# * <tt>Default:</tt> false
|
32
38
|
# * <tt>Accepts:</tt> Boolean
|
@@ -52,12 +58,14 @@ module Authlogic
|
|
52
58
|
|
53
59
|
# Class level methods for the perishable token
|
54
60
|
module ClassMethods
|
55
|
-
# Use this method to find a record with a perishable token. This
|
61
|
+
# Use this method to find a record with a perishable token. This
|
62
|
+
# method does 2 things for you:
|
56
63
|
#
|
57
64
|
# 1. It ignores blank tokens
|
58
65
|
# 2. It enforces the perishable_token_valid_for configuration option.
|
59
66
|
#
|
60
|
-
# If you want to use a different timeout value, just pass it as the
|
67
|
+
# If you want to use a different timeout value, just pass it as the
|
68
|
+
# second parameter:
|
61
69
|
#
|
62
70
|
# User.find_using_perishable_token(token, 1.hour)
|
63
71
|
def find_using_perishable_token(token, age = self.perishable_token_valid_for)
|
@@ -94,7 +102,8 @@ module Authlogic
|
|
94
102
|
save_without_session_maintenance(:validate => false)
|
95
103
|
end
|
96
104
|
|
97
|
-
# A convenience method based on the
|
105
|
+
# A convenience method based on the
|
106
|
+
# disable_perishable_token_maintenance configuration option.
|
98
107
|
def disable_perishable_token_maintenance?
|
99
108
|
self.class.disable_perishable_token_maintenance == true
|
100
109
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module ActsAsAuthentic
|
3
|
-
# This module is responsible for transitioning existing applications from
|
3
|
+
# This module is responsible for transitioning existing applications from
|
4
|
+
# the restful_authentication plugin.
|
4
5
|
module RestfulAuthentication
|
5
6
|
def self.included(klass)
|
6
7
|
klass.class_eval do
|
@@ -10,10 +11,13 @@ module Authlogic
|
|
10
11
|
end
|
11
12
|
|
12
13
|
module Config
|
13
|
-
# Switching an existing app to Authlogic from restful_authentication? No
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
14
|
+
# Switching an existing app to Authlogic from restful_authentication? No
|
15
|
+
# problem, just set this true and your users won't know anything
|
16
|
+
# changed. From your database perspective nothing will change at all.
|
17
|
+
# Authlogic will continue to encrypt passwords just like
|
18
|
+
# restful_authentication, so your app won't skip a beat. Although, might
|
19
|
+
# consider transitioning your users to a newer and stronger algorithm.
|
20
|
+
# Checkout the transition_from_restful_authentication option.
|
17
21
|
#
|
18
22
|
# * <tt>Default:</tt> false
|
19
23
|
# * <tt>Accepts:</tt> Boolean
|
@@ -24,10 +28,13 @@ module Authlogic
|
|
24
28
|
end
|
25
29
|
alias_method :act_like_restful_authentication=, :act_like_restful_authentication
|
26
30
|
|
27
|
-
# This works just like act_like_restful_authentication except that it
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
+
# This works just like act_like_restful_authentication except that it
|
32
|
+
# will start transitioning your users to the algorithm you specify with
|
33
|
+
# the crypto provider option. The next time they log in it will resave
|
34
|
+
# their password with the new algorithm and any new record will use the
|
35
|
+
# new algorithm as well. Make sure to update your users table if you are
|
36
|
+
# using the default migration since it will set crypted_password and
|
37
|
+
# salt columns to a maximum width of 40 characters which is not enough.
|
31
38
|
def transition_from_restful_authentication(value = nil)
|
32
39
|
r = rw_config(:transition_from_restful_authentication, value, false)
|
33
40
|
set_restful_authentication_config if value
|
@@ -102,7 +102,8 @@ module Authlogic
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def get_session_information
|
105
|
-
# Need to determine if we are completely logged out, or logged in as
|
105
|
+
# Need to determine if we are completely logged out, or logged in as
|
106
|
+
# another user.
|
106
107
|
@_sessions = []
|
107
108
|
|
108
109
|
session_ids.each do |session_id|
|
@@ -120,8 +121,9 @@ module Authlogic
|
|
120
121
|
end
|
121
122
|
|
122
123
|
def create_session
|
123
|
-
# We only want to automatically login into the first session, since
|
124
|
-
#
|
124
|
+
# We only want to automatically login into the first session, since
|
125
|
+
# this is the main session. The other sessions are sessions that
|
126
|
+
# need to be created after logging into the main session.
|
125
127
|
session_id = session_ids.first
|
126
128
|
session_class.create(*[self, self, session_id].compact)
|
127
129
|
|
@@ -1,14 +1,17 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module AuthenticatesMany
|
3
|
-
# An object of this class is used as a proxy for the authenticates_many
|
4
|
-
#
|
3
|
+
# An object of this class is used as a proxy for the authenticates_many
|
4
|
+
# relationship. It basically allows you to "save" scope details and call
|
5
|
+
# them on an object, which allows you to do the following:
|
5
6
|
#
|
6
7
|
# @account.user_sessions.new
|
7
8
|
# @account.user_sessions.find
|
8
9
|
# # ... etc
|
9
10
|
#
|
10
|
-
# You can call all of the class level methods off of an object with a saved
|
11
|
-
#
|
11
|
+
# You can call all of the class level methods off of an object with a saved
|
12
|
+
# scope, so that calling the above methods scopes the user sessions down to
|
13
|
+
# that specific account. To implement this via ActiveRecord do something
|
14
|
+
# like:
|
12
15
|
#
|
13
16
|
# class User < ActiveRecord::Base
|
14
17
|
# authenticates_many :user_sessions
|
@@ -16,6 +19,10 @@ module Authlogic
|
|
16
19
|
class Association
|
17
20
|
attr_accessor :klass, :find_options, :id
|
18
21
|
|
22
|
+
# - id: Usually `nil`, but if the `scope_cookies` option is used, then
|
23
|
+
# `id` is a string like "company_123". It may seem strange to refer
|
24
|
+
# to such a string as an "id", but the naming is intentional, and
|
25
|
+
# is derived from `Authlogic::Session::Id`.
|
19
26
|
def initialize(klass, find_options, id)
|
20
27
|
self.klass = klass
|
21
28
|
self.find_options = find_options
|
@@ -43,17 +43,18 @@ module Authlogic
|
|
43
43
|
# * <tt>scope_cookies:</tt> default: false
|
44
44
|
# By the nature of cookies they scope themselves if you are using subdomains to
|
45
45
|
# access accounts. If you aren't using subdomains you need to have separate
|
46
|
-
# cookies for each account, assuming a user is logging into
|
46
|
+
# cookies for each account, assuming a user is logging into more than one account.
|
47
47
|
# Authlogic can take care of this for you by prefixing the name of the cookie and
|
48
|
-
#
|
49
|
-
#
|
48
|
+
# session with the model id. Because it affects both cookies names and session keys,
|
49
|
+
# the name `scope_cookies` is misleading. Perhaps simply `scope` or `scoped`
|
50
|
+
# would have been better.
|
50
51
|
def authenticates_many(name, options = {})
|
51
52
|
options[:session_class] ||= name.to_s.classify.constantize
|
52
53
|
options[:relationship_name] ||= options[:session_class].klass_name.underscore.pluralize
|
53
54
|
class_eval <<-"end_eval", __FILE__, __LINE__
|
54
55
|
def #{name}
|
55
56
|
find_options = #{options[:find_options].inspect} || #{options[:relationship_name]}.where(nil)
|
56
|
-
@#{name} ||= Authlogic::AuthenticatesMany::Association.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
|
57
|
+
@#{name} ||= Authlogic::AuthenticatesMany::Association.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
|
57
58
|
end
|
58
59
|
end_eval
|
59
60
|
end
|
@@ -2,8 +2,10 @@ require 'action_controller'
|
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module ControllerAdapters
|
5
|
-
# Adapts authlogic to work with rails. The point is to close the gap between
|
6
|
-
#
|
5
|
+
# Adapts authlogic to work with rails. The point is to close the gap between
|
6
|
+
# what authlogic expects and what the rails controller object provides.
|
7
|
+
# Similar to how ActiveRecord has an adapter for MySQL, PostgreSQL, SQLite,
|
8
|
+
# etc.
|
7
9
|
class RailsAdapter < AbstractAdapter
|
8
10
|
class AuthlogicLoadedTooLateError < StandardError; end
|
9
11
|
|
@@ -31,12 +33,13 @@ module Authlogic
|
|
31
33
|
if defined?(::ApplicationController)
|
32
34
|
raise AuthlogicLoadedTooLateError.new(
|
33
35
|
<<-EOS.strip_heredoc
|
34
|
-
Authlogic is trying to add a callback to ActionController::Base
|
35
|
-
ApplicationController has already been loaded, so the
|
36
|
-
be copied into your application. Generally this
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
Authlogic is trying to add a callback to ActionController::Base
|
37
|
+
but ApplicationController has already been loaded, so the
|
38
|
+
callback won't be copied into your application. Generally this
|
39
|
+
is due to another gem or plugin requiring your
|
40
|
+
ApplicationController prematurely, such as the
|
41
|
+
resource_controller plugin. Please require Authlogic first,
|
42
|
+
before these other gems / plugins.
|
40
43
|
EOS
|
41
44
|
)
|
42
45
|
end
|
@@ -38,8 +38,27 @@ module Authlogic
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def aes
|
41
|
-
|
42
|
-
|
41
|
+
if @key.blank?
|
42
|
+
raise ArgumentError.new(
|
43
|
+
"You must provide a key like #{name}.key = my_key before using the #{name}"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
@aes ||= openssl_cipher_class.new("AES-256-ECB")
|
48
|
+
end
|
49
|
+
|
50
|
+
# `::OpenSSL::Cipher::Cipher` has been deprecated since at least 2014,
|
51
|
+
# in favor of `::OpenSSL::Cipher`, but a deprecation warning was not
|
52
|
+
# printed until 2016
|
53
|
+
# (https://github.com/ruby/openssl/commit/5c20a4c014) when openssl
|
54
|
+
# became a gem. Its first release as a gem was 2.0.0, in ruby 2.4.
|
55
|
+
# (See https://github.com/ruby/ruby/blob/v2_4_0/NEWS)
|
56
|
+
def openssl_cipher_class
|
57
|
+
if ::Gem::Version.new(::OpenSSL::VERSION) < ::Gem::Version.new("2.0.0")
|
58
|
+
::OpenSSL::Cipher::Cipher
|
59
|
+
else
|
60
|
+
::OpenSSL::Cipher
|
61
|
+
end
|
43
62
|
end
|
44
63
|
end
|
45
64
|
end
|
@@ -56,7 +56,10 @@ module Authlogic
|
|
56
56
|
|
57
57
|
def cost=(val)
|
58
58
|
if val < ::BCrypt::Engine::MIN_COST
|
59
|
-
raise ArgumentError.new(
|
59
|
+
raise ArgumentError.new(
|
60
|
+
"Authlogic's bcrypt cost cannot be set below the engine's " \
|
61
|
+
"min cost (#{::BCrypt::Engine::MIN_COST})"
|
62
|
+
)
|
60
63
|
end
|
61
64
|
@cost = val
|
62
65
|
end
|
@@ -1,22 +1,25 @@
|
|
1
1
|
require "digest/sha2"
|
2
2
|
|
3
3
|
module Authlogic
|
4
|
-
# The acts_as_authentic method has a crypto_provider option. This allows you
|
5
|
-
#
|
4
|
+
# The acts_as_authentic method has a crypto_provider option. This allows you
|
5
|
+
# to use any type of encryption you like. Just create a class with a class
|
6
|
+
# level encrypt and matches? method. See example below.
|
6
7
|
#
|
7
8
|
# === Example
|
8
9
|
#
|
9
10
|
# class MyAwesomeEncryptionMethod
|
10
11
|
# def self.encrypt(*tokens)
|
11
|
-
# #
|
12
|
-
# # just do what you need to do with them and return a
|
13
|
-
# #
|
12
|
+
# # The tokens passed will be an array of objects, what type of object
|
13
|
+
# # is irrelevant, just do what you need to do with them and return a
|
14
|
+
# # single encrypted string. For example, you will most likely join all
|
15
|
+
# # of the objects into a single string and then encrypt that string.
|
14
16
|
# end
|
15
17
|
#
|
16
18
|
# def self.matches?(crypted, *tokens)
|
17
|
-
# #
|
18
|
-
# #
|
19
|
-
# # encrypt the tokens and make sure it matches the
|
19
|
+
# # Return true if the crypted string matches the tokens. Depending on
|
20
|
+
# # your algorithm you might decrypt the string then compare it to the
|
21
|
+
# # token, or you might encrypt the tokens and make sure it matches the
|
22
|
+
# # crypted string, its up to you.
|
20
23
|
# end
|
21
24
|
# end
|
22
25
|
module CryptoProviders
|
@@ -27,7 +30,8 @@ module Authlogic
|
|
27
30
|
class << self
|
28
31
|
attr_accessor :join_token
|
29
32
|
|
30
|
-
# The number of times to loop through the encryption. This is twenty
|
33
|
+
# The number of times to loop through the encryption. This is twenty
|
34
|
+
# because that is what restful_authentication defaults to.
|
31
35
|
def stretches
|
32
36
|
@stretches ||= 20
|
33
37
|
end
|
@@ -40,7 +44,8 @@ module Authlogic
|
|
40
44
|
digest
|
41
45
|
end
|
42
46
|
|
43
|
-
# Does the crypted password match the tokens? Uses the same tokens that
|
47
|
+
# Does the crypted password match the tokens? Uses the same tokens that
|
48
|
+
# were used to encrypt.
|
44
49
|
def matches?(crypted, *tokens)
|
45
50
|
encrypt(*tokens) == crypted
|
46
51
|
end
|
data/lib/authlogic/regex.rb
CHANGED
@@ -5,15 +5,16 @@ module Authlogic
|
|
5
5
|
#
|
6
6
|
# validates_format_of :my_email_field, :with => Authlogic::Regex.email
|
7
7
|
module Regex
|
8
|
-
# A general email regular expression. It allows top level domains (TLD) to be from 2 -
|
9
|
-
# The decisions behind this regular expression were made by analyzing
|
10
|
-
# maintained by IANA and by reading this website:
|
11
|
-
# which is an excellent resource for
|
8
|
+
# A general email regular expression. It allows top level domains (TLD) to be from 2 -
|
9
|
+
# 24 in length. The decisions behind this regular expression were made by analyzing
|
10
|
+
# the list of top-level domains maintained by IANA and by reading this website:
|
11
|
+
# http://www.regular-expressions.info/email.html, which is an excellent resource for
|
12
|
+
# regular expressions.
|
12
13
|
def self.email
|
13
14
|
@email_regex ||= begin
|
14
15
|
email_name_regex = '[A-Z0-9_\.&%\+\-\']+'
|
15
16
|
domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
|
16
|
-
domain_tld_regex = '(?:[A-Z]{2,
|
17
|
+
domain_tld_regex = '(?:[A-Z]{2,25})'
|
17
18
|
/\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
|
18
19
|
end
|
19
20
|
end
|
@@ -33,7 +34,7 @@ module Authlogic
|
|
33
34
|
@email_nonascii_regex ||= begin
|
34
35
|
email_name_regex = '[^[:cntrl:][@\[\]\^ \!\"#$\(\)*,/:;<=>\?`{|}~\\\]]+'
|
35
36
|
domain_head_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\']]+\.)+'
|
36
|
-
domain_tld_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\-\'0-9]]{2,
|
37
|
+
domain_tld_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\-\'0-9]]{2,25})'
|
37
38
|
/\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/
|
38
39
|
end
|
39
40
|
end
|
@@ -2,9 +2,11 @@ require 'request_store'
|
|
2
2
|
|
3
3
|
module Authlogic
|
4
4
|
module Session
|
5
|
-
# Activating Authlogic requires that you pass it an
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# Activating Authlogic requires that you pass it an
|
6
|
+
# Authlogic::ControllerAdapters::AbstractAdapter object, or a class that
|
7
|
+
# extends it. This is sort of like a database connection for an ORM library,
|
8
|
+
# Authlogic can't do anything until it is "connected" to a controller. If
|
9
|
+
# you are using a supported framework, Authlogic takes care of this for you.
|
8
10
|
module Activation
|
9
11
|
class NotActivatedError < ::StandardError # :nodoc:
|
10
12
|
def initialize(session)
|
@@ -20,17 +22,24 @@ module Authlogic
|
|
20
22
|
end
|
21
23
|
|
22
24
|
module ClassMethods
|
23
|
-
# Returns true if a controller has been set and can be used properly.
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
25
|
+
# Returns true if a controller has been set and can be used properly.
|
26
|
+
# This MUST be set before anything can be done. Similar to how
|
27
|
+
# ActiveRecord won't allow you to do anything without establishing a DB
|
28
|
+
# connection. In your framework environment this is done for you, but if
|
29
|
+
# you are using Authlogic outside of your framework, you need to assign
|
30
|
+
# a controller object to Authlogic via
|
31
|
+
# Authlogic::Session::Base.controller = obj. See the controller= method
|
32
|
+
# for more information.
|
27
33
|
def activated?
|
28
34
|
!controller.nil?
|
29
35
|
end
|
30
36
|
|
31
|
-
# This accepts a controller object wrapped with the Authlogic controller
|
32
|
-
#
|
33
|
-
#
|
37
|
+
# This accepts a controller object wrapped with the Authlogic controller
|
38
|
+
# adapter. The controller adapters close the gap between the different
|
39
|
+
# controllers in each framework. That being said, Authlogic is expecting
|
40
|
+
# your object's class to extend
|
41
|
+
# Authlogic::ControllerAdapters::AbstractAdapter. See
|
42
|
+
# Authlogic::ControllerAdapters for more info.
|
34
43
|
#
|
35
44
|
# Lastly, this is thread safe.
|
36
45
|
def controller=(value)
|
@@ -91,7 +91,9 @@ module Authlogic
|
|
91
91
|
values = value.is_a?(Array) ? value : [value]
|
92
92
|
case values.first
|
93
93
|
when Hash
|
94
|
-
|
94
|
+
if values.first.with_indifferent_access.key?(:remember_me)
|
95
|
+
self.remember_me = values.first.with_indifferent_access[:remember_me]
|
96
|
+
end
|
95
97
|
else
|
96
98
|
r = values.find { |value| value.is_a?(TrueClass) || value.is_a?(FalseClass) }
|
97
99
|
self.remember_me = r if !r.nil?
|
data/lib/authlogic/session/id.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
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
|
5
6
|
def self.included(klass)
|
6
7
|
klass.class_eval do
|
@@ -15,18 +16,23 @@ module Authlogic
|
|
15
16
|
self.id = values.last if values.last.is_a?(Symbol)
|
16
17
|
end
|
17
18
|
|
18
|
-
# Allows you to set a unique identifier for your session, so that you can
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
19
|
+
# Allows you to set a unique identifier for your session, so that you can
|
20
|
+
# have more than 1 session at a time. A good example when this might be
|
21
|
+
# needed is when you want to have a normal user session and a "secure"
|
22
|
+
# user session. The secure user session would be created only when they
|
23
|
+
# want to modify their billing information, or other sensitive
|
24
|
+
# information. Similar to me.com. This requires 2 user sessions. Just use
|
25
|
+
# an id for the "secure" session and you should be good.
|
22
26
|
#
|
23
|
-
# You can set the id during initialization (see initialize for more
|
27
|
+
# You can set the id during initialization (see initialize for more
|
28
|
+
# information), or as an attribute:
|
24
29
|
#
|
25
30
|
# session.id = :my_id
|
26
31
|
#
|
27
32
|
# Just be sure and set your id before you save your session.
|
28
33
|
#
|
29
|
-
# Lastly, to retrieve your session with the id check out the find class
|
34
|
+
# Lastly, to retrieve your session with the id check out the find class
|
35
|
+
# method.
|
30
36
|
def id
|
31
37
|
@id
|
32
38
|
end
|
@@ -74,14 +74,18 @@ module Authlogic
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
# This method lets authlogic know whether it should allow the
|
78
|
-
#
|
79
|
-
#
|
80
|
-
# in your
|
77
|
+
# This method lets authlogic know whether it should allow the
|
78
|
+
# last_request_at field to be updated with the current time
|
79
|
+
# (Time.now). One thing to note here is that it also checks for the
|
80
|
+
# existence of a last_request_update_allowed? method in your
|
81
|
+
# controller. This allows you to control this method pragmatically in
|
82
|
+
# your controller.
|
81
83
|
#
|
82
|
-
# For example, what if you had a javascript function that polled the
|
83
|
-
#
|
84
|
-
#
|
84
|
+
# For example, what if you had a javascript function that polled the
|
85
|
+
# server updating how much time is left in their session before it
|
86
|
+
# times out. Obviously you would want to ignore this request, because
|
87
|
+
# then the user would never time out. So you can do something like
|
88
|
+
# this in your controller:
|
85
89
|
#
|
86
90
|
# def last_request_update_allowed?
|
87
91
|
# action_name != "update_session_time_left"
|
@@ -89,9 +93,14 @@ module Authlogic
|
|
89
93
|
#
|
90
94
|
# You can do whatever you want with that method.
|
91
95
|
def set_last_request_at? # :doc:
|
92
|
-
|
93
|
-
|
94
|
-
|
96
|
+
if !record || !klass.column_names.include?("last_request_at")
|
97
|
+
return false
|
98
|
+
end
|
99
|
+
if controller.responds_to_last_request_update_allowed? && !controller.last_request_update_allowed?
|
100
|
+
return false
|
101
|
+
end
|
102
|
+
record.last_request_at.blank? ||
|
103
|
+
last_request_at_threshold.to_i.seconds.ago >= record.last_request_at
|
95
104
|
end
|
96
105
|
|
97
106
|
def set_last_request_at
|
@@ -58,7 +58,13 @@ module Authlogic
|
|
58
58
|
return true if attempted_record.nil?
|
59
59
|
[:active, :approved, :confirmed].each do |required_status|
|
60
60
|
if attempted_record.respond_to?("#{required_status}?") && !attempted_record.send("#{required_status}?")
|
61
|
-
errors.add(
|
61
|
+
errors.add(
|
62
|
+
:base,
|
63
|
+
I18n.t(
|
64
|
+
"error_messages.not_#{required_status}",
|
65
|
+
:default => "Your account is not #{required_status}"
|
66
|
+
)
|
67
|
+
)
|
62
68
|
return false
|
63
69
|
end
|
64
70
|
end
|