authlogic 3.8.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/lib/authlogic/acts_as_authentic/base.rb +33 -36
  3. data/lib/authlogic/acts_as_authentic/email.rb +8 -141
  4. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +17 -10
  5. data/lib/authlogic/acts_as_authentic/login.rb +14 -165
  6. data/lib/authlogic/acts_as_authentic/magic_columns.rb +13 -10
  7. data/lib/authlogic/acts_as_authentic/password.rb +186 -254
  8. data/lib/authlogic/acts_as_authentic/perishable_token.rb +30 -22
  9. data/lib/authlogic/acts_as_authentic/persistence_token.rb +19 -18
  10. data/lib/authlogic/acts_as_authentic/queries/case_sensitivity.rb +53 -0
  11. data/lib/authlogic/acts_as_authentic/queries/find_with_case.rb +83 -0
  12. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +94 -62
  13. data/lib/authlogic/acts_as_authentic/single_access_token.rb +28 -14
  14. data/lib/authlogic/config.rb +29 -10
  15. data/lib/authlogic/controller_adapters/abstract_adapter.rb +43 -13
  16. data/lib/authlogic/controller_adapters/rack_adapter.rb +11 -5
  17. data/lib/authlogic/controller_adapters/rails_adapter.rb +11 -29
  18. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +8 -2
  19. data/lib/authlogic/cookie_credentials.rb +63 -0
  20. data/lib/authlogic/crypto_providers/bcrypt.rb +24 -18
  21. data/lib/authlogic/crypto_providers/md5/v2.rb +35 -0
  22. data/lib/authlogic/crypto_providers/md5.rb +8 -6
  23. data/lib/authlogic/crypto_providers/scrypt.rb +24 -17
  24. data/lib/authlogic/crypto_providers/sha1/v2.rb +41 -0
  25. data/lib/authlogic/crypto_providers/sha1.rb +12 -5
  26. data/lib/authlogic/crypto_providers/sha256/v2.rb +58 -0
  27. data/lib/authlogic/crypto_providers/sha256.rb +18 -9
  28. data/lib/authlogic/crypto_providers/sha512/v2.rb +39 -0
  29. data/lib/authlogic/crypto_providers/sha512.rb +9 -26
  30. data/lib/authlogic/crypto_providers.rb +77 -1
  31. data/lib/authlogic/errors.rb +35 -0
  32. data/lib/authlogic/i18n/translator.rb +4 -1
  33. data/lib/authlogic/i18n.rb +29 -20
  34. data/lib/authlogic/random.rb +12 -28
  35. data/lib/authlogic/session/base.rb +2087 -33
  36. data/lib/authlogic/session/magic_column/assigns_last_request_at.rb +46 -0
  37. data/lib/authlogic/test_case/mock_controller.rb +7 -4
  38. data/lib/authlogic/test_case/mock_cookie_jar.rb +19 -3
  39. data/lib/authlogic/test_case/mock_logger.rb +2 -0
  40. data/lib/authlogic/test_case/mock_request.rb +8 -3
  41. data/lib/authlogic/test_case/rails_request_adapter.rb +5 -2
  42. data/lib/authlogic/test_case.rb +74 -2
  43. data/lib/authlogic/version.rb +22 -0
  44. data/lib/authlogic.rb +33 -54
  45. metadata +208 -234
  46. data/.github/ISSUE_TEMPLATE.md +0 -13
  47. data/.gitignore +0 -14
  48. data/.rubocop.yml +0 -33
  49. data/.rubocop_todo.yml +0 -391
  50. data/.travis.yml +0 -48
  51. data/CHANGELOG.md +0 -5
  52. data/CONTRIBUTING.md +0 -60
  53. data/Gemfile +0 -5
  54. data/LICENSE +0 -20
  55. data/README.md +0 -294
  56. data/Rakefile +0 -21
  57. data/authlogic.gemspec +0 -27
  58. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +0 -70
  59. data/lib/authlogic/acts_as_authentic/validations_scope.rb +0 -32
  60. data/lib/authlogic/authenticates_many/association.rb +0 -50
  61. data/lib/authlogic/authenticates_many/base.rb +0 -65
  62. data/lib/authlogic/crypto_providers/aes256.rb +0 -66
  63. data/lib/authlogic/crypto_providers/wordpress.rb +0 -43
  64. data/lib/authlogic/regex.rb +0 -48
  65. data/lib/authlogic/session/activation.rb +0 -70
  66. data/lib/authlogic/session/active_record_trickery.rb +0 -61
  67. data/lib/authlogic/session/brute_force_protection.rb +0 -120
  68. data/lib/authlogic/session/callbacks.rb +0 -105
  69. data/lib/authlogic/session/cookies.rb +0 -244
  70. data/lib/authlogic/session/existence.rb +0 -93
  71. data/lib/authlogic/session/foundation.rb +0 -55
  72. data/lib/authlogic/session/http_auth.rb +0 -100
  73. data/lib/authlogic/session/id.rb +0 -48
  74. data/lib/authlogic/session/klass.rb +0 -70
  75. data/lib/authlogic/session/magic_columns.rb +0 -116
  76. data/lib/authlogic/session/magic_states.rb +0 -76
  77. data/lib/authlogic/session/params.rb +0 -116
  78. data/lib/authlogic/session/password.rb +0 -308
  79. data/lib/authlogic/session/perishable_token.rb +0 -23
  80. data/lib/authlogic/session/persistence.rb +0 -71
  81. data/lib/authlogic/session/priority_record.rb +0 -35
  82. data/lib/authlogic/session/scopes.rb +0 -119
  83. data/lib/authlogic/session/session.rb +0 -67
  84. data/lib/authlogic/session/timeout.rb +0 -103
  85. data/lib/authlogic/session/unauthorized_record.rb +0 -51
  86. data/lib/authlogic/session/validation.rb +0 -93
  87. data/test/acts_as_authentic_test/base_test.rb +0 -25
  88. data/test/acts_as_authentic_test/email_test.rb +0 -240
  89. data/test/acts_as_authentic_test/logged_in_status_test.rb +0 -62
  90. data/test/acts_as_authentic_test/login_test.rb +0 -156
  91. data/test/acts_as_authentic_test/magic_columns_test.rb +0 -27
  92. data/test/acts_as_authentic_test/password_test.rb +0 -249
  93. data/test/acts_as_authentic_test/perishable_token_test.rb +0 -90
  94. data/test/acts_as_authentic_test/persistence_token_test.rb +0 -56
  95. data/test/acts_as_authentic_test/restful_authentication_test.rb +0 -37
  96. data/test/acts_as_authentic_test/session_maintenance_test.rb +0 -96
  97. data/test/acts_as_authentic_test/single_access_test.rb +0 -44
  98. data/test/authenticates_many_test.rb +0 -31
  99. data/test/config_test.rb +0 -36
  100. data/test/crypto_provider_test/aes256_test.rb +0 -14
  101. data/test/crypto_provider_test/bcrypt_test.rb +0 -14
  102. data/test/crypto_provider_test/scrypt_test.rb +0 -14
  103. data/test/crypto_provider_test/sha1_test.rb +0 -23
  104. data/test/crypto_provider_test/sha256_test.rb +0 -14
  105. data/test/crypto_provider_test/sha512_test.rb +0 -14
  106. data/test/fixtures/companies.yml +0 -5
  107. data/test/fixtures/employees.yml +0 -17
  108. data/test/fixtures/projects.yml +0 -3
  109. data/test/fixtures/users.yml +0 -41
  110. data/test/gemfiles/Gemfile.rails-3.2.x +0 -7
  111. data/test/gemfiles/Gemfile.rails-4.0.x +0 -7
  112. data/test/gemfiles/Gemfile.rails-4.1.x +0 -7
  113. data/test/gemfiles/Gemfile.rails-4.2.x +0 -7
  114. data/test/gemfiles/Gemfile.rails-5.0.x +0 -6
  115. data/test/gemfiles/Gemfile.rails-5.1.x +0 -6
  116. data/test/gemfiles/Gemfile.rails-5.2.x +0 -6
  117. data/test/i18n/lol.yml +0 -4
  118. data/test/i18n_test.rb +0 -33
  119. data/test/libs/affiliate.rb +0 -7
  120. data/test/libs/company.rb +0 -6
  121. data/test/libs/employee.rb +0 -7
  122. data/test/libs/employee_session.rb +0 -2
  123. data/test/libs/ldaper.rb +0 -3
  124. data/test/libs/project.rb +0 -3
  125. data/test/libs/user.rb +0 -7
  126. data/test/libs/user_session.rb +0 -25
  127. data/test/random_test.rb +0 -43
  128. data/test/session_test/activation_test.rb +0 -43
  129. data/test/session_test/active_record_trickery_test.rb +0 -75
  130. data/test/session_test/brute_force_protection_test.rb +0 -108
  131. data/test/session_test/callbacks_test.rb +0 -34
  132. data/test/session_test/cookies_test.rb +0 -201
  133. data/test/session_test/credentials_test.rb +0 -0
  134. data/test/session_test/existence_test.rb +0 -75
  135. data/test/session_test/foundation_test.rb +0 -6
  136. data/test/session_test/http_auth_test.rb +0 -56
  137. data/test/session_test/id_test.rb +0 -17
  138. data/test/session_test/klass_test.rb +0 -40
  139. data/test/session_test/magic_columns_test.rb +0 -62
  140. data/test/session_test/magic_states_test.rb +0 -58
  141. data/test/session_test/params_test.rb +0 -53
  142. data/test/session_test/password_test.rb +0 -105
  143. data/test/session_test/perishability_test.rb +0 -15
  144. data/test/session_test/persistence_test.rb +0 -32
  145. data/test/session_test/scopes_test.rb +0 -60
  146. data/test/session_test/session_test.rb +0 -78
  147. data/test/session_test/timeout_test.rb +0 -82
  148. data/test/session_test/unauthorized_record_test.rb +0 -13
  149. data/test/session_test/validation_test.rb +0 -23
  150. data/test/test_helper.rb +0 -233
@@ -1,48 +0,0 @@
1
- # encoding: utf-8
2
- module Authlogic
3
- # This is a module the contains regular expressions used throughout Authlogic. The point of extracting
4
- # them out into their own module is to make them easily available to you for other uses. Ex:
5
- #
6
- # validates_format_of :my_email_field, :with => Authlogic::Regex.email
7
- module Regex
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.
13
- def self.email
14
- @email_regex ||= begin
15
- email_name_regex = '[A-Z0-9_\.&%\+\-\']+'
16
- domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
17
- domain_tld_regex = '(?:[A-Z]{2,25})'
18
- /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
19
- end
20
- end
21
-
22
- # A draft regular expression for internationalized email addresses.
23
- # Given that the standard may be in flux, this simply emulates @email_regex but rather than
24
- # allowing specific characters for each part, it instead disallows the complement set of characters:
25
- # - email_name_regex disallows: @[]^ !"#$()*,/:;<=>?`{|}~\ and control characters
26
- # - domain_head_regex disallows: _%+ and all characters in email_name_regex
27
- # - domain_tld_regex disallows: 0123456789- and all characters in domain_head_regex
28
- # http://en.wikipedia.org/wiki/Email_address#Internationalization
29
- # http://tools.ietf.org/html/rfc6530
30
- # http://www.unicode.org/faq/idn.html
31
- # http://ruby-doc.org/core-2.1.5/Regexp.html#class-Regexp-label-Character+Classes
32
- # http://en.wikipedia.org/wiki/Unicode_character_property#General_Category
33
- def self.email_nonascii
34
- @email_nonascii_regex ||= begin
35
- email_name_regex = '[^[:cntrl:][@\[\]\^ \!\"#$\(\)*,/:;<=>\?`{|}~\\\]]+'
36
- domain_head_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\']]+\.)+'
37
- domain_tld_regex = '(?:[^[:cntrl:][@\[\]\^ \!\"#$&\(\)*,/:;<=>\?`{|}~\\\_\.%\+\-\'0-9]]{2,25})'
38
- /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/
39
- end
40
- end
41
-
42
- # A simple regular expression that only allows for letters, numbers, spaces, and .-_@+. Just a standard login / username
43
- # regular expression.
44
- def self.login
45
- /\A[a-zA-Z0-9_][a-zA-Z0-9\.+\-_@ ]+\z/
46
- end
47
- end
48
- end
@@ -1,70 +0,0 @@
1
- require 'request_store'
2
-
3
- module Authlogic
4
- module Session
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.
10
- module Activation
11
- class NotActivatedError < ::StandardError # :nodoc:
12
- def initialize(session)
13
- super("You must activate the Authlogic::Session::Base.controller with a controller object before creating objects")
14
- end
15
- end
16
-
17
- def self.included(klass)
18
- klass.class_eval do
19
- extend ClassMethods
20
- include InstanceMethods
21
- end
22
- end
23
-
24
- module ClassMethods
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.
33
- def activated?
34
- !controller.nil?
35
- end
36
-
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.
43
- #
44
- # Lastly, this is thread safe.
45
- def controller=(value)
46
- RequestStore.store[:authlogic_controller] = value
47
- end
48
-
49
- # The current controller object
50
- def controller
51
- RequestStore.store[:authlogic_controller]
52
- end
53
- end
54
-
55
- module InstanceMethods
56
- # Making sure we are activated before we start creating objects
57
- def initialize(*args)
58
- raise NotActivatedError.new(self) unless self.class.activated?
59
- super
60
- end
61
-
62
- private
63
-
64
- def controller
65
- self.class.controller
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,61 +0,0 @@
1
- module Authlogic
2
- module Session
3
- # Authlogic looks like ActiveRecord, sounds like ActiveRecord, but its not ActiveRecord. That's the goal here.
4
- # This is useful for the various rails helper methods such as form_for, error_messages_for, or any method that
5
- # expects an ActiveRecord object. The point is to disguise the object as an ActiveRecord object so we can take
6
- # advantage of the many ActiveRecord tools.
7
- module ActiveRecordTrickery
8
- def self.included(klass)
9
- klass.extend ActiveModel::Naming
10
- klass.extend ActiveModel::Translation
11
-
12
- # Support ActiveModel::Name#name for Rails versions before 4.0.
13
- if !klass.model_name.respond_to?(:name)
14
- ActiveModel::Name.module_eval do
15
- alias_method :name, :to_s
16
- end
17
- end
18
-
19
- klass.extend ClassMethods
20
- klass.send(:include, InstanceMethods)
21
- end
22
-
23
- module ClassMethods
24
- # How to name the class, works JUST LIKE ActiveRecord, except it uses the following namespace:
25
- #
26
- # authlogic.models.user_session
27
- def human_name(*args)
28
- I18n.t("models.#{name.underscore}", { :count => 1, :default => name.humanize })
29
- end
30
-
31
- def i18n_scope
32
- I18n.scope
33
- end
34
- end
35
-
36
- module InstanceMethods
37
- # Don't use this yourself, this is to just trick some of the helpers since this is the method it calls.
38
- def new_record?
39
- new_session?
40
- end
41
-
42
- def persisted?
43
- !(new_record? || destroyed?)
44
- end
45
-
46
- def destroyed?
47
- record.nil?
48
- end
49
-
50
- def to_key
51
- new_record? ? nil : record.to_key
52
- end
53
-
54
- # For rails >= 3.0
55
- def to_model
56
- self
57
- end
58
- end
59
- end
60
- end
61
- end
@@ -1,120 +0,0 @@
1
- module Authlogic
2
- module Session
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.
11
- #
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:
19
- #
20
- # class UserSession < Authlogic::Session::Base
21
- # consecutive_failed_logins_limit 10
22
- # end
23
- module BruteForceProtection
24
- def self.included(klass)
25
- klass.class_eval do
26
- extend Config
27
- include InstanceMethods
28
- validate :reset_failed_login_count, :if => :reset_failed_login_count?
29
- validate :validate_failed_logins, :if => :being_brute_force_protected?
30
- end
31
- end
32
-
33
- # Configuration for the brute force protection feature.
34
- module Config
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.
40
- #
41
- # In order to enable this field your model MUST have a
42
- # failed_login_count (integer) field.
43
- #
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.
48
- #
49
- # * <tt>Default:</tt> 50
50
- # * <tt>Accepts:</tt> Integer, set to 0 to disable
51
- def consecutive_failed_logins_limit(value = nil)
52
- rw_config(:consecutive_failed_logins_limit, value, 50)
53
- end
54
- alias_method :consecutive_failed_logins_limit=, :consecutive_failed_logins_limit
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.
58
- #
59
- # * <tt>Default:</tt> 2.hours
60
- # * <tt>Accepts:</tt> Fixnum, set to 0 for permanent ban
61
- def failed_login_ban_for(value = nil)
62
- rw_config(:failed_login_ban_for, (!value.nil? && value) || value, 2.hours.to_i)
63
- end
64
- alias_method :failed_login_ban_for=, :failed_login_ban_for
65
- end
66
-
67
- # The methods available for an Authlogic::Session::Base object that make
68
- # up the brute force protection feature.
69
- module InstanceMethods
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.
75
- def being_brute_force_protected?
76
- exceeded_failed_logins_limit? && (failed_login_ban_for <= 0 ||
77
- (attempted_record.respond_to?(:updated_at) && attempted_record.updated_at >= failed_login_ban_for.seconds.ago))
78
- end
79
-
80
- private
81
-
82
- def exceeded_failed_logins_limit?
83
- !attempted_record.nil? && attempted_record.respond_to?(:failed_login_count) && consecutive_failed_logins_limit > 0 &&
84
- attempted_record.failed_login_count && attempted_record.failed_login_count >= consecutive_failed_logins_limit
85
- end
86
-
87
- def reset_failed_login_count?
88
- exceeded_failed_logins_limit? && !being_brute_force_protected?
89
- end
90
-
91
- def reset_failed_login_count
92
- attempted_record.failed_login_count = 0
93
- end
94
-
95
- def validate_failed_logins
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
- )
108
- end
109
-
110
- def consecutive_failed_logins_limit
111
- self.class.consecutive_failed_logins_limit
112
- end
113
-
114
- def failed_login_ban_for
115
- self.class.failed_login_ban_for
116
- end
117
- end
118
- end
119
- end
120
- end
@@ -1,105 +0,0 @@
1
- module Authlogic
2
- module Session
3
- # Between these callbacks and the configuration, this is the contract between me and you to safely
4
- # modify Authlogic's behavior. I will do everything I can to make sure these do not change.
5
- #
6
- # Check out the sub modules of Authlogic::Session. They are very concise, clear, and to the point. More
7
- # importantly they use the same API that you would use to extend Authlogic. That being said, they are great
8
- # examples of how to extend Authlogic and add / modify behavior to Authlogic. These modules could easily be pulled out
9
- # into their own plugin and become an "add on" without any change.
10
- #
11
- # Now to the point of this module. Just like in ActiveRecord you have before_save, before_validation, etc.
12
- # You have similar callbacks with Authlogic, see the METHODS constant below. The order of execution is as follows:
13
- #
14
- # before_persisting
15
- # persist
16
- # after_persisting
17
- # [save record if record.changed?]
18
- #
19
- # before_validation
20
- # before_validation_on_create
21
- # before_validation_on_update
22
- # validate
23
- # after_validation_on_update
24
- # after_validation_on_create
25
- # after_validation
26
- # [save record if record.changed?]
27
- #
28
- # before_save
29
- # before_create
30
- # before_update
31
- # after_update
32
- # after_create
33
- # after_save
34
- # [save record if record.changed?]
35
- #
36
- # before_destroy
37
- # [save record if record.changed?]
38
- # destroy
39
- # after_destroy
40
- #
41
- # Notice the "save record if changed?" lines above. This helps with performance. If you need to make
42
- # changes to the associated record, there is no need to save the record, Authlogic will do it for you.
43
- # This allows multiple modules to modify the record and execute as few queries as possible.
44
- #
45
- # **WARNING**: unlike ActiveRecord, these callbacks must be set up on the class level:
46
- #
47
- # class UserSession < Authlogic::Session::Base
48
- # before_validation :my_method
49
- # validate :another_method
50
- # # ..etc
51
- # end
52
- #
53
- # You can NOT define a "before_validation" method, this is bad practice and does not allow Authlogic
54
- # to extend properly with multiple extensions. Please ONLY use the method above.
55
- module Callbacks
56
- METHODS = [
57
- "before_persisting", "persist", "after_persisting",
58
- "before_validation", "before_validation_on_create", "before_validation_on_update", "validate",
59
- "after_validation_on_update", "after_validation_on_create", "after_validation",
60
- "before_save", "before_create", "before_update", "after_update", "after_create", "after_save",
61
- "before_destroy", "after_destroy"
62
- ]
63
-
64
- def self.included(base) #:nodoc:
65
- base.send :include, ActiveSupport::Callbacks
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 } }]
72
- else
73
- base.define_callbacks *METHODS + [{ :terminator => 'result == false' }]
74
- base.define_callbacks *['persist', { :terminator => 'result == true' }]
75
- end
76
-
77
- # If Rails 3, support the new callback syntax
78
- if base.singleton_class.method_defined?(:set_callback)
79
- METHODS.each do |method|
80
- base.class_eval <<-"end_eval", __FILE__, __LINE__
81
- def self.#{method}(*methods, &block)
82
- set_callback :#{method}, *methods, &block
83
- end
84
- end_eval
85
- end
86
- end
87
- end
88
-
89
- private
90
-
91
- METHODS.each do |method|
92
- class_eval <<-"end_eval", __FILE__, __LINE__
93
- def #{method}
94
- run_callbacks(:#{method})
95
- end
96
- end_eval
97
- end
98
-
99
- def save_record(alternate_record = nil)
100
- r = alternate_record || record
101
- r.save_without_session_maintenance(:validate => false) if r && r.changed? && !r.readonly?
102
- end
103
- end
104
- end
105
- end
@@ -1,244 +0,0 @@
1
- module Authlogic
2
- module Session
3
- # Handles all authentication that deals with cookies, such as persisting,
4
- # saving, and destroying.
5
- module Cookies
6
- def self.included(klass)
7
- klass.class_eval do
8
- extend Config
9
- include InstanceMethods
10
- persist :persist_by_cookie
11
- after_save :save_cookie
12
- after_destroy :destroy_cookie
13
- end
14
- end
15
-
16
- # Configuration for the cookie feature set.
17
- module Config
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:
22
- #
23
- # session = UserSession.new
24
- # session.cookie_key => "user_credentials"
25
- #
26
- # session = UserSession.new(:super_high_secret)
27
- # session.cookie_key => "super_high_secret_user_credentials"
28
- #
29
- # * <tt>Default:</tt> "#{klass_name.underscore}_credentials"
30
- # * <tt>Accepts:</tt> String
31
- def cookie_key(value = nil)
32
- rw_config(:cookie_key, value, "#{klass_name.underscore}_credentials")
33
- end
34
- alias_method :cookie_key=, :cookie_key
35
-
36
- # If sessions should be remembered by default or not.
37
- #
38
- # * <tt>Default:</tt> false
39
- # * <tt>Accepts:</tt> Boolean
40
- def remember_me(value = nil)
41
- rw_config(:remember_me, value, false)
42
- end
43
- alias_method :remember_me=, :remember_me
44
-
45
- # The length of time until the cookie expires.
46
- #
47
- # * <tt>Default:</tt> 3.months
48
- # * <tt>Accepts:</tt> Integer, length of time in seconds, such as 60 or 3.months
49
- def remember_me_for(value = nil)
50
- rw_config(:remember_me_for, value, 3.months)
51
- end
52
- alias_method :remember_me_for=, :remember_me_for
53
-
54
- # Should the cookie be set as secure? If true, the cookie will only be sent over
55
- # SSL connections
56
- #
57
- # * <tt>Default:</tt> false
58
- # * <tt>Accepts:</tt> Boolean
59
- def secure(value = nil)
60
- rw_config(:secure, value, false)
61
- end
62
- alias_method :secure=, :secure
63
-
64
- # Should the cookie be set as httponly? If true, the cookie will not be
65
- # accessible from javascript
66
- #
67
- # * <tt>Default:</tt> false
68
- # * <tt>Accepts:</tt> Boolean
69
- def httponly(value = nil)
70
- rw_config(:httponly, value, false)
71
- end
72
- alias_method :httponly=, :httponly
73
-
74
- # Should the cookie be signed? If the controller adapter supports it, this is a
75
- # measure against cookie tampering.
76
- def sign_cookie(value = nil)
77
- if value && !controller.cookies.respond_to?(:signed)
78
- raise "Signed cookies not supported with #{controller.class}!"
79
- end
80
- rw_config(:sign_cookie, value, false)
81
- end
82
- alias_method :sign_cookie=, :sign_cookie
83
- end
84
-
85
- # The methods available for an Authlogic::Session::Base object that make up the
86
- # cookie feature set.
87
- module InstanceMethods
88
- # Allows you to set the remember_me option when passing credentials.
89
- def credentials=(value)
90
- super
91
- values = value.is_a?(Array) ? value : [value]
92
- case values.first
93
- when Hash
94
- if values.first.with_indifferent_access.key?(:remember_me)
95
- self.remember_me = values.first.with_indifferent_access[:remember_me]
96
- end
97
- else
98
- r = values.find { |value| value.is_a?(TrueClass) || value.is_a?(FalseClass) }
99
- self.remember_me = r if !r.nil?
100
- end
101
- end
102
-
103
- # Is the cookie going to expire after the session is over, or will it stick around?
104
- def remember_me
105
- return @remember_me if defined?(@remember_me)
106
- @remember_me = self.class.remember_me
107
- end
108
-
109
- # Accepts a boolean as a flag to remember the session or not. Basically
110
- # to expire the cookie at the end of the session or keep it for
111
- # "remember_me_until".
112
- def remember_me=(value)
113
- @remember_me = value
114
- end
115
-
116
- # See remember_me
117
- def remember_me?
118
- remember_me == true || remember_me == "true" || remember_me == "1"
119
- end
120
-
121
- # How long to remember the user if remember_me is true. This is based on the class
122
- # level configuration: remember_me_for
123
- def remember_me_for
124
- return unless remember_me?
125
- self.class.remember_me_for
126
- end
127
-
128
- # When to expire the cookie. See remember_me_for configuration option to change
129
- # this.
130
- def remember_me_until
131
- return unless remember_me?
132
- remember_me_for.from_now
133
- end
134
-
135
- # Has the cookie expired due to current time being greater than remember_me_until.
136
- def remember_me_expired?
137
- return unless remember_me?
138
- (Time.parse(cookie_credentials[2]) < Time.now)
139
- end
140
-
141
- # If the cookie should be marked as secure (SSL only)
142
- def secure
143
- return @secure if defined?(@secure)
144
- @secure = self.class.secure
145
- end
146
-
147
- # Accepts a boolean as to whether the cookie should be marked as secure. If true
148
- # the cookie will only ever be sent over an SSL connection.
149
- def secure=(value)
150
- @secure = value
151
- end
152
-
153
- # See secure
154
- def secure?
155
- secure == true || secure == "true" || secure == "1"
156
- end
157
-
158
- # If the cookie should be marked as httponly (not accessible via javascript)
159
- def httponly
160
- return @httponly if defined?(@httponly)
161
- @httponly = self.class.httponly
162
- end
163
-
164
- # Accepts a boolean as to whether the cookie should be marked as
165
- # httponly. If true, the cookie will not be accessible from javascript
166
- def httponly=(value)
167
- @httponly = value
168
- end
169
-
170
- # See httponly
171
- def httponly?
172
- httponly == true || httponly == "true" || httponly == "1"
173
- end
174
-
175
- # If the cookie should be signed
176
- def sign_cookie
177
- return @sign_cookie if defined?(@sign_cookie)
178
- @sign_cookie = self.class.sign_cookie
179
- end
180
-
181
- # Accepts a boolean as to whether the cookie should be signed. If true
182
- # the cookie will be saved and verified using a signature.
183
- def sign_cookie=(value)
184
- @sign_cookie = value
185
- end
186
-
187
- # See sign_cookie
188
- def sign_cookie?
189
- sign_cookie == true || sign_cookie == "true" || sign_cookie == "1"
190
- end
191
-
192
- private
193
-
194
- def cookie_key
195
- build_key(self.class.cookie_key)
196
- end
197
-
198
- def cookie_credentials
199
- if self.class.sign_cookie
200
- cookie = controller.cookies.signed[cookie_key]
201
- else
202
- cookie = controller.cookies[cookie_key]
203
- end
204
- cookie && cookie.split("::")
205
- end
206
-
207
- # Tries to validate the session from information in the cookie
208
- def persist_by_cookie
209
- persistence_token, record_id = cookie_credentials
210
- if persistence_token.present?
211
- record = search_for_record("find_by_#{klass.primary_key}", record_id)
212
- self.unauthorized_record = record if record && record.persistence_token == persistence_token
213
- valid?
214
- else
215
- false
216
- end
217
- end
218
-
219
- def save_cookie
220
- if sign_cookie?
221
- controller.cookies.signed[cookie_key] = generate_cookie_for_saving
222
- else
223
- controller.cookies[cookie_key] = generate_cookie_for_saving
224
- end
225
- end
226
-
227
- def generate_cookie_for_saving
228
- remember_me_until_value = "::#{remember_me_until.iso8601}" if remember_me?
229
- {
230
- :value => "#{record.persistence_token}::#{record.send(record.class.primary_key)}#{remember_me_until_value}",
231
- :expires => remember_me_until,
232
- :secure => secure,
233
- :httponly => httponly,
234
- :domain => controller.cookie_domain
235
- }
236
- end
237
-
238
- def destroy_cookie
239
- controller.cookies.delete cookie_key, :domain => controller.cookie_domain
240
- end
241
- end
242
- end
243
- end
244
- end