authlogic 3.8.0 → 6.0.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.
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