authlogic 1.4.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of authlogic might be problematic. Click here for more details.

Files changed (131) hide show
  1. data/CHANGELOG.rdoc +19 -0
  2. data/Manifest.txt +111 -0
  3. data/README.rdoc +116 -389
  4. data/Rakefile +14 -7
  5. data/lib/authlogic.rb +33 -35
  6. data/lib/authlogic/acts_as_authentic/base.rb +91 -0
  7. data/lib/authlogic/acts_as_authentic/email.rb +77 -0
  8. data/lib/authlogic/acts_as_authentic/logged_in_status.rb +54 -0
  9. data/lib/authlogic/acts_as_authentic/login.rb +65 -0
  10. data/lib/authlogic/acts_as_authentic/magic_columns.rb +24 -0
  11. data/lib/authlogic/acts_as_authentic/password.rb +215 -0
  12. data/lib/authlogic/acts_as_authentic/perishable_token.rb +100 -0
  13. data/lib/authlogic/acts_as_authentic/persistence_token.rb +66 -0
  14. data/lib/authlogic/acts_as_authentic/restful_authentication.rb +60 -0
  15. data/lib/authlogic/acts_as_authentic/session_maintenance.rb +127 -0
  16. data/lib/authlogic/acts_as_authentic/single_access_token.rb +58 -0
  17. data/lib/authlogic/acts_as_authentic/validations_scope.rb +32 -0
  18. data/lib/authlogic/{session/authenticates_many_association.rb → authenticates_many/association.rb} +10 -6
  19. data/lib/authlogic/authenticates_many/base.rb +55 -0
  20. data/lib/authlogic/controller_adapters/abstract_adapter.rb +2 -3
  21. data/lib/authlogic/controller_adapters/merb_adapter.rb +0 -4
  22. data/lib/authlogic/controller_adapters/rails_adapter.rb +0 -4
  23. data/lib/authlogic/crypto_providers/aes256.rb +0 -2
  24. data/lib/authlogic/crypto_providers/bcrypt.rb +0 -2
  25. data/lib/authlogic/crypto_providers/md5.rb +34 -0
  26. data/lib/authlogic/crypto_providers/sha1.rb +0 -2
  27. data/lib/authlogic/crypto_providers/sha512.rb +1 -3
  28. data/lib/authlogic/i18n.rb +1 -4
  29. data/lib/authlogic/random.rb +33 -0
  30. data/lib/authlogic/session/activation.rb +56 -0
  31. data/lib/authlogic/session/active_record_trickery.rb +15 -7
  32. data/lib/authlogic/session/base.rb +31 -456
  33. data/lib/authlogic/session/brute_force_protection.rb +50 -27
  34. data/lib/authlogic/session/callbacks.rb +24 -15
  35. data/lib/authlogic/session/cookies.rb +108 -22
  36. data/lib/authlogic/session/existence.rb +89 -0
  37. data/lib/authlogic/session/foundation.rb +63 -0
  38. data/lib/authlogic/session/http_auth.rb +23 -0
  39. data/lib/authlogic/session/id.rb +41 -0
  40. data/lib/authlogic/session/klass.rb +75 -0
  41. data/lib/authlogic/session/magic_columns.rb +75 -0
  42. data/lib/authlogic/session/magic_states.rb +58 -0
  43. data/lib/authlogic/session/params.rb +82 -19
  44. data/lib/authlogic/session/password.rb +156 -0
  45. data/lib/authlogic/session/{perishability.rb → perishable_token.rb} +4 -4
  46. data/lib/authlogic/session/persistence.rb +70 -0
  47. data/lib/authlogic/session/priority_record.rb +34 -0
  48. data/lib/authlogic/session/scopes.rb +57 -53
  49. data/lib/authlogic/session/session.rb +46 -31
  50. data/lib/authlogic/session/timeout.rb +65 -31
  51. data/lib/authlogic/session/unauthorized_record.rb +50 -0
  52. data/lib/authlogic/session/validation.rb +76 -0
  53. data/lib/authlogic/testing/test_unit_helpers.rb +3 -3
  54. data/lib/authlogic/version.rb +3 -3
  55. data/test/acts_as_authentic_test/base_test.rb +12 -0
  56. data/test/acts_as_authentic_test/email_test.rb +79 -0
  57. data/test/acts_as_authentic_test/logged_in_status_test.rb +36 -0
  58. data/test/acts_as_authentic_test/login_test.rb +79 -0
  59. data/test/acts_as_authentic_test/magic_columns_test.rb +27 -0
  60. data/test/acts_as_authentic_test/password_test.rb +212 -0
  61. data/test/acts_as_authentic_test/perishable_token_test.rb +56 -0
  62. data/test/acts_as_authentic_test/persistence_token_test.rb +55 -0
  63. data/test/acts_as_authentic_test/session_maintenance_test.rb +68 -0
  64. data/test/acts_as_authentic_test/single_access_test.rb +39 -0
  65. data/test/authenticates_many_test.rb +16 -0
  66. data/test/{crypto_provider_tests → crypto_provider_test}/aes256_test.rb +1 -1
  67. data/test/{crypto_provider_tests → crypto_provider_test}/bcrypt_test.rb +1 -1
  68. data/test/{crypto_provider_tests → crypto_provider_test}/sha1_test.rb +1 -1
  69. data/test/{crypto_provider_tests → crypto_provider_test}/sha512_test.rb +1 -1
  70. data/test/fixtures/employees.yml +4 -4
  71. data/test/fixtures/users.yml +6 -6
  72. data/test/libs/company.rb +6 -0
  73. data/test/libs/employee.rb +7 -0
  74. data/test/libs/employee_session.rb +2 -0
  75. data/test/libs/project.rb +3 -0
  76. data/test/libs/user_session.rb +2 -0
  77. data/test/random_test.rb +49 -0
  78. data/test/session_test/activation_test.rb +43 -0
  79. data/test/session_test/active_record_trickery_test.rb +26 -0
  80. data/test/session_test/brute_force_protection_test.rb +76 -0
  81. data/test/session_test/callbacks_test.rb +6 -0
  82. data/test/session_test/cookies_test.rb +107 -0
  83. data/test/session_test/credentials_test.rb +0 -0
  84. data/test/session_test/existence_test.rb +64 -0
  85. data/test/session_test/http_auth_test.rb +16 -0
  86. data/test/session_test/id_test.rb +17 -0
  87. data/test/session_test/klass_test.rb +35 -0
  88. data/test/session_test/magic_columns_test.rb +59 -0
  89. data/test/session_test/magic_states_test.rb +60 -0
  90. data/test/session_test/params_test.rb +53 -0
  91. data/test/session_test/password_test.rb +84 -0
  92. data/test/{session_tests → session_test}/perishability_test.rb +1 -1
  93. data/test/session_test/persistence_test.rb +21 -0
  94. data/test/{session_tests → session_test}/scopes_test.rb +2 -3
  95. data/test/session_test/session_test.rb +59 -0
  96. data/test/session_test/timeout_test.rb +43 -0
  97. data/test/session_test/unauthorized_record_test.rb +13 -0
  98. data/test/session_test/validation_test.rb +23 -0
  99. data/test/test_helper.rb +14 -29
  100. metadata +120 -112
  101. data/Manifest +0 -76
  102. data/authlogic.gemspec +0 -38
  103. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/base.rb +0 -22
  104. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/config.rb +0 -238
  105. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/credentials.rb +0 -155
  106. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/logged_in.rb +0 -51
  107. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/perishability.rb +0 -71
  108. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/persistence.rb +0 -94
  109. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/session_maintenance.rb +0 -87
  110. data/lib/authlogic/orm_adapters/active_record_adapter/acts_as_authentic/single_access.rb +0 -61
  111. data/lib/authlogic/orm_adapters/active_record_adapter/authenticates_many.rb +0 -58
  112. data/lib/authlogic/session/config.rb +0 -421
  113. data/lib/authlogic/session/errors.rb +0 -18
  114. data/lib/authlogic/session/record_info.rb +0 -24
  115. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/config_test.rb +0 -154
  116. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/credentials_test.rb +0 -157
  117. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/logged_in_test.rb +0 -24
  118. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/perishability_test.rb +0 -41
  119. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/persistence_test.rb +0 -54
  120. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/session_maintenance_test.rb +0 -62
  121. data/test/orm_adapters_tests/active_record_adapter_tests/acts_as_authentic_tests/single_access_test.rb +0 -41
  122. data/test/orm_adapters_tests/active_record_adapter_tests/authenticates_many_test.rb +0 -32
  123. data/test/session_tests/active_record_trickery_test.rb +0 -14
  124. data/test/session_tests/authenticates_many_association_test.rb +0 -28
  125. data/test/session_tests/base_test.rb +0 -307
  126. data/test/session_tests/brute_force_protection_test.rb +0 -53
  127. data/test/session_tests/config_test.rb +0 -184
  128. data/test/session_tests/cookies_test.rb +0 -32
  129. data/test/session_tests/params_test.rb +0 -32
  130. data/test/session_tests/session_test.rb +0 -45
  131. data/test/session_tests/timeout_test.rb +0 -71
@@ -1,51 +0,0 @@
1
- module Authlogic
2
- module ORMAdapters
3
- module ActiveRecordAdapter
4
- module ActsAsAuthentic
5
- # = Logged In
6
- #
7
- # Handles all logic determining if a record is logged in or not. This uses the "last_request_at" field, if this field is not present none of this will be available.
8
- #
9
- # === Named Scopes
10
- #
11
- # * <tt>logged_in</tt> - returns all records that have a last_request_at value that is > your :logged_in_timeout.ago
12
- # * <tt>logged_out</tt> - same as logged in but returns users that are logged out, be careful with using this, this can return a lot of users
13
- #
14
- # === Instance Methods
15
- #
16
- # * <tt>logged_in?</tt> - same as the logged_in named scope, but returns true if the record is logged in
17
- # * <tt>logged_out?</tt> - opposite of logged_in?
18
- module LoggedIn
19
- def acts_as_authentic_with_logged_in(options = {})
20
- acts_as_authentic_without_logged_in(options)
21
-
22
- validates_numericality_of :login_count, :only_integer => :true, :greater_than_or_equal_to => 0, :allow_nil => true if column_names.include?("login_count")
23
-
24
- if column_names.include?("last_request_at")
25
- class_eval <<-"end_eval", __FILE__, __LINE__
26
- named_scope :logged_in, lambda { {:conditions => ["last_request_at > ?", #{options[:logged_in_timeout]}.seconds.ago]} }
27
- named_scope :logged_out, lambda { {:conditions => ["last_request_at is NULL or last_request_at <= ?", #{options[:logged_in_timeout]}.seconds.ago]} }
28
-
29
- def logged_in?
30
- raise "Can not determine the records login state because there is no last_request_at column" if !respond_to?(:last_request_at)
31
- !last_request_at.nil? && last_request_at > #{options[:logged_in_timeout]}.seconds.ago
32
- end
33
-
34
- def logged_out?
35
- !logged_in?
36
- end
37
- end_eval
38
- end
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
45
-
46
- ActiveRecord::Base.class_eval do
47
- class << self
48
- include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::LoggedIn
49
- alias_method_chain :acts_as_authentic, :logged_in
50
- end
51
- end
@@ -1,71 +0,0 @@
1
- module Authlogic
2
- module ORMAdapters
3
- module ActiveRecordAdapter
4
- module ActsAsAuthentic
5
- # = Perishable
6
- #
7
- # Handles all logic the deals with maintaining the perishable token. This token should be used to authenticate a user that is not logged in so that they
8
- # can change their password, confirm their account, etc. Use it for whatever you want, but keep in mind this token is only temporary. Which
9
- # is perfect for emailing, etc.
10
- #
11
- # === Class Methods
12
- #
13
- # * <tt>find_using_{options[:perishable_token_field]}(token, age = {options[:perishable_token_valid_for]})</tt> - returns the record that matches the pased token. The record's updated at column must not be older than
14
- # {age} ago. Lastly, if a blank token is passed no record will be returned.
15
- #
16
- # === Instance Methods
17
- #
18
- # * <tt>reset_#{options[:perishable_token_field]}</tt> - resets the perishable token field to a friendly unique token.
19
- # * <tt>reset_#{options[:perishable_token_field]}!</tt> - same as above but saves the record afterwards.
20
- module Perishability
21
- def acts_as_authentic_with_perishability(options = {})
22
- acts_as_authentic_without_perishability(options)
23
-
24
- return if options[:perishable_token_field].blank?
25
-
26
- class_eval <<-"end_eval", __FILE__, __LINE__
27
- validates_uniqueness_of :#{options[:perishable_token_field]}, :if => :#{options[:perishable_token_field]}_changed?
28
-
29
- before_validation :reset_#{options[:perishable_token_field]}, :unless => :disable_#{options[:perishable_token_field]}_maintenance?
30
-
31
- def self.find_using_#{options[:perishable_token_field]}(token, age = #{options[:perishable_token_valid_for]})
32
- return if token.blank?
33
- age = age.to_i
34
-
35
- conditions_sql = "#{options[:perishable_token_field]} = ?"
36
- conditions_subs = [token]
37
-
38
- if column_names.include?("updated_at") && age > 0
39
- conditions_sql += " and updated_at > ?"
40
- conditions_subs << age.seconds.ago
41
- end
42
-
43
- find(:first, :conditions => [conditions_sql, *conditions_subs])
44
- end
45
-
46
- def reset_#{options[:perishable_token_field]}
47
- self.#{options[:perishable_token_field]} = self.class.friendly_unique_token
48
- end
49
-
50
- def reset_#{options[:perishable_token_field]}!
51
- reset_#{options[:perishable_token_field]}
52
- save_without_session_maintenance(false)
53
- end
54
-
55
- def disable_#{options[:perishable_token_field]}_maintenance?
56
- #{options[:disable_perishable_token_maintenance].inspect} == true
57
- end
58
- end_eval
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
65
-
66
- ActiveRecord::Base.class_eval do
67
- class << self
68
- include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::Perishability
69
- alias_method_chain :acts_as_authentic, :perishability
70
- end
71
- end
@@ -1,94 +0,0 @@
1
- module Authlogic
2
- module ORMAdapters
3
- module ActiveRecordAdapter
4
- module ActsAsAuthentic
5
- # = Persistence
6
- #
7
- # This is responsible for all record persistence. Basically what your Authlogic session needs to persist the record's session.
8
- #
9
- # === Class Methods
10
- #
11
- # * <tt>forget_all!</tt> - resets ALL records persistence_token to a unique value, requiring all users to re-login
12
- # * <tt>unique_token</tt> - returns a pretty hardcore random token that is finally encrypted with a hash algorithm
13
- #
14
- # === Instance Methods
15
- #
16
- # * <tt>forget!</tt> - resets the record's persistence_token which requires them to re-login
17
- #
18
- # === Alias Method Chains
19
- #
20
- # * <tt>#{options[:password_field]}</tt> - adds in functionality to reset the persistence token when the password is changed
21
- module Persistence
22
- def acts_as_authentic_with_persistence(options = {})
23
- acts_as_authentic_without_persistence(options)
24
-
25
- validates_presence_of options[:persistence_token_field]
26
- validates_uniqueness_of options[:persistence_token_field], :if => "#{options[:persistence_token_field]}_changed?".to_sym
27
-
28
- before_validation "reset_#{options[:persistence_token_field]}".to_sym, :if => "reset_#{options[:persistence_token_field]}?".to_sym
29
-
30
- def forget_all!
31
- # Paginate these to save on memory
32
- records = nil
33
- i = 0
34
- begin
35
- records = find(:all, :limit => 50, :offset => i)
36
- records.each { |record| record.forget! }
37
- i += 50
38
- end while !records.blank?
39
- end
40
-
41
- class_eval <<-"end_eval", __FILE__, __LINE__
42
- def self.unique_token
43
- Authlogic::CryptoProviders::Sha512.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
44
- end
45
-
46
- def forget!
47
- self.#{options[:persistence_token_field]} = self.class.unique_token
48
- save_without_session_maintenance(false)
49
- end
50
-
51
- def #{options[:password_field]}_with_persistence=(value)
52
- reset_#{options[:persistence_token_field]} unless value.blank?
53
- self.#{options[:password_field]}_without_persistence = value
54
- end
55
- alias_method_chain :#{options[:password_field]}=, :persistence
56
-
57
- def reset_#{options[:persistence_token_field]}
58
- self.#{options[:persistence_token_field]} = self.class.unique_token
59
- end
60
-
61
- def reset_#{options[:persistence_token_field]}!
62
- reset_#{options[:persistence_token_field]}
63
- save_without_session_maintenance(false)
64
- end
65
-
66
- def reset_#{options[:persistence_token_field]}?
67
- #{options[:persistence_token_field]}.blank?
68
- end
69
-
70
- # When a user logs in we need to ensure they have a persistence token. Think about apps that are transitioning and
71
- # never have a persistence token to begin with. When their users log in their persistence token needs to be set.
72
- # The only other time persistence tokens are reset is in a before_validation on the user, and when a user is saved
73
- # from the session we skip validation for performance reasons. We do save_without_session_maintenance(false), the false
74
- # indicates to skip validation.
75
- def valid_#{options[:password_field]}_with_persistence?(attempted_password)
76
- result = valid_password_without_persistence?(attempted_password)
77
- reset_#{options[:persistence_token_field]}! if result && #{options[:persistence_token_field]}.blank?
78
- result
79
- end
80
- alias_method_chain :valid_#{options[:password_field]}?, :persistence
81
- end_eval
82
- end
83
- end
84
- end
85
- end
86
- end
87
- end
88
-
89
- ActiveRecord::Base.class_eval do
90
- class << self
91
- include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::Persistence
92
- alias_method_chain :acts_as_authentic, :persistence
93
- end
94
- end
@@ -1,87 +0,0 @@
1
- module Authlogic
2
- module ORMAdapters
3
- module ActiveRecordAdapter
4
- module ActsAsAuthentic
5
- # = Session Maintenance
6
- #
7
- # Responsible for maintaining the related session as the record changes. Here is what it does:
8
- #
9
- # 1. If the user is logged out and creates a new record, they will be logged in as that record
10
- # 2. If the user is logged out and changes a record's password, they will be logged in as that record
11
- # 3. If a user is logged in and changes his own password, their session will be updated accordingly. This can be done *anywhere*: the my account section, admin area, etc.
12
- #
13
- # === Instance Methods
14
- #
15
- # * <tt>save_without_session_maintenance</tt> - allows you to save the record and skip all of the session maintenance completely
16
- module SessionMaintenance
17
- def acts_as_authentic_with_session_maintenance(options = {})
18
- acts_as_authentic_without_session_maintenance(options)
19
-
20
- before_save :get_session_information, :if => :update_sessions?
21
- after_save :maintain_sessions!, :if => :update_sessions?
22
-
23
- class_eval <<-"end_eval", __FILE__, __LINE__
24
- def save_without_session_maintenance(*args)
25
- @skip_session_maintenance = true
26
- result = save(*args)
27
- @skip_session_maintenance = false
28
- result
29
- end
30
-
31
- protected
32
- def update_sessions?
33
- !@skip_session_maintenance && #{options[:session_class]}.activated? && !#{options[:session_ids].inspect}.blank? && #{options[:persistence_token_field]}_changed?
34
- end
35
-
36
- def get_session_information
37
- # Need to determine if we are completely logged out, or logged in as another user
38
- @_sessions = []
39
- @_logged_out = true
40
-
41
- #{options[:session_ids].inspect}.each do |session_id|
42
- session = #{options[:session_class]}.find(session_id, self)
43
- if session && !session.record.blank?
44
- @_logged_out = false
45
- @_sessions << session if session.record == self
46
- end
47
- end
48
- end
49
-
50
- def maintain_sessions!
51
- if @_logged_out
52
- create_session!
53
- elsif !@_sessions.blank?
54
- update_sessions!
55
- end
56
- end
57
-
58
- def create_session!
59
- # We only want to automatically login into the first session, since this is the main session. The other sessions are sessions
60
- # that need to be created after logging into the main session.
61
- session_id = #{options[:session_ids].inspect}.first
62
-
63
- # Log me in, only if we aren't already logged in
64
- #{options[:session_class]}.create(*[self, session_id].compact) if !#{options[:session_class]}.find(session_id, self)
65
- end
66
-
67
- def update_sessions!
68
- # We found sessions above, let's update them with the new info
69
- @_sessions.each do |stale_session|
70
- stale_session.unauthorized_record = self
71
- stale_session.save
72
- end
73
- end
74
- end_eval
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end
81
-
82
- ActiveRecord::Base.class_eval do
83
- class << self
84
- include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::SessionMaintenance
85
- alias_method_chain :acts_as_authentic, :session_maintenance
86
- end
87
- end
@@ -1,61 +0,0 @@
1
- module Authlogic
2
- module ORMAdapters
3
- module ActiveRecordAdapter
4
- module ActsAsAuthentic
5
- # = Single Access
6
- #
7
- # Instead of repeating myself here, checkout the README. There is a "Tokens" section in there that goes over the single access token.
8
- # Keep in mind none of this will be applied if there is not a single_access_token field supplied in the database.
9
- #
10
- # === Instance Methods
11
- #
12
- # * <tt>reset_{options[:single_access_token_field]}</tt> - resets the single access token with the friendly_unique_token
13
- # * <tt>reset_{options[:single_access_token_field]}!</tt> - same as above, but saves the record afterwards
14
- #
15
- # === Alias Method Chains
16
- #
17
- # * <tt>{options[:password_field]}</tt> - if the :change_single_access_token_with_password is set to true, reset_{options[:single_access_token_field]} will be called when the password changes
18
- module SingleAccess
19
- def acts_as_authentic_with_single_access(options = {})
20
- acts_as_authentic_without_single_access(options)
21
-
22
- return if options[:single_access_token_field].blank?
23
-
24
- class_eval <<-"end_eval", __FILE__, __LINE__
25
- validates_uniqueness_of :#{options[:single_access_token_field]}, :if => :#{options[:single_access_token_field]}_changed?
26
-
27
- before_validation :set_#{options[:single_access_token_field]}_field
28
-
29
- def password_with_single_access=(value)
30
- reset_#{options[:single_access_token_field]} if #{options[:change_single_access_token_with_password].inspect}
31
- self.password_without_single_access = value
32
- end
33
- alias_method_chain :password=, :single_access
34
-
35
- def reset_#{options[:single_access_token_field]}
36
- self.#{options[:single_access_token_field]} = self.class.friendly_unique_token
37
- end
38
-
39
- def reset_#{options[:single_access_token_field]}!
40
- reset_#{options[:single_access_token_field]}
41
- save_without_session_maintenance
42
- end
43
-
44
- protected
45
- def set_#{options[:single_access_token_field]}_field
46
- reset_#{options[:single_access_token_field]} if #{options[:single_access_token_field]}.blank?
47
- end
48
- end_eval
49
- end
50
- end
51
- end
52
- end
53
- end
54
- end
55
-
56
- ActiveRecord::Base.class_eval do
57
- class << self
58
- include Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::SingleAccess
59
- alias_method_chain :acts_as_authentic, :single_access
60
- end
61
- end
@@ -1,58 +0,0 @@
1
- module Authlogic
2
- module ORMAdapters
3
- module ActiveRecordAdapter
4
- # = Authenticates Many
5
- #
6
- # This allows you to scope your authentication. For example, let's say all users belong to an account, you want to make sure only users
7
- # that belong to that account can actually login into that account. Simple, just do:
8
- #
9
- # class Account < ActiveRecord::Base
10
- # authenticates_many :user_sessions
11
- # end
12
- #
13
- # Now you can scope sessions just like everything else in ActiveRecord:
14
- #
15
- # @account.user_sessions.new(*args)
16
- # @account.user_sessions.create(*args)
17
- # @account.user_sessions.find(*args)
18
- # # ... etc
19
- #
20
- # For more information on scopes check out the scopes section in the README.
21
- module AuthenticatesMany
22
- # Allows you set essentially set up a relationship with your sessions. See module definition above for more details.
23
- #
24
- # === Options
25
- #
26
- # * <tt>session_class:</tt> default: "#{name}Session",
27
- # This is the related session class.
28
- #
29
- # * <tt>relationship_name:</tt> default: options[:session_class].klass_name.underscore.pluralize,
30
- # This is the name of the relationship you want to use to scope everything. For example an Account has many Users. There should be a relationship
31
- # called :users that you defined with a has_many. The reason we use the relationship is so you don't have to repeat yourself. The relatonship
32
- # could have all kinds of custom options. So instead of repeating yourself we essentially use the scope that the relationship creates.
33
- #
34
- # * <tt>find_options:</tt> default: nil,
35
- # By default the find options are created from the relationship you specify with :relationship_name. But if you want to override this and
36
- # manually specify find_options you can do it here. Specify options just as you would in ActiveRecord::Base.find.
37
- #
38
- # * <tt>scope_cookies:</tt> default: false
39
- # By the nature of cookies they scope theirself if you are using subdomains to access accounts. If you aren't using subdomains you need to have
40
- # separate cookies for each account, assuming a user is logging into mroe than one account. Authlogic can take care of this for you by
41
- # prefixing the name of the cookie and sessin with the model id. You just need to tell Authlogic to do this by passing this option.
42
- def authenticates_many(name, options = {})
43
- options[:session_class] ||= name.to_s.classify.constantize
44
- options[:relationship_name] ||= options[:session_class].klass_name.underscore.pluralize
45
- class_eval <<-"end_eval", __FILE__, __LINE__
46
- def #{name}
47
- find_options = #{options[:find_options].inspect} || #{options[:relationship_name]}.scope(:find)
48
- find_options.delete_if { |key, value| ![:conditions, :include, :joins].include?(key.to_sym) || value.nil? }
49
- @#{name} ||= Authlogic::Session::AuthenticatesManyAssociation.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
50
- end
51
- end_eval
52
- end
53
- end
54
- end
55
- end
56
- end
57
-
58
- ActiveRecord::Base.extend Authlogic::ORMAdapters::ActiveRecordAdapter::AuthenticatesMany
@@ -1,421 +0,0 @@
1
- module Authlogic
2
- module Session
3
- module Config # :nodoc:
4
- def self.included(klass)
5
- klass.extend(ClassMethods)
6
- klass.send(:include, InstanceMethods)
7
- end
8
-
9
- # = Session Config
10
- #
11
- # This deals with configuration for your session. If you are wanting to configure your model please look at Authlogic::ORMAdapters::ActiveRecordAdapter::ActsAsAuthentic::Config
12
- #
13
- # Configuration for your session is simple. The configuration options are just class methods. Just put this in your config/initializers directory
14
- #
15
- # UserSession.configure do |config|
16
- # config.authenticate_with = User
17
- # # ... more configuration
18
- # end
19
- #
20
- # or you can set your configuration in the session class directly:
21
- #
22
- # class UserSession < Authlogic::Session::Base
23
- # authenticate_with User
24
- # # ... more configuration
25
- # end
26
- #
27
- # You can also access the values in the same fashion:
28
- #
29
- # UserSession.authenticate_with
30
- #
31
- # See the methods belows for all configuration options.
32
- module ClassMethods
33
- # Lets you change which model to use for authentication.
34
- #
35
- # * <tt>Default:</tt> inferred from the class name. UserSession would automatically try User
36
- # * <tt>Accepts:</tt> an ActiveRecord class
37
- def authenticate_with(klass)
38
- @klass_name = klass.name
39
- @klass = klass
40
- end
41
- alias_method :authenticate_with=, :authenticate_with
42
-
43
- # Convenience method that lets you easily set configuration, see examples above
44
- def configure
45
- yield self
46
- end
47
-
48
- # The name of the cookie or the key in the cookies hash. Be sure and use a unique name. If you have multiple sessions and they use the same cookie it will cause problems.
49
- # Also, if a id is set it will be inserted into the beginning of the string. Exmaple:
50
- #
51
- # session = UserSession.new
52
- # session.cookie_key => "user_credentials"
53
- #
54
- # session = UserSession.new(:super_high_secret)
55
- # session.cookie_key => "super_high_secret_user_credentials"
56
- #
57
- # * <tt>Default:</tt> "#{klass_name.underscore}_credentials"
58
- # * <tt>Accepts:</tt> String
59
- def cookie_key(value = nil)
60
- if value.nil?
61
- read_inheritable_attribute(:cookie_key) || cookie_key("#{klass_name.underscore}_credentials")
62
- else
63
- write_inheritable_attribute(:cookie_key, value)
64
- end
65
- end
66
- alias_method :cookie_key=, :cookie_key
67
-
68
- # Set this to true if you want to disable the checking of active?, approved?, and confirmed? on your record. This is more or less of a
69
- # convenience feature, since 99% of the time if those methods exist and return false you will not want the user logging in. You could
70
- # easily accomplish this same thing with a before_validation method or other callbacks.
71
- #
72
- # * <tt>Default:</tt> false
73
- # * <tt>Accepts:</tt> Boolean
74
- def disable_magic_states(value = nil)
75
- if value.nil?
76
- read_inheritable_attribute(:disable_magic_states)
77
- else
78
- write_inheritable_attribute(:disable_magic_states, value)
79
- end
80
- end
81
- alias_method :disable_magic_states=, :disable_magic_states
82
-
83
- # Authlogic tries to validate the credentials passed to it. One part of validation is actually finding the user and making sure it exists. What method it uses the do this is up to you.
84
- #
85
- # Let's say you have a UserSession that is authenticating a User. By default UserSession will call User.find_by_login(login). You can change what method UserSession calls by specifying it here. Then
86
- # in your User model you can make that method do anything you want, giving you complete control of how users are found by the UserSession.
87
- #
88
- # 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 that does this in the User model. Let's call it "find_by_username_or_email"
89
- #
90
- # class User < ActiveRecord::Base
91
- # def self.find_by_username_or_email(login)
92
- # find_by_username(login) || find_by_email(login)
93
- # end
94
- # end
95
- #
96
- # * <tt>Default:</tt> "find_by_#{login_field}"
97
- # * <tt>Accepts:</tt> Symbol or String
98
- def find_by_login_method(value = nil)
99
- if value.nil?
100
- read_inheritable_attribute(:find_by_login_method) || find_by_login_method("find_by_#{login_field}")
101
- else
102
- write_inheritable_attribute(:find_by_login_method, value)
103
- end
104
- end
105
- alias_method :find_by_login_method=, :find_by_login_method
106
-
107
- # Calling UserSession.find tries to find the user session by session, then cookie, then params, and finally by basic http auth.
108
- # This option allows you to change the order or remove any of these.
109
- #
110
- # * <tt>Default:</tt> [:params, :session, :cookie, :http_auth]
111
- # * <tt>Accepts:</tt> Array, and can only use any of the 3 options above
112
- def find_with(*values)
113
- if values.blank?
114
- read_inheritable_attribute(:find_with) || find_with(:params, :session, :cookie, :http_auth)
115
- else
116
- values.flatten!
117
- write_inheritable_attribute(:find_with, values)
118
- end
119
- end
120
- alias_method :find_with=, :find_with
121
-
122
- # Every time a session is found the last_request_at field for that record is updatd with the current time, if that field exists. If you want to limit how frequent that field is updated specify the threshold
123
- # here. For example, if your user is making a request every 5 seconds, and you feel this is too frequent, and feel a minute is a good threashold. Set this to 1.minute. Once a minute has passed in between
124
- # requests the field will be updated.
125
- #
126
- # * <tt>Default:</tt> 0
127
- # * <tt>Accepts:</tt> integer representing time in seconds
128
- def last_request_at_threshold(value = nil)
129
- if value.nil?
130
- read_inheritable_attribute(:last_request_at_threshold) || last_request_at_threshold(0)
131
- else
132
- write_inheritable_attribute(:last_request_at_threshold, value)
133
- end
134
- end
135
- alias_method :last_request_at_threshold=, :last_request_at_threshold
136
-
137
- def login_blank_message(value = nil) # :nodoc:
138
- new_i18n_error
139
- end
140
- alias_method :login_blank_message=, :login_blank_message
141
-
142
- def login_not_found_message(value = nil) # :nodoc:
143
- new_i18n_error
144
- end
145
- alias_method :login_not_found_message=, :login_not_found_message
146
-
147
- # The name of the method you want Authlogic to create for storing the login / username. Keep in mind this is just for your
148
- # Authlogic::Session, if you want it can be something completely different than the field in your model. So if you wanted people to
149
- # login with a field called "login" and then find users by email this is compeltely doable. See the find_by_login_method configuration
150
- # option for more details.
151
- #
152
- # * <tt>Default:</tt> Uses the configuration option in your model: User.acts_as_authentic_config[:login_field]
153
- # * <tt>Accepts:</tt> Symbol or String
154
- def login_field(value = nil)
155
- if value.nil?
156
- read_inheritable_attribute(:login_field) || login_field(klass.acts_as_authentic_config[:login_field])
157
- else
158
- write_inheritable_attribute(:login_field, value)
159
- end
160
- end
161
- alias_method :login_field=, :login_field
162
-
163
- # With acts_as_authentic you get a :logged_in_timeout configuration option. If this is set, after this amount of time has passed the user
164
- # will be marked as logged out. Obviously, since web based apps are on a per request basis, we have to define a time limit threshold that
165
- # determines when we consider a user to be "logged out". Meaning, if they login and then leave the website, when do mark them as logged out?
166
- # I recommend just using this as a fun feature on your website or reports, giving you a ballpark number of users logged in and active. This is
167
- # not meant to be a dead accurate representation of a users logged in state, since there is really no real way to do this with web based apps.
168
- # Think about a user that logs in and doesn't log out. There is no action that tells you that the user isn't technically still logged in and
169
- # active.
170
- #
171
- # That being said, you can use that feature to require a new login if their session timesout. Similar to how financial sites work. Just set this option to
172
- # true and if your record returns true for stale? then they will be required to log back in.
173
- #
174
- # Lastly, UserSession.find will still return a object is the session is stale, but you will not get a record. This allows you to determine if the
175
- # user needs to log back in because their session went stale, or because they just aren't logged in. Just call current_user_session.stale? as your flag.
176
- #
177
- # * <tt>Default:</tt> false
178
- # * <tt>Accepts:</tt> Boolean
179
- def logout_on_timeout(value = nil)
180
- if value.nil?
181
- read_inheritable_attribute(:logout_on_timeout) || logout_on_timeout(false)
182
- else
183
- write_inheritable_attribute(:logout_on_timeout, value)
184
- end
185
- end
186
- alias_method :logout_on_timeout=, :logout_on_timeout
187
-
188
- # To help protect from brute force attacks you can set a limit on the allowed number of consecutive failed logins. By default this is 50, this is a very liberal
189
- # number, and if someone fails to login after 50 tries it should be pretty obvious that it's a machine trying to login in and very likely a brute force attack.
190
- #
191
- # In order to enable this field your model MUST have a failed_login_count (integer) field.
192
- #
193
- # If you don't know what a brute force attack is, it's when a machine tries to login into a system using every combination of character possible. Thus resulting
194
- # in possibly millions of attempts to log into an account.
195
- #
196
- # * <tt>Default:</tt> 50
197
- # * <tt>Accepts:</tt> Integer, set to 0 to disable
198
- def consecutive_failed_logins_limit(value = nil)
199
- if value.nil?
200
- read_inheritable_attribute(:consecutive_failed_logins_limit) || consecutive_failed_logins_limit(50)
201
- else
202
- write_inheritable_attribute(:consecutive_failed_logins_limit, value)
203
- end
204
- end
205
- alias_method :consecutive_failed_logins_limit=, :consecutive_failed_logins_limit
206
-
207
- def not_active_message(value = nil) # :nodoc:
208
- new_i18n_error
209
- end
210
- alias_method :not_active_message=, :not_active_message
211
-
212
- def not_approved_message(value = nil) # :nodoc:
213
- new_i18n_error
214
- end
215
- alias_method :not_approved_message=, :not_approved_message
216
-
217
- def not_confirmed_message(value = nil) # :nodoc:
218
- new_i18n_error
219
- end
220
- alias_method :not_confirmed_message=, :not_confirmed_message
221
-
222
- # Works exactly like cookie_key, but for params. So a user can login via params just like a cookie or a session. Your URL would look like:
223
- #
224
- # http://www.domain.com?user_credentials=my_single_access_key
225
- #
226
- # You can change the "user_credentials" key above with this configuration option. Keep in mind, just like cookie_key, if you supply an id
227
- # the id will be appended to the front. Check out cookie_key for more details. Also checkout the "Single Access / Private Feeds Access" section in the README.
228
- #
229
- # * <tt>Default:</tt> cookie_key
230
- # * <tt>Accepts:</tt> String
231
- def params_key(value = nil)
232
- if value.nil?
233
- read_inheritable_attribute(:params_key) || params_key(cookie_key)
234
- else
235
- write_inheritable_attribute(:params_key, value)
236
- end
237
- end
238
- alias_method :params_key=, :params_key
239
-
240
- def password_blank_message(value = nil) # :nodoc:
241
- new_i18n_error
242
- end
243
- alias_method :password_blank_message=, :password_blank_message
244
-
245
- # Works exactly like login_field, but for the password instead.
246
- #
247
- # * <tt>Default:</tt> :password
248
- # * <tt>Accepts:</tt> Symbol or String
249
- def password_field(value = nil)
250
- if value.nil?
251
- read_inheritable_attribute(:password_field) || password_field(:password)
252
- else
253
- write_inheritable_attribute(:password_field, value)
254
- end
255
- end
256
- alias_method :password_field=, :password_field
257
-
258
- def password_invalid_message(value = nil) # :nodoc:
259
- new_i18n_error
260
- end
261
- alias_method :password_invalid_message=, :password_invalid_message
262
-
263
- # If sessions should be remembered by default or not.
264
- #
265
- # * <tt>Default:</tt> false
266
- # * <tt>Accepts:</tt> Boolean
267
- def remember_me(value = nil)
268
- if value.nil?
269
- read_inheritable_attribute(:remember_me)
270
- else
271
- write_inheritable_attribute(:remember_me, value)
272
- end
273
- end
274
- alias_method :remember_me=, :remember_me
275
-
276
- # The length of time until the cookie expires.
277
- #
278
- # * <tt>Default:</tt> 3.months
279
- # * <tt>Accepts:</tt> Integer, length of time in seconds, such as 60 or 3.months
280
- def remember_me_for(value = :_read)
281
- if value == :_read
282
- read_inheritable_attribute(:remember_me_for) || remember_me_for(3.months)
283
- else
284
- write_inheritable_attribute(:remember_me_for, value)
285
- end
286
- end
287
- alias_method :remember_me_for=, :remember_me_for
288
-
289
- # Works exactly like cookie_key, but for sessions. See cookie_key for more info.
290
- #
291
- # * <tt>Default:</tt> cookie_key
292
- # * <tt>Accepts:</tt> Symbol or String
293
- def session_key(value = nil)
294
- if value.nil?
295
- read_inheritable_attribute(:session_key) || session_key(cookie_key)
296
- else
297
- write_inheritable_attribute(:session_key, value)
298
- end
299
- end
300
- alias_method :session_key=, :session_key
301
-
302
- # Authentication is allowed via a single access token, but maybe this is something you don't want for your application as a whole. Maybe this is something you only want for specific request types.
303
- # Specify a list of allowed request types and single access authentication will only be allowed for the ones you specify. Checkout the "Single Access / Private Feeds Access" section in the README.
304
- #
305
- # * <tt>Default:</tt> "application/rss+xml", "application/atom+xml"
306
- # * <tt>Accepts:</tt> String of request type, or :all to allow single access authentication for any and all request types
307
- def single_access_allowed_request_types(*values)
308
- if values.blank?
309
- read_inheritable_attribute(:single_access_allowed_request_types) || single_access_allowed_request_types("application/rss+xml", "application/atom+xml")
310
- else
311
- write_inheritable_attribute(:single_access_allowed_request_types, values)
312
- end
313
- end
314
- alias_method :single_access_allowed_request_types=, :single_access_allowed_request_types
315
-
316
- # The name of the method in your model used to verify the password. This should be an instance method. It should also be prepared to accept a raw password and a crytped password.
317
- #
318
- # * <tt>Default:</tt> "valid_#{password_field}?"
319
- # * <tt>Accepts:</tt> Symbol or String
320
- def verify_password_method(value = nil)
321
- if value.nil?
322
- read_inheritable_attribute(:verify_password_method) || verify_password_method("valid_#{password_field}?")
323
- else
324
- write_inheritable_attribute(:verify_password_method, value)
325
- end
326
- end
327
- alias_method :verify_password_method=, :verify_password_method
328
-
329
- private
330
- def new_i18n_error
331
- raise NotImplementedError.new("As of v 1.4.0 Authlogic implements a new I18n solution that is much cleaner and easier. Please see Authlogic::I18n for more information on how to provide internationalization in Authlogic.")
332
- end
333
- end
334
-
335
- module InstanceMethods # :nodoc:
336
- def change_single_access_token_with_password?
337
- self.class.change_single_access_token_with_password == true
338
- end
339
-
340
- def consecutive_failed_logins_limit
341
- self.class.consecutive_failed_logins_limit
342
- end
343
-
344
- def cookie_key
345
- build_key(self.class.cookie_key)
346
- end
347
-
348
- def disable_magic_states?
349
- self.class.disable_magic_states == true
350
- end
351
-
352
- def find_by_login_method
353
- self.class.find_by_login_method
354
- end
355
-
356
- def find_with
357
- self.class.find_with
358
- end
359
-
360
- def last_request_at_threshold
361
- self.class.last_request_at_threshold
362
- end
363
-
364
- def login_field
365
- self.class.login_field
366
- end
367
-
368
- def logout_on_timeout?
369
- self.class.logout_on_timeout == true
370
- end
371
-
372
- def params_allowed_request_types
373
- build_key(self.class.params_allowed_request_types)
374
- end
375
-
376
- def params_key
377
- build_key(self.class.params_key)
378
- end
379
-
380
- def password_field
381
- self.class.password_field
382
- end
383
-
384
- def perishable_token_field
385
- klass.acts_as_authentic_config[:perishable_token_field]
386
- end
387
-
388
- def remember_me_for
389
- return unless remember_me?
390
- self.class.remember_me_for
391
- end
392
-
393
- def persistence_token_field
394
- klass.acts_as_authentic_config[:persistence_token_field]
395
- end
396
-
397
- def session_key
398
- build_key(self.class.session_key)
399
- end
400
-
401
- def single_access_token_field
402
- klass.acts_as_authentic_config[:single_access_token_field]
403
- end
404
-
405
- def single_access_allowed_request_types
406
- self.class.single_access_allowed_request_types
407
- end
408
-
409
- def verify_password_method
410
- self.class.verify_password_method
411
- end
412
-
413
- private
414
- def build_key(last_part)
415
- key_parts = [id, scope[:id], last_part].compact
416
- key_parts.join("_")
417
- end
418
- end
419
- end
420
- end
421
- end