drogus-authlogic 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. data/.gitignore +9 -0
  2. data/CHANGELOG.rdoc +345 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +246 -0
  5. data/Rakefile +42 -0
  6. data/VERSION.yml +5 -0
  7. data/authlogic.gemspec +217 -0
  8. data/generators/session/session_generator.rb +9 -0
  9. data/generators/session/templates/session.rb +2 -0
  10. data/init.rb +1 -0
  11. data/lib/authlogic.rb +64 -0
  12. data/lib/authlogic/acts_as_authentic/base.rb +107 -0
  13. data/lib/authlogic/acts_as_authentic/email.rb +110 -0
  14. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +60 -0
  15. data/lib/authlogic/acts_as_authentic/login.rb +137 -0
  16. data/lib/authlogic/acts_as_authentic/magic_columns.rb +24 -0
  17. data/lib/authlogic/acts_as_authentic/password.rb +355 -0
  18. data/lib/authlogic/acts_as_authentic/perishable_token.rb +105 -0
  19. data/lib/authlogic/acts_as_authentic/persistence_token.rb +68 -0
  20. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +61 -0
  21. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +139 -0
  22. data/lib/authlogic/acts_as_authentic/single_access_token.rb +65 -0
  23. data/lib/authlogic/acts_as_authentic/validations_scope.rb +32 -0
  24. data/lib/authlogic/authenticates_many/association.rb +42 -0
  25. data/lib/authlogic/authenticates_many/base.rb +55 -0
  26. data/lib/authlogic/controller_adapters/abstract_adapter.rb +67 -0
  27. data/lib/authlogic/controller_adapters/merb_adapter.rb +30 -0
  28. data/lib/authlogic/controller_adapters/rails_adapter.rb +48 -0
  29. data/lib/authlogic/controller_adapters/sinatra_adapter.rb +61 -0
  30. data/lib/authlogic/crypto_providers/aes256.rb +43 -0
  31. data/lib/authlogic/crypto_providers/bcrypt.rb +90 -0
  32. data/lib/authlogic/crypto_providers/md5.rb +34 -0
  33. data/lib/authlogic/crypto_providers/sha1.rb +35 -0
  34. data/lib/authlogic/crypto_providers/sha256.rb +50 -0
  35. data/lib/authlogic/crypto_providers/sha512.rb +50 -0
  36. data/lib/authlogic/crypto_providers/wordpress.rb +43 -0
  37. data/lib/authlogic/i18n.rb +83 -0
  38. data/lib/authlogic/i18n/translator.rb +15 -0
  39. data/lib/authlogic/random.rb +33 -0
  40. data/lib/authlogic/regex.rb +25 -0
  41. data/lib/authlogic/session/activation.rb +58 -0
  42. data/lib/authlogic/session/active_record_trickery.rb +64 -0
  43. data/lib/authlogic/session/base.rb +37 -0
  44. data/lib/authlogic/session/brute_force_protection.rb +96 -0
  45. data/lib/authlogic/session/callbacks.rb +99 -0
  46. data/lib/authlogic/session/cookies.rb +130 -0
  47. data/lib/authlogic/session/existence.rb +93 -0
  48. data/lib/authlogic/session/foundation.rb +63 -0
  49. data/lib/authlogic/session/http_auth.rb +58 -0
  50. data/lib/authlogic/session/id.rb +41 -0
  51. data/lib/authlogic/session/klass.rb +78 -0
  52. data/lib/authlogic/session/magic_columns.rb +95 -0
  53. data/lib/authlogic/session/magic_states.rb +59 -0
  54. data/lib/authlogic/session/params.rb +101 -0
  55. data/lib/authlogic/session/password.rb +240 -0
  56. data/lib/authlogic/session/perishable_token.rb +18 -0
  57. data/lib/authlogic/session/persistence.rb +70 -0
  58. data/lib/authlogic/session/priority_record.rb +34 -0
  59. data/lib/authlogic/session/scopes.rb +101 -0
  60. data/lib/authlogic/session/session.rb +62 -0
  61. data/lib/authlogic/session/timeout.rb +82 -0
  62. data/lib/authlogic/session/unauthorized_record.rb +50 -0
  63. data/lib/authlogic/session/validation.rb +82 -0
  64. data/lib/authlogic/test_case.rb +120 -0
  65. data/lib/authlogic/test_case/mock_controller.rb +45 -0
  66. data/lib/authlogic/test_case/mock_cookie_jar.rb +14 -0
  67. data/lib/authlogic/test_case/mock_logger.rb +10 -0
  68. data/lib/authlogic/test_case/mock_request.rb +19 -0
  69. data/lib/authlogic/test_case/rails_request_adapter.rb +30 -0
  70. data/rails/init.rb +1 -0
  71. data/shoulda_macros/authlogic.rb +69 -0
  72. data/test/acts_as_authentic_test/base_test.rb +18 -0
  73. data/test/acts_as_authentic_test/email_test.rb +97 -0
  74. data/test/acts_as_authentic_test/logged_in_status_test.rb +36 -0
  75. data/test/acts_as_authentic_test/login_test.rb +109 -0
  76. data/test/acts_as_authentic_test/magic_columns_test.rb +27 -0
  77. data/test/acts_as_authentic_test/password_test.rb +236 -0
  78. data/test/acts_as_authentic_test/perishable_token_test.rb +90 -0
  79. data/test/acts_as_authentic_test/persistence_token_test.rb +55 -0
  80. data/test/acts_as_authentic_test/restful_authentication_test.rb +40 -0
  81. data/test/acts_as_authentic_test/session_maintenance_test.rb +84 -0
  82. data/test/acts_as_authentic_test/single_access_test.rb +44 -0
  83. data/test/authenticates_many_test.rb +16 -0
  84. data/test/crypto_provider_test/aes256_test.rb +14 -0
  85. data/test/crypto_provider_test/bcrypt_test.rb +14 -0
  86. data/test/crypto_provider_test/sha1_test.rb +23 -0
  87. data/test/crypto_provider_test/sha256_test.rb +14 -0
  88. data/test/crypto_provider_test/sha512_test.rb +14 -0
  89. data/test/fixtures/companies.yml +5 -0
  90. data/test/fixtures/employees.yml +17 -0
  91. data/test/fixtures/projects.yml +3 -0
  92. data/test/fixtures/users.yml +24 -0
  93. data/test/i18n_test.rb +33 -0
  94. data/test/libs/affiliate.rb +7 -0
  95. data/test/libs/company.rb +6 -0
  96. data/test/libs/employee.rb +7 -0
  97. data/test/libs/employee_session.rb +2 -0
  98. data/test/libs/ldaper.rb +3 -0
  99. data/test/libs/ordered_hash.rb +9 -0
  100. data/test/libs/project.rb +3 -0
  101. data/test/libs/user.rb +5 -0
  102. data/test/libs/user_session.rb +6 -0
  103. data/test/random_test.rb +49 -0
  104. data/test/session_test/activation_test.rb +43 -0
  105. data/test/session_test/active_record_trickery_test.rb +36 -0
  106. data/test/session_test/brute_force_protection_test.rb +101 -0
  107. data/test/session_test/callbacks_test.rb +6 -0
  108. data/test/session_test/cookies_test.rb +112 -0
  109. data/test/session_test/credentials_test.rb +0 -0
  110. data/test/session_test/existence_test.rb +64 -0
  111. data/test/session_test/http_auth_test.rb +28 -0
  112. data/test/session_test/id_test.rb +17 -0
  113. data/test/session_test/klass_test.rb +40 -0
  114. data/test/session_test/magic_columns_test.rb +62 -0
  115. data/test/session_test/magic_states_test.rb +60 -0
  116. data/test/session_test/params_test.rb +53 -0
  117. data/test/session_test/password_test.rb +106 -0
  118. data/test/session_test/perishability_test.rb +15 -0
  119. data/test/session_test/persistence_test.rb +21 -0
  120. data/test/session_test/scopes_test.rb +60 -0
  121. data/test/session_test/session_test.rb +59 -0
  122. data/test/session_test/timeout_test.rb +52 -0
  123. data/test/session_test/unauthorized_record_test.rb +13 -0
  124. data/test/session_test/validation_test.rb +23 -0
  125. data/test/test_helper.rb +182 -0
  126. metadata +238 -0
@@ -0,0 +1,240 @@
1
+ module Authlogic
2
+ module Session
3
+ # Handles authenticating via a traditional username and password.
4
+ module Password
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ extend Config
8
+ include InstanceMethods
9
+ validate :validate_by_password, :if => :authenticating_with_password?
10
+
11
+ class << self
12
+ attr_accessor :configured_password_methods
13
+ end
14
+ end
15
+ end
16
+
17
+ # Password configuration
18
+ module Config
19
+ # Authlogic tries to validate the credentials passed to it. One part of validation is actually finding the user and
20
+ # making sure it exists. What method it uses the do this is up to you.
21
+ #
22
+ # Let's say you have a UserSession that is authenticating a User. By default UserSession will call User.find_by_login(login).
23
+ # You can change what method UserSession calls by specifying it here. Then in your User model you can make that method do
24
+ # anything you want, giving you complete control of how users are found by the UserSession.
25
+ #
26
+ # Let's take an example: You want to allow users to login by username or email. Set this to the name of the class method
27
+ # that does this in the User model. Let's call it "find_by_username_or_email"
28
+ #
29
+ # class User < ActiveRecord::Base
30
+ # def self.find_by_username_or_email(login)
31
+ # find_by_username(login) || find_by_email(login)
32
+ # end
33
+ # end
34
+ #
35
+ # Now just specify the name of this method for this configuration option and you are all set. You can do anything you
36
+ # want here. Maybe you allow users to have multiple logins and you want to search a has_many relationship, etc. The sky is the limit.
37
+ #
38
+ # * <tt>Default:</tt> "find_by_smart_case_login_field"
39
+ # * <tt>Accepts:</tt> Symbol or String
40
+ def find_by_login_method(value = nil)
41
+ rw_config(:find_by_login_method, value, "find_by_smart_case_login_field")
42
+ end
43
+ alias_method :find_by_login_method=, :find_by_login_method
44
+
45
+ # The text used to identify credentials (username/password) combination when a bad login attempt occurs.
46
+ # When you show error messages for a bad login, it's considered good security practice to hide which field
47
+ # the user has entered incorrectly (the login field or the password field). For a full explanation, see
48
+ # http://www.gnucitizen.org/blog/username-enumeration-vulnerabilities/
49
+ #
50
+ # Example of use:
51
+ #
52
+ # class UserSession < Authlogic::Session::Base
53
+ # generalize_credentials_error_messages true
54
+ # end
55
+ #
56
+ # This would make the error message for bad logins and bad passwords look identical:
57
+ #
58
+ # Login/Password combination is not valid
59
+ #
60
+ # Alternatively you may use a custom message:
61
+ #
62
+ # class UserSession < AuthLogic::Session::Base
63
+ # generalize_credentials_error_messages "Your login information is invalid"
64
+ # end
65
+ #
66
+ # This will instead show your custom error message when the UserSession is invalid.
67
+ #
68
+ # The downside to enabling this is that is can be too vague for a user that has a hard time remembering
69
+ # their username and password combinations. It also disables the ability to to highlight the field
70
+ # with the error when you use form_for.
71
+ #
72
+ # If you are developing an app where security is an extreme priority (such as a financial application),
73
+ # then you should enable this. Otherwise, leaving this off is fine.
74
+ #
75
+ # * <tt>Default</tt> false
76
+ # * <tt>Accepts:</tt> Boolean
77
+ def generalize_credentials_error_messages(value = nil)
78
+ rw_config(:generalize_credentials_error_messages, value, false)
79
+ end
80
+ alias_method :generalize_credentials_error_messages=, :generalize_credentials_error_messages
81
+
82
+ # The name of the method you want Authlogic to create for storing the login / username. Keep in mind this is just for your
83
+ # Authlogic::Session, if you want it can be something completely different than the field in your model. So if you wanted people to
84
+ # login with a field called "login" and then find users by email this is compeltely doable. See the find_by_login_method configuration
85
+ # option for more details.
86
+ #
87
+ # * <tt>Default:</tt> klass.login_field || klass.email_field
88
+ # * <tt>Accepts:</tt> Symbol or String
89
+ def login_field(value = nil)
90
+ rw_config(:login_field, value, klass.login_field || klass.email_field)
91
+ end
92
+ alias_method :login_field=, :login_field
93
+
94
+ # Works exactly like login_field, but for the password instead. Returns :password if a login_field exists.
95
+ #
96
+ # * <tt>Default:</tt> :password
97
+ # * <tt>Accepts:</tt> Symbol or String
98
+ def password_field(value = nil)
99
+ rw_config(:password_field, value, login_field && :password)
100
+ end
101
+ alias_method :password_field=, :password_field
102
+
103
+ # The name of the method in your model used to verify the password. This should be an instance method. It should also
104
+ # be prepared to accept a raw password and a crytped password.
105
+ #
106
+ # * <tt>Default:</tt> "valid_password?"
107
+ # * <tt>Accepts:</tt> Symbol or String
108
+ def verify_password_method(value = nil)
109
+ rw_config(:verify_password_method, value, "valid_password?")
110
+ end
111
+ alias_method :verify_password_method=, :verify_password_method
112
+ end
113
+
114
+ # Password related instance methods
115
+ module InstanceMethods
116
+ def initialize(*args)
117
+ if !self.class.configured_password_methods
118
+ if login_field
119
+ self.class.send(:attr_writer, login_field) if !respond_to?("#{login_field}=")
120
+ self.class.send(:attr_reader, login_field) if !respond_to?(login_field)
121
+ end
122
+
123
+ if password_field
124
+ self.class.send(:attr_writer, password_field) if !respond_to?("#{password_field}=")
125
+ self.class.send(:define_method, password_field) {} if !respond_to?(password_field)
126
+
127
+ self.class.class_eval <<-"end_eval", __FILE__, __LINE__
128
+ private
129
+ # The password should not be accessible publicly. This way forms using form_for don't fill the password with the
130
+ # attempted password. To prevent this we just create this method that is private.
131
+ def protected_#{password_field}
132
+ @#{password_field}
133
+ end
134
+ end_eval
135
+ end
136
+
137
+ self.class.configured_password_methods = true
138
+ end
139
+
140
+ super
141
+ end
142
+
143
+ # Returns the login_field / password_field credentials combination in hash form.
144
+ def credentials
145
+ if authenticating_with_password?
146
+ details = {}
147
+ details[login_field.to_sym] = send(login_field)
148
+ details[password_field.to_sym] = "<protected>"
149
+ details
150
+ else
151
+ super
152
+ end
153
+ end
154
+
155
+ # Accepts the login_field / password_field credentials combination in hash form.
156
+ def credentials=(value)
157
+ super
158
+ values = value.is_a?(Array) ? value : [value]
159
+ if values.first.is_a?(Hash)
160
+ values.first.with_indifferent_access.slice(login_field, password_field).each do |field, value|
161
+ next if value.blank?
162
+ send("#{field}=", value)
163
+ end
164
+ end
165
+ end
166
+
167
+ def invalid_password?
168
+ invalid_password == true
169
+ end
170
+
171
+ private
172
+ def authenticating_with_password?
173
+ login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
174
+ end
175
+
176
+ def validate_by_password
177
+ self.invalid_password = false
178
+
179
+ errors.add(login_field, I18n.t('error_messages.login_blank', :default => "cannot be blank")) if send(login_field).blank?
180
+ errors.add(password_field, I18n.t('error_messages.password_blank', :default => "cannot be blank")) if send("protected_#{password_field}").blank?
181
+ return if errors.count > 0
182
+
183
+ self.attempted_record = search_for_record(find_by_login_method, send(login_field))
184
+ if attempted_record.blank?
185
+ generalize_credentials_error_messages? ?
186
+ add_general_credentials_error :
187
+ errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
188
+ return
189
+ end
190
+
191
+ if !attempted_record.send(verify_password_method, send("protected_#{password_field}"))
192
+ self.invalid_password = true
193
+ generalize_credentials_error_messages? ?
194
+ add_general_credentials_error :
195
+ errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid"))
196
+ return
197
+ end
198
+ end
199
+
200
+ def invalid_password
201
+ @invalid_password
202
+ end
203
+
204
+ def invalid_password=(value)
205
+ @invalid_password = value
206
+ end
207
+
208
+ def find_by_login_method
209
+ self.class.find_by_login_method
210
+ end
211
+
212
+ def login_field
213
+ self.class.login_field
214
+ end
215
+
216
+ def add_general_credentials_error
217
+ error_message =
218
+ if self.class.generalize_credentials_error_messages.is_a? String
219
+ self.class.generalize_credentials_error_messages
220
+ else
221
+ "#{login_field.to_s.humanize}/Password combination is not valid"
222
+ end
223
+ errors.add(:base, I18n.t('error_messages.general_credentials_error', :default => error_message))
224
+ end
225
+
226
+ def generalize_credentials_error_messages?
227
+ self.class.generalize_credentials_error_messages
228
+ end
229
+
230
+ def password_field
231
+ self.class.password_field
232
+ end
233
+
234
+ def verify_password_method
235
+ self.class.verify_password_method
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,18 @@
1
+ module Authlogic
2
+ module Session
3
+ # Maintains the perishable token, which is helpful for confirming records or authorizing records to reset their password. All that this
4
+ # module does is reset it after a session have been saved, just keep it changing. The more it changes, the tighter the security.
5
+ #
6
+ # See Authlogic::ActsAsAuthentic::PerishableToken for more information.
7
+ module PerishableToken
8
+ def self.included(klass)
9
+ klass.after_save :reset_perishable_token!
10
+ end
11
+
12
+ private
13
+ def reset_perishable_token!
14
+ record.reset_perishable_token if record.respond_to?(:reset_perishable_token) && !record.disable_perishable_token_maintenance?
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,70 @@
1
+ module Authlogic
2
+ module Session
3
+ # Responsible for allowing you to persist your sessions.
4
+ module Persistence
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ extend ClassMethods
8
+ include InstanceMethods
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ # This is how you persist a session. This finds the record for the current session using
14
+ # a variety of methods. It basically tries to "log in" the user without the user having
15
+ # to explicitly log in. Check out the other Authlogic::Session modules for more information.
16
+ #
17
+ # The best way to use this method is something like:
18
+ #
19
+ # helper_method :current_user_session, :current_user
20
+ #
21
+ # def current_user_session
22
+ # return @current_user_session if defined?(@current_user_session)
23
+ # @current_user_session = UserSession.find
24
+ # end
25
+ #
26
+ # def current_user
27
+ # return @current_user if defined?(@current_user)
28
+ # @current_user = current_user_session && current_user_session.user
29
+ # end
30
+ #
31
+ # Also, this method accepts a single parameter as the id, to find session that you marked with an id:
32
+ #
33
+ # UserSession.find(:secure)
34
+ #
35
+ # See the id method for more information on ids.
36
+ def find(id = nil, priority_record = nil)
37
+ session = new({:priority_record => priority_record}, id)
38
+ session.priority_record = priority_record
39
+ if session.persisting?
40
+ session
41
+ else
42
+ nil
43
+ end
44
+ end
45
+ end
46
+
47
+ module InstanceMethods
48
+ # Let's you know if the session is being persisted or not, meaning the user does not have to explicitly log in
49
+ # in order to be logged in. If the session has no associated record, it will try to find a record and persis
50
+ # the session. This is the method that the class level method find uses to ultimately persist the session.
51
+ def persisting?
52
+ return true if !record.nil?
53
+ self.attempted_record = nil
54
+ before_persisting
55
+ persist
56
+ ensure_authentication_attempted
57
+ if errors.empty? && !attempted_record.nil?
58
+ self.record = attempted_record
59
+ after_persisting
60
+ save_record
61
+ self.new_session = false
62
+ true
63
+ else
64
+ false
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,34 @@
1
+ module Authlogic
2
+ module Session
3
+ # The point of this module is to avoid the StaleObjectError raised when lock_version is implemented in ActiveRecord.
4
+ # We accomplish this by using a "priority record". Meaning this record is used if possible, it gets priority.
5
+ # This way we don't save a record behind the scenes thus making an object being used stale.
6
+ module PriorityRecord
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ attr_accessor :priority_record
10
+ end
11
+ end
12
+
13
+ # Setting priority record if it is passed. The only way it can be passed is through an array:
14
+ #
15
+ # session.credentials = [real_user_object, priority_user_object]
16
+ def credentials=(value)
17
+ super
18
+ values = value.is_a?(Array) ? value : [value]
19
+ self.priority_record = values[1] if values[1].class < ::ActiveRecord::Base
20
+ end
21
+
22
+ private
23
+ def attempted_record=(value)
24
+ value = priority_record if value == priority_record
25
+ super
26
+ end
27
+
28
+ def save_record(alternate_record = nil)
29
+ r = alternate_record || record
30
+ super if r != priority_record
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,101 @@
1
+ module Authlogic
2
+ module Session
3
+ # Authentication can be scoped, and it's easy, you just need to define how you want to scope everything. This should help you:
4
+ #
5
+ # 1. Want to scope by a parent object? Ex: An account has many users. Checkout Authlogic::AuthenticatesMany
6
+ # 2. Want to scope the validations in your model? Ex: 2 users can have the same login under different accounts. See Authlogic::ActsAsAuthentic::Scope
7
+ module Scopes # :nodoc:
8
+ def self.included(klass)
9
+ klass.class_eval do
10
+ extend ClassMethods
11
+ include InstanceMethods
12
+ attr_writer :scope
13
+ end
14
+ end
15
+
16
+ # = Scopes
17
+ module ClassMethods
18
+ # The current scope set, should be used in the block passed to with_scope.
19
+ def scope
20
+ Thread.current[:authlogic_scope]
21
+ end
22
+
23
+ # What with_scopes focuses on is scoping the query when finding the object and the name of the cookie / session. It works very similar to
24
+ # ActiveRecord::Base#with_scopes. It accepts a hash with any of the following options:
25
+ #
26
+ # * <tt>find_options:</tt> any options you can pass into ActiveRecord::Base.find. This is used when trying to find the record.
27
+ # * <tt>id:</tt> The id of the session, this gets merged with the real id. For information ids see the id method.
28
+ #
29
+ # Here is how you use it:
30
+ #
31
+ # UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
32
+ # UserSession.find
33
+ # end
34
+ #
35
+ # Eseentially what the above does is scope the searching of the object with the sql you provided. So instead of:
36
+ #
37
+ # User.find(:first, :conditions => "login = 'ben'")
38
+ #
39
+ # it would be:
40
+ #
41
+ # User.find(:first, :conditions => "login = 'ben' and account_id = 2")
42
+ #
43
+ # You will also notice the :id option. This works just like the id method. It scopes your cookies. So the name of your cookie will be:
44
+ #
45
+ # account_2_user_credentials
46
+ #
47
+ # instead of:
48
+ #
49
+ # user_credentials
50
+ #
51
+ # What is also nifty about scoping with an :id is that it merges your id's. So if you do:
52
+ #
53
+ # UserSession.with_scope(:find_options => {:conditions => "account_id = 2"}, :id => "account_2") do
54
+ # session = UserSession.new
55
+ # session.id = :secure
56
+ # end
57
+ #
58
+ # The name of your cookies will be:
59
+ #
60
+ # secure_account_2_user_credentials
61
+ def with_scope(options = {}, &block)
62
+ raise ArgumentError.new("You must provide a block") unless block_given?
63
+ self.scope = options
64
+ result = yield
65
+ self.scope = nil
66
+ result
67
+ end
68
+
69
+ private
70
+ def scope=(value)
71
+ Thread.current[:authlogic_scope] = value
72
+ end
73
+ end
74
+
75
+ module InstanceMethods
76
+ # Setting the scope if it exists upon instantiation.
77
+ def initialize(*args)
78
+ self.scope = self.class.scope
79
+ super
80
+ end
81
+
82
+ # The scope of the current object
83
+ def scope
84
+ @scope ||= {}
85
+ end
86
+
87
+ private
88
+ # Used for things like cookie_key, session_key, etc.
89
+ def build_key(last_part)
90
+ [scope[:id], super].compact.join("_")
91
+ end
92
+
93
+ def search_for_record(*args)
94
+ klass.send(:with_scope, :find => (scope[:find_options] || {})) do
95
+ klass.send(*args)
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end