authlogic 3.4.6 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +33 -0
- data/.rubocop_todo.yml +427 -0
- data/.travis.yml +24 -3
- data/CHANGELOG.md +9 -2
- data/CONTRIBUTING.md +40 -1
- data/Gemfile +1 -1
- data/README.md +295 -0
- data/Rakefile +10 -2
- data/authlogic.gemspec +6 -5
- data/lib/authlogic.rb +2 -2
- data/lib/authlogic/acts_as_authentic/base.rb +2 -2
- data/lib/authlogic/acts_as_authentic/email.rb +59 -14
- data/lib/authlogic/acts_as_authentic/logged_in_status.rb +4 -3
- data/lib/authlogic/acts_as_authentic/login.rb +62 -12
- data/lib/authlogic/acts_as_authentic/magic_columns.rb +17 -6
- data/lib/authlogic/acts_as_authentic/password.rb +107 -53
- data/lib/authlogic/acts_as_authentic/persistence_token.rb +10 -9
- data/lib/authlogic/acts_as_authentic/restful_authentication.rb +2 -0
- data/lib/authlogic/acts_as_authentic/session_maintenance.rb +48 -35
- data/lib/authlogic/acts_as_authentic/single_access_token.rb +19 -15
- data/lib/authlogic/acts_as_authentic/validations_scope.rb +2 -2
- data/lib/authlogic/authenticates_many/association.rb +6 -5
- data/lib/authlogic/authenticates_many/base.rb +22 -12
- data/lib/authlogic/config.rb +2 -1
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +2 -1
- data/lib/authlogic/controller_adapters/rack_adapter.rb +3 -4
- data/lib/authlogic/controller_adapters/rails_adapter.rb +26 -14
- data/lib/authlogic/controller_adapters/sinatra_adapter.rb +1 -1
- data/lib/authlogic/crypto_providers/aes256.rb +16 -12
- data/lib/authlogic/crypto_providers/bcrypt.rb +10 -4
- data/lib/authlogic/crypto_providers/md5.rb +7 -7
- data/lib/authlogic/crypto_providers/scrypt.rb +10 -2
- data/lib/authlogic/crypto_providers/sha1.rb +3 -3
- data/lib/authlogic/crypto_providers/sha256.rb +3 -3
- data/lib/authlogic/crypto_providers/sha512.rb +4 -4
- data/lib/authlogic/crypto_providers/wordpress.rb +13 -13
- data/lib/authlogic/i18n.rb +22 -16
- data/lib/authlogic/i18n/translator.rb +1 -1
- data/lib/authlogic/random.rb +13 -12
- data/lib/authlogic/regex.rb +3 -3
- data/lib/authlogic/session/activation.rb +7 -6
- data/lib/authlogic/session/active_record_trickery.rb +1 -2
- data/lib/authlogic/session/base.rb +7 -6
- data/lib/authlogic/session/brute_force_protection.rb +58 -34
- data/lib/authlogic/session/callbacks.rb +16 -12
- data/lib/authlogic/session/cookies.rb +29 -14
- data/lib/authlogic/session/existence.rb +10 -10
- data/lib/authlogic/session/foundation.rb +11 -7
- data/lib/authlogic/session/http_auth.rb +6 -5
- data/lib/authlogic/session/id.rb +5 -4
- data/lib/authlogic/session/klass.rb +2 -1
- data/lib/authlogic/session/magic_columns.rb +21 -14
- data/lib/authlogic/session/magic_states.rb +25 -14
- data/lib/authlogic/session/params.rb +41 -26
- data/lib/authlogic/session/password.rb +62 -40
- data/lib/authlogic/session/perishable_token.rb +3 -2
- data/lib/authlogic/session/persistence.rb +3 -3
- data/lib/authlogic/session/priority_record.rb +5 -4
- data/lib/authlogic/session/scopes.rb +20 -9
- data/lib/authlogic/session/session.rb +9 -4
- data/lib/authlogic/session/timeout.rb +40 -23
- data/lib/authlogic/session/unauthorized_record.rb +6 -5
- data/lib/authlogic/session/validation.rb +18 -9
- data/lib/authlogic/test_case.rb +2 -2
- data/lib/authlogic/test_case/mock_controller.rb +9 -9
- data/lib/authlogic/test_case/mock_cookie_jar.rb +2 -2
- data/lib/authlogic/test_case/mock_logger.rb +1 -1
- data/lib/authlogic/test_case/mock_request.rb +2 -1
- data/lib/authlogic/test_case/rails_request_adapter.rb +5 -5
- data/test/acts_as_authentic_test/email_test.rb +29 -17
- data/test/acts_as_authentic_test/logged_in_status_test.rb +9 -3
- data/test/acts_as_authentic_test/login_test.rb +47 -13
- data/test/acts_as_authentic_test/magic_columns_test.rb +4 -4
- data/test/acts_as_authentic_test/password_test.rb +31 -21
- data/test/acts_as_authentic_test/perishable_token_test.rb +15 -15
- data/test/acts_as_authentic_test/session_maintenance_test.rb +20 -13
- data/test/acts_as_authentic_test/single_access_test.rb +8 -8
- data/test/authenticates_many_test.rb +4 -4
- data/test/crypto_provider_test/aes256_test.rb +2 -2
- data/test/crypto_provider_test/scrypt_test.rb +1 -1
- data/test/crypto_provider_test/sha1_test.rb +3 -3
- data/test/crypto_provider_test/sha256_test.rb +1 -1
- data/test/crypto_provider_test/sha512_test.rb +2 -2
- data/test/gemfiles/Gemfile.rails-3.2.x +2 -2
- data/test/gemfiles/Gemfile.rails-5.0.x +6 -0
- data/test/i18n_test.rb +5 -5
- data/test/libs/affiliate.rb +2 -2
- data/test/libs/company.rb +1 -1
- 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/random_test.rb +5 -4
- data/test/session_test/activation_test.rb +5 -5
- data/test/session_test/active_record_trickery_test.rb +7 -5
- data/test/session_test/cookies_test.rb +8 -6
- data/test/session_test/existence_test.rb +19 -13
- data/test/session_test/http_auth_test.rb +0 -3
- data/test/session_test/id_test.rb +2 -2
- data/test/session_test/klass_test.rb +1 -1
- data/test/session_test/magic_columns_test.rb +0 -3
- data/test/session_test/magic_states_test.rb +11 -11
- data/test/session_test/params_test.rb +10 -10
- data/test/session_test/password_test.rb +4 -5
- data/test/session_test/perishability_test.rb +3 -3
- data/test/session_test/scopes_test.rb +8 -8
- data/test/session_test/session_test.rb +5 -4
- data/test/session_test/timeout_test.rb +8 -8
- data/test/session_test/unauthorized_record_test.rb +2 -2
- data/test/session_test/validation_test.rb +3 -3
- data/test/test_helper.rb +9 -5
- metadata +54 -24
- data/README.rdoc +0 -232
@@ -1,7 +1,7 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module I18n
|
3
3
|
class Translator
|
4
|
-
# If the I18n gem is present, calls +I18n.translate+ passing all
|
4
|
+
# If the I18n gem is present, calls +I18n.translate+ passing all
|
5
5
|
# arguments, else returns +options[:default]+.
|
6
6
|
def translate(key, options = {})
|
7
7
|
if defined?(::I18n)
|
data/lib/authlogic/random.rb
CHANGED
@@ -1,33 +1,34 @@
|
|
1
1
|
module Authlogic
|
2
|
-
# Handles generating random strings. If SecureRandom is installed it will default to
|
3
|
-
#
|
2
|
+
# Handles generating random strings. If SecureRandom is installed it will default to
|
3
|
+
# this and use it instead. SecureRandom comes with ActiveSupport. So if you are using
|
4
|
+
# this in a rails app you should have this library.
|
4
5
|
module Random
|
5
6
|
extend self
|
6
|
-
|
7
|
-
SecureRandom = (defined?(::SecureRandom) && ::SecureRandom) ||
|
8
|
-
|
7
|
+
|
8
|
+
SecureRandom = (defined?(::SecureRandom) && ::SecureRandom) ||
|
9
|
+
(defined?(::ActiveSupport::SecureRandom) && ::ActiveSupport::SecureRandom)
|
10
|
+
|
9
11
|
if SecureRandom
|
10
12
|
def hex_token
|
11
13
|
SecureRandom.hex(64)
|
12
14
|
end
|
13
|
-
|
15
|
+
|
14
16
|
def friendly_token
|
15
17
|
# use base64url as defined by RFC4648
|
16
18
|
SecureRandom.base64(15).tr('+/=', '').strip.delete("\n")
|
17
19
|
end
|
18
20
|
else
|
19
21
|
def hex_token
|
20
|
-
Authlogic::CryptoProviders::Sha512.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
|
22
|
+
Authlogic::CryptoProviders::Sha512.encrypt(Time.now.to_s + (1..10).collect { rand.to_s }.join)
|
21
23
|
end
|
22
|
-
|
24
|
+
|
23
25
|
FRIENDLY_CHARS = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
24
|
-
|
26
|
+
|
25
27
|
def friendly_token
|
26
28
|
newpass = ""
|
27
|
-
1.upto(20) { |i| newpass << FRIENDLY_CHARS[rand(FRIENDLY_CHARS.size-1)] }
|
29
|
+
1.upto(20) { |i| newpass << FRIENDLY_CHARS[rand(FRIENDLY_CHARS.size - 1)] }
|
28
30
|
newpass
|
29
31
|
end
|
30
32
|
end
|
31
|
-
|
32
33
|
end
|
33
|
-
end
|
34
|
+
end
|
data/lib/authlogic/regex.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#encoding: utf-8
|
1
|
+
# encoding: utf-8
|
2
2
|
module Authlogic
|
3
3
|
# This is a module the contains regular expressions used throughout Authlogic. The point of extracting
|
4
4
|
# them out into their own module is to make them easily available to you for other uses. Ex:
|
@@ -38,10 +38,10 @@ module Authlogic
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
# A simple regular expression that only allows for letters, numbers, spaces, and .-_
|
41
|
+
# A simple regular expression that only allows for letters, numbers, spaces, and .-_@+. Just a standard login / username
|
42
42
|
# regular expression.
|
43
43
|
def self.login
|
44
|
-
/\A
|
44
|
+
/\A[a-zA-Z0-9_][a-zA-Z0-9\.+\-_@ ]+\z/
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -11,14 +11,14 @@ module Authlogic
|
|
11
11
|
super("You must activate the Authlogic::Session::Base.controller with a controller object before creating objects")
|
12
12
|
end
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def self.included(klass)
|
16
16
|
klass.class_eval do
|
17
17
|
extend ClassMethods
|
18
18
|
include InstanceMethods
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
module ClassMethods
|
23
23
|
# Returns true if a controller has been set and can be used properly. This MUST be set before anything can be done.
|
24
24
|
# Similar to how ActiveRecord won't allow you to do anything without establishing a DB connection. In your framework
|
@@ -27,7 +27,7 @@ module Authlogic
|
|
27
27
|
def activated?
|
28
28
|
!controller.nil?
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# This accepts a controller object wrapped with the Authlogic controller adapter. The controller adapters close the gap
|
32
32
|
# between the different controllers in each framework. That being said, Authlogic is expecting your object's class to
|
33
33
|
# extend Authlogic::ControllerAdapters::AbstractAdapter. See Authlogic::ControllerAdapters for more info.
|
@@ -36,21 +36,22 @@ module Authlogic
|
|
36
36
|
def controller=(value)
|
37
37
|
RequestStore.store[:authlogic_controller] = value
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# The current controller object
|
41
41
|
def controller
|
42
42
|
RequestStore.store[:authlogic_controller]
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
module InstanceMethods
|
47
47
|
# Making sure we are activated before we start creating objects
|
48
48
|
def initialize(*args)
|
49
49
|
raise NotActivatedError.new(self) unless self.class.activated?
|
50
50
|
super
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
private
|
54
|
+
|
54
55
|
def controller
|
55
56
|
self.class.controller
|
56
57
|
end
|
@@ -25,13 +25,12 @@ module Authlogic
|
|
25
25
|
#
|
26
26
|
# authlogic.models.user_session
|
27
27
|
def human_name(*args)
|
28
|
-
I18n.t("models.#{name.underscore}", {:count => 1, :default => name.humanize})
|
28
|
+
I18n.t("models.#{name.underscore}", { :count => 1, :default => name.humanize })
|
29
29
|
end
|
30
30
|
|
31
31
|
def i18n_scope
|
32
32
|
I18n.scope
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
36
35
|
|
37
36
|
module InstanceMethods
|
@@ -1,25 +1,26 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session # :nodoc:
|
3
|
-
# This is the base class Authlogic, where all modules are included. For information on
|
3
|
+
# This is the base class Authlogic, where all modules are included. For information on functionality see the various
|
4
4
|
# sub modules.
|
5
5
|
class Base
|
6
6
|
include Foundation
|
7
7
|
include Callbacks
|
8
|
-
|
8
|
+
|
9
9
|
# Included first so that the session resets itself to nil
|
10
10
|
include Timeout
|
11
|
-
|
11
|
+
|
12
12
|
# Included in a specific order so they are tried in this order when persisting
|
13
13
|
include Params
|
14
14
|
include Cookies
|
15
15
|
include Session
|
16
16
|
include HttpAuth
|
17
|
-
|
17
|
+
|
18
18
|
# Included in a specific order so magic states gets ran after a record is found
|
19
|
+
# TODO: What does "magic states gets ran" mean? Be specific.
|
19
20
|
include Password
|
20
21
|
include UnauthorizedRecord
|
21
22
|
include MagicStates
|
22
|
-
|
23
|
+
|
23
24
|
include Activation
|
24
25
|
include ActiveRecordTrickery
|
25
26
|
include BruteForceProtection
|
@@ -34,4 +35,4 @@ module Authlogic
|
|
34
35
|
include PriorityRecord
|
35
36
|
end
|
36
37
|
end
|
37
|
-
end
|
38
|
+
end
|
@@ -1,15 +1,21 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# A brute force attacks is executed by hammering a login with as many password
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
3
|
+
# A brute force attacks is executed by hammering a login with as many password
|
4
|
+
# combinations as possible, until one works. A brute force attacked is generally
|
5
|
+
# combated with a slow hashing algorithm such as BCrypt. You can increase the cost,
|
6
|
+
# which makes the hash generation slower, and ultimately increases the time it takes
|
7
|
+
# to execute a brute force attack. Just to put this into perspective, if a hacker was
|
8
|
+
# to gain access to your server and execute a brute force attack locally, meaning
|
9
|
+
# there is no network lag, it would probably take decades to complete. Now throw in
|
10
|
+
# network lag and it would take MUCH longer.
|
8
11
|
#
|
9
|
-
# But for those that are extra paranoid and can't get enough protection, why not stop
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
12
|
+
# But for those that are extra paranoid and can't get enough protection, why not stop
|
13
|
+
# them as soon as you realize something isn't right? That's what this module is all
|
14
|
+
# about. By default the consecutive_failed_logins_limit configuration option is set to
|
15
|
+
# 50, if someone consecutively fails to login after 50 attempts their account will be
|
16
|
+
# suspended. This is a very liberal number and at this point it should be obvious that
|
17
|
+
# something is not right. If you wish to lower this number just set the configuration
|
18
|
+
# to a lower number:
|
13
19
|
#
|
14
20
|
# class UserSession < Authlogic::Session::Base
|
15
21
|
# consecutive_failed_logins_limit 10
|
@@ -23,16 +29,22 @@ module Authlogic
|
|
23
29
|
validate :validate_failed_logins, :if => :being_brute_force_protected?
|
24
30
|
end
|
25
31
|
end
|
26
|
-
|
32
|
+
|
27
33
|
# Configuration for the brute force protection feature.
|
28
34
|
module Config
|
29
|
-
# To help protect from brute force attacks you can set a limit on the
|
30
|
-
# number
|
35
|
+
# To help protect from brute force attacks you can set a limit on the
|
36
|
+
# allowed number of consecutive failed logins. By default this is 50,
|
37
|
+
# this is a very liberal number, and if someone fails to login after 50
|
38
|
+
# tries it should be pretty obvious that it's a machine trying to login
|
39
|
+
# in and very likely a brute force attack.
|
31
40
|
#
|
32
|
-
# In order to enable this field your model MUST have a
|
41
|
+
# In order to enable this field your model MUST have a
|
42
|
+
# failed_login_count (integer) field.
|
33
43
|
#
|
34
|
-
# If you don't know what a brute force attack is, it's when a machine
|
35
|
-
#
|
44
|
+
# If you don't know what a brute force attack is, it's when a machine
|
45
|
+
# tries to login into a system using every combination of character
|
46
|
+
# possible. Thus resulting in possibly millions of attempts to log into
|
47
|
+
# an account.
|
36
48
|
#
|
37
49
|
# * <tt>Default:</tt> 50
|
38
50
|
# * <tt>Accepts:</tt> Integer, set to 0 to disable
|
@@ -40,8 +52,9 @@ module Authlogic
|
|
40
52
|
rw_config(:consecutive_failed_logins_limit, value, 50)
|
41
53
|
end
|
42
54
|
alias_method :consecutive_failed_logins_limit=, :consecutive_failed_logins_limit
|
43
|
-
|
44
|
-
# Once the failed logins limit has been exceed, how long do you want to
|
55
|
+
|
56
|
+
# Once the failed logins limit has been exceed, how long do you want to
|
57
|
+
# ban the user? This can be a temporary or permanent ban.
|
45
58
|
#
|
46
59
|
# * <tt>Default:</tt> 2.hours
|
47
60
|
# * <tt>Accepts:</tt> Fixnum, set to 0 for permanent ban
|
@@ -50,47 +63,58 @@ module Authlogic
|
|
50
63
|
end
|
51
64
|
alias_method :failed_login_ban_for=, :failed_login_ban_for
|
52
65
|
end
|
53
|
-
|
54
|
-
# The methods available for an Authlogic::Session::Base object that make
|
66
|
+
|
67
|
+
# The methods available for an Authlogic::Session::Base object that make
|
68
|
+
# up the brute force protection feature.
|
55
69
|
module InstanceMethods
|
56
|
-
# Returns true when the consecutive_failed_logins_limit has been
|
57
|
-
#
|
58
|
-
#
|
70
|
+
# Returns true when the consecutive_failed_logins_limit has been
|
71
|
+
# exceeded and is being temporarily banned. Notice the word temporary,
|
72
|
+
# the user will not be permanently banned unless you choose to do so
|
73
|
+
# with configuration. By default they will be banned for 2 hours. During
|
74
|
+
# that 2 hour period this method will return true.
|
59
75
|
def being_brute_force_protected?
|
60
76
|
exceeded_failed_logins_limit? && (failed_login_ban_for <= 0 ||
|
61
77
|
(attempted_record.respond_to?(:updated_at) && attempted_record.updated_at >= failed_login_ban_for.seconds.ago))
|
62
78
|
end
|
63
|
-
|
79
|
+
|
64
80
|
private
|
81
|
+
|
65
82
|
def exceeded_failed_logins_limit?
|
66
83
|
!attempted_record.nil? && attempted_record.respond_to?(:failed_login_count) && consecutive_failed_logins_limit > 0 &&
|
67
84
|
attempted_record.failed_login_count && attempted_record.failed_login_count >= consecutive_failed_logins_limit
|
68
85
|
end
|
69
|
-
|
86
|
+
|
70
87
|
def reset_failed_login_count?
|
71
88
|
exceeded_failed_logins_limit? && !being_brute_force_protected?
|
72
89
|
end
|
73
|
-
|
90
|
+
|
74
91
|
def reset_failed_login_count
|
75
92
|
attempted_record.failed_login_count = 0
|
76
93
|
end
|
77
|
-
|
94
|
+
|
78
95
|
def validate_failed_logins
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
96
|
+
# Clear all other error messages, as they are irrelevant at this point and can
|
97
|
+
# only provide additional information that is not needed
|
98
|
+
errors.clear
|
99
|
+
errors.add(
|
100
|
+
:base,
|
101
|
+
I18n.t(
|
102
|
+
'error_messages.consecutive_failed_logins_limit_exceeded',
|
103
|
+
:default => "Consecutive failed logins limit exceeded, account has been" +
|
104
|
+
(failed_login_ban_for == 0 ? "" : " temporarily") +
|
105
|
+
" disabled."
|
106
|
+
)
|
107
|
+
)
|
84
108
|
end
|
85
|
-
|
109
|
+
|
86
110
|
def consecutive_failed_logins_limit
|
87
111
|
self.class.consecutive_failed_logins_limit
|
88
112
|
end
|
89
|
-
|
113
|
+
|
90
114
|
def failed_login_ban_for
|
91
115
|
self.class.failed_login_ban_for
|
92
116
|
end
|
93
117
|
end
|
94
118
|
end
|
95
119
|
end
|
96
|
-
end
|
120
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Between these
|
3
|
+
# Between these callbacks and the configuration, this is the contract between me and you to safely
|
4
4
|
# modify Authlogic's behavior. I will do everything I can to make sure these do not change.
|
5
5
|
#
|
6
6
|
# Check out the sub modules of Authlogic::Session. They are very concise, clear, and to the point. More
|
@@ -15,7 +15,7 @@ module Authlogic
|
|
15
15
|
# persist
|
16
16
|
# after_persisting
|
17
17
|
# [save record if record.changed?]
|
18
|
-
#
|
18
|
+
#
|
19
19
|
# before_validation
|
20
20
|
# before_validation_on_create
|
21
21
|
# before_validation_on_update
|
@@ -24,7 +24,7 @@ module Authlogic
|
|
24
24
|
# after_validation_on_create
|
25
25
|
# after_validation
|
26
26
|
# [save record if record.changed?]
|
27
|
-
#
|
27
|
+
#
|
28
28
|
# before_save
|
29
29
|
# before_create
|
30
30
|
# before_update
|
@@ -32,7 +32,7 @@ module Authlogic
|
|
32
32
|
# after_create
|
33
33
|
# after_save
|
34
34
|
# [save record if record.changed?]
|
35
|
-
#
|
35
|
+
#
|
36
36
|
# before_destroy
|
37
37
|
# [save record if record.changed?]
|
38
38
|
# destroy
|
@@ -60,15 +60,18 @@ module Authlogic
|
|
60
60
|
"before_save", "before_create", "before_update", "after_update", "after_create", "after_save",
|
61
61
|
"before_destroy", "after_destroy"
|
62
62
|
]
|
63
|
-
|
63
|
+
|
64
64
|
def self.included(base) #:nodoc:
|
65
65
|
base.send :include, ActiveSupport::Callbacks
|
66
|
-
if ActiveSupport::VERSION::STRING >=
|
67
|
-
base.define_callbacks *METHODS + [{:terminator => ->(target,
|
68
|
-
base.define_callbacks *['persist', {:terminator => ->(target,
|
66
|
+
if Gem::Version.new(ActiveSupport::VERSION::STRING) >= Gem::Version.new('5')
|
67
|
+
base.define_callbacks *METHODS + [{ :terminator => ->(target, result_lambda) { result_lambda.call == false } }]
|
68
|
+
base.define_callbacks *['persist', { :terminator => ->(target, result_lambda) { result_lambda.call == true } }]
|
69
|
+
elsif Gem::Version.new(ActiveSupport::VERSION::STRING) >= Gem::Version.new('4.1')
|
70
|
+
base.define_callbacks *METHODS + [{ :terminator => ->(target, result) { result == false } }]
|
71
|
+
base.define_callbacks *['persist', { :terminator => ->(target, result) { result == true } }]
|
69
72
|
else
|
70
|
-
base.define_callbacks *METHODS + [{:terminator => 'result == false'}]
|
71
|
-
base.define_callbacks *['persist', {:terminator => 'result == true'}]
|
73
|
+
base.define_callbacks *METHODS + [{ :terminator => 'result == false' }]
|
74
|
+
base.define_callbacks *['persist', { :terminator => 'result == true' }]
|
72
75
|
end
|
73
76
|
|
74
77
|
# If Rails 3, support the new callback syntax
|
@@ -82,8 +85,9 @@ module Authlogic
|
|
82
85
|
end
|
83
86
|
end
|
84
87
|
end
|
85
|
-
|
88
|
+
|
86
89
|
private
|
90
|
+
|
87
91
|
METHODS.each do |method|
|
88
92
|
class_eval <<-"end_eval", __FILE__, __LINE__
|
89
93
|
def #{method}
|
@@ -91,7 +95,7 @@ module Authlogic
|
|
91
95
|
end
|
92
96
|
end_eval
|
93
97
|
end
|
94
|
-
|
98
|
+
|
95
99
|
def save_record(alternate_record = nil)
|
96
100
|
r = alternate_record || record
|
97
101
|
r.save_without_session_maintenance(:validate => false) if r && r.changed? && !r.readonly?
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Authlogic
|
2
2
|
module Session
|
3
|
-
# Handles all authentication that deals with cookies, such as persisting,
|
3
|
+
# Handles all authentication that deals with cookies, such as persisting,
|
4
|
+
# saving, and destroying.
|
4
5
|
module Cookies
|
5
6
|
def self.included(klass)
|
6
7
|
klass.class_eval do
|
@@ -14,8 +15,10 @@ module Authlogic
|
|
14
15
|
|
15
16
|
# Configuration for the cookie feature set.
|
16
17
|
module Config
|
17
|
-
# The name of the cookie or the key in the cookies hash. Be sure and use
|
18
|
-
#
|
18
|
+
# The name of the cookie or the key in the cookies hash. Be sure and use
|
19
|
+
# a unique name. If you have multiple sessions and they use the same
|
20
|
+
# cookie it will cause problems. Also, if a id is set it will be
|
21
|
+
# inserted into the beginning of the string. Example:
|
19
22
|
#
|
20
23
|
# session = UserSession.new
|
21
24
|
# session.cookie_key => "user_credentials"
|
@@ -48,7 +51,8 @@ module Authlogic
|
|
48
51
|
end
|
49
52
|
alias_method :remember_me_for=, :remember_me_for
|
50
53
|
|
51
|
-
# Should the cookie be set as secure? If true, the cookie will only be sent over
|
54
|
+
# Should the cookie be set as secure? If true, the cookie will only be sent over
|
55
|
+
# SSL connections
|
52
56
|
#
|
53
57
|
# * <tt>Default:</tt> false
|
54
58
|
# * <tt>Accepts:</tt> Boolean
|
@@ -57,7 +61,8 @@ module Authlogic
|
|
57
61
|
end
|
58
62
|
alias_method :secure=, :secure
|
59
63
|
|
60
|
-
# Should the cookie be set as httponly? If true, the cookie will not be
|
64
|
+
# Should the cookie be set as httponly? If true, the cookie will not be
|
65
|
+
# accessible from javascript
|
61
66
|
#
|
62
67
|
# * <tt>Default:</tt> false
|
63
68
|
# * <tt>Accepts:</tt> Boolean
|
@@ -66,7 +71,8 @@ module Authlogic
|
|
66
71
|
end
|
67
72
|
alias_method :httponly=, :httponly
|
68
73
|
|
69
|
-
# Should the cookie be signed? If the controller adapter supports it, this is a
|
74
|
+
# Should the cookie be signed? If the controller adapter supports it, this is a
|
75
|
+
# measure against cookie tampering.
|
70
76
|
def sign_cookie(value = nil)
|
71
77
|
if value && !controller.cookies.respond_to?(:signed)
|
72
78
|
raise "Signed cookies not supported with #{controller.class}!"
|
@@ -76,7 +82,8 @@ module Authlogic
|
|
76
82
|
alias_method :sign_cookie=, :sign_cookie
|
77
83
|
end
|
78
84
|
|
79
|
-
# The methods available for an Authlogic::Session::Base object that make up the
|
85
|
+
# The methods available for an Authlogic::Session::Base object that make up the
|
86
|
+
# cookie feature set.
|
80
87
|
module InstanceMethods
|
81
88
|
# Allows you to set the remember_me option when passing credentials.
|
82
89
|
def credentials=(value)
|
@@ -97,7 +104,9 @@ module Authlogic
|
|
97
104
|
@remember_me = self.class.remember_me
|
98
105
|
end
|
99
106
|
|
100
|
-
# Accepts a boolean as a flag to remember the session or not. Basically
|
107
|
+
# Accepts a boolean as a flag to remember the session or not. Basically
|
108
|
+
# to expire the cookie at the end of the session or keep it for
|
109
|
+
# "remember_me_until".
|
101
110
|
def remember_me=(value)
|
102
111
|
@remember_me = value
|
103
112
|
end
|
@@ -107,13 +116,15 @@ module Authlogic
|
|
107
116
|
remember_me == true || remember_me == "true" || remember_me == "1"
|
108
117
|
end
|
109
118
|
|
110
|
-
# How long to remember the user if remember_me is true. This is based on the class
|
119
|
+
# How long to remember the user if remember_me is true. This is based on the class
|
120
|
+
# level configuration: remember_me_for
|
111
121
|
def remember_me_for
|
112
122
|
return unless remember_me?
|
113
123
|
self.class.remember_me_for
|
114
124
|
end
|
115
125
|
|
116
|
-
# When to expire the cookie. See remember_me_for configuration option to change
|
126
|
+
# When to expire the cookie. See remember_me_for configuration option to change
|
127
|
+
# this.
|
117
128
|
def remember_me_until
|
118
129
|
return unless remember_me?
|
119
130
|
remember_me_for.from_now
|
@@ -131,7 +142,8 @@ module Authlogic
|
|
131
142
|
@secure = self.class.secure
|
132
143
|
end
|
133
144
|
|
134
|
-
# Accepts a boolean as to whether the cookie should be marked as secure. If true
|
145
|
+
# Accepts a boolean as to whether the cookie should be marked as secure. If true
|
146
|
+
# the cookie will only ever be sent over an SSL connection.
|
135
147
|
def secure=(value)
|
136
148
|
@secure = value
|
137
149
|
end
|
@@ -141,13 +153,14 @@ module Authlogic
|
|
141
153
|
secure == true || secure == "true" || secure == "1"
|
142
154
|
end
|
143
155
|
|
144
|
-
# If the cookie should be marked as httponly (not
|
156
|
+
# If the cookie should be marked as httponly (not accessible via javascript)
|
145
157
|
def httponly
|
146
158
|
return @httponly if defined?(@httponly)
|
147
159
|
@httponly = self.class.httponly
|
148
160
|
end
|
149
161
|
|
150
|
-
# Accepts a boolean as to whether the cookie should be marked as
|
162
|
+
# Accepts a boolean as to whether the cookie should be marked as
|
163
|
+
# httponly. If true, the cookie will not be accessible from javascript
|
151
164
|
def httponly=(value)
|
152
165
|
@httponly = value
|
153
166
|
end
|
@@ -163,7 +176,8 @@ module Authlogic
|
|
163
176
|
@sign_cookie = self.class.sign_cookie
|
164
177
|
end
|
165
178
|
|
166
|
-
# Accepts a boolean as to whether the cookie should be signed. If true
|
179
|
+
# Accepts a boolean as to whether the cookie should be signed. If true
|
180
|
+
# the cookie will be saved and verified using a signature.
|
167
181
|
def sign_cookie=(value)
|
168
182
|
@sign_cookie = value
|
169
183
|
end
|
@@ -174,6 +188,7 @@ module Authlogic
|
|
174
188
|
end
|
175
189
|
|
176
190
|
private
|
191
|
+
|
177
192
|
def cookie_key
|
178
193
|
build_key(self.class.cookie_key)
|
179
194
|
end
|