authlogic 0.10.4

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 (102) hide show
  1. data/CHANGELOG.rdoc +47 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Manifest +100 -0
  4. data/README.rdoc +292 -0
  5. data/Rakefile +15 -0
  6. data/authlogic.gemspec +38 -0
  7. data/init.rb +1 -0
  8. data/lib/authlogic.rb +25 -0
  9. data/lib/authlogic/active_record/acts_as_authentic.rb +265 -0
  10. data/lib/authlogic/active_record/authenticates_many.rb +19 -0
  11. data/lib/authlogic/active_record/scoped_session.rb +28 -0
  12. data/lib/authlogic/controller_adapters/abstract_adapter.rb +25 -0
  13. data/lib/authlogic/controller_adapters/rails_adapter.rb +39 -0
  14. data/lib/authlogic/session/active_record_trickery.rb +26 -0
  15. data/lib/authlogic/session/base.rb +510 -0
  16. data/lib/authlogic/session/callbacks.rb +56 -0
  17. data/lib/authlogic/session/config.rb +237 -0
  18. data/lib/authlogic/session/errors.rb +18 -0
  19. data/lib/authlogic/sha512_crypto_provider.rb +18 -0
  20. data/lib/authlogic/version.rb +56 -0
  21. data/test_app/README +256 -0
  22. data/test_app/Rakefile +10 -0
  23. data/test_app/app/controllers/application.rb +72 -0
  24. data/test_app/app/controllers/companies_controller.rb +2 -0
  25. data/test_app/app/controllers/user_sessions_controller.rb +25 -0
  26. data/test_app/app/controllers/users_controller.rb +61 -0
  27. data/test_app/app/helpers/application_helper.rb +3 -0
  28. data/test_app/app/helpers/companies_helper.rb +2 -0
  29. data/test_app/app/helpers/user_sessions_helper.rb +2 -0
  30. data/test_app/app/helpers/users_helper.rb +2 -0
  31. data/test_app/app/models/company.rb +4 -0
  32. data/test_app/app/models/project.rb +3 -0
  33. data/test_app/app/models/user.rb +5 -0
  34. data/test_app/app/models/user_session.rb +3 -0
  35. data/test_app/app/views/layouts/application.html.erb +27 -0
  36. data/test_app/app/views/user_sessions/new.html.erb +15 -0
  37. data/test_app/app/views/users/_form.erb +15 -0
  38. data/test_app/app/views/users/edit.html.erb +8 -0
  39. data/test_app/app/views/users/new.html.erb +8 -0
  40. data/test_app/app/views/users/show.html.erb +29 -0
  41. data/test_app/config/boot.rb +109 -0
  42. data/test_app/config/database.yml +19 -0
  43. data/test_app/config/environment.rb +69 -0
  44. data/test_app/config/environments/development.rb +17 -0
  45. data/test_app/config/environments/production.rb +22 -0
  46. data/test_app/config/environments/test.rb +22 -0
  47. data/test_app/config/initializers/inflections.rb +10 -0
  48. data/test_app/config/initializers/mime_types.rb +5 -0
  49. data/test_app/config/initializers/new_rails_defaults.rb +17 -0
  50. data/test_app/config/routes.rb +11 -0
  51. data/test_app/db/development.sqlite3 +0 -0
  52. data/test_app/db/migrate/20081023040052_create_users.rb +20 -0
  53. data/test_app/db/migrate/20081103003828_create_companies.rb +14 -0
  54. data/test_app/db/migrate/20081103003834_create_projects.rb +18 -0
  55. data/test_app/db/schema.rb +46 -0
  56. data/test_app/db/test.sqlite3 +0 -0
  57. data/test_app/doc/README_FOR_APP +2 -0
  58. data/test_app/public/404.html +30 -0
  59. data/test_app/public/422.html +30 -0
  60. data/test_app/public/500.html +30 -0
  61. data/test_app/public/dispatch.cgi +10 -0
  62. data/test_app/public/dispatch.fcgi +24 -0
  63. data/test_app/public/dispatch.rb +10 -0
  64. data/test_app/public/favicon.ico +0 -0
  65. data/test_app/public/images/rails.png +0 -0
  66. data/test_app/public/javascripts/application.js +2 -0
  67. data/test_app/public/javascripts/controls.js +963 -0
  68. data/test_app/public/javascripts/dragdrop.js +972 -0
  69. data/test_app/public/javascripts/effects.js +1120 -0
  70. data/test_app/public/javascripts/prototype.js +4225 -0
  71. data/test_app/public/robots.txt +5 -0
  72. data/test_app/public/stylesheets/scaffold.css +62 -0
  73. data/test_app/script/about +4 -0
  74. data/test_app/script/console +3 -0
  75. data/test_app/script/dbconsole +3 -0
  76. data/test_app/script/destroy +3 -0
  77. data/test_app/script/generate +3 -0
  78. data/test_app/script/performance/benchmarker +3 -0
  79. data/test_app/script/performance/profiler +3 -0
  80. data/test_app/script/performance/request +3 -0
  81. data/test_app/script/plugin +3 -0
  82. data/test_app/script/process/inspector +3 -0
  83. data/test_app/script/process/reaper +3 -0
  84. data/test_app/script/process/spawner +3 -0
  85. data/test_app/script/runner +3 -0
  86. data/test_app/script/server +3 -0
  87. data/test_app/test/fixtures/companies.yml +7 -0
  88. data/test_app/test/fixtures/projects.yml +4 -0
  89. data/test_app/test/fixtures/users.yml +21 -0
  90. data/test_app/test/functional/companies_controller_test.rb +8 -0
  91. data/test_app/test/functional/user_sessions_controller_test.rb +36 -0
  92. data/test_app/test/functional/users_controller_test.rb +8 -0
  93. data/test_app/test/integration/company_user_session_stories_test.rb +46 -0
  94. data/test_app/test/integration/user_sesion_stories_test.rb +105 -0
  95. data/test_app/test/integration/user_session_config_test.rb +24 -0
  96. data/test_app/test/integration/user_session_test.rb +161 -0
  97. data/test_app/test/test_helper.rb +81 -0
  98. data/test_app/test/unit/account_test.rb +8 -0
  99. data/test_app/test/unit/company_test.rb +8 -0
  100. data/test_app/test/unit/project_test.rb +8 -0
  101. data/test_app/test/unit/user_test.rb +80 -0
  102. metadata +201 -0
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+
4
+ require File.dirname(__FILE__) << "/lib/authlogic/version"
5
+
6
+ Echoe.new 'authlogic' do |p|
7
+ p.version = Authlogic::Version::STRING
8
+ p.author = "Ben Johnson of Binary Logic"
9
+ p.email = 'bjohnson@binarylogic.com'
10
+ p.project = 'authlogic'
11
+ p.summary = "Rails authentication done right"
12
+ p.url = "http://github.com/binarylogic/authlogic"
13
+ p.dependencies = %w(activesupport activerecord)
14
+ p.include_rakefile = true
15
+ end
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{authlogic}
3
+ s.version = "0.10.4"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Ben Johnson of Binary Logic"]
7
+ s.date = %q{2008-11-03}
8
+ s.description = %q{Rails authentication done right}
9
+ s.email = %q{bjohnson@binarylogic.com}
10
+ s.extra_rdoc_files = ["CHANGELOG.rdoc", "lib/authlogic/active_record/acts_as_authentic.rb", "lib/authlogic/active_record/authenticates_many.rb", "lib/authlogic/active_record/scoped_session.rb", "lib/authlogic/controller_adapters/abstract_adapter.rb", "lib/authlogic/controller_adapters/rails_adapter.rb", "lib/authlogic/session/active_record_trickery.rb", "lib/authlogic/session/base.rb", "lib/authlogic/session/callbacks.rb", "lib/authlogic/session/config.rb", "lib/authlogic/session/errors.rb", "lib/authlogic/sha512_crypto_provider.rb", "lib/authlogic/version.rb", "lib/authlogic.rb", "README.rdoc"]
11
+ s.files = ["CHANGELOG.rdoc", "init.rb", "lib/authlogic/active_record/acts_as_authentic.rb", "lib/authlogic/active_record/authenticates_many.rb", "lib/authlogic/active_record/scoped_session.rb", "lib/authlogic/controller_adapters/abstract_adapter.rb", "lib/authlogic/controller_adapters/rails_adapter.rb", "lib/authlogic/session/active_record_trickery.rb", "lib/authlogic/session/base.rb", "lib/authlogic/session/callbacks.rb", "lib/authlogic/session/config.rb", "lib/authlogic/session/errors.rb", "lib/authlogic/sha512_crypto_provider.rb", "lib/authlogic/version.rb", "lib/authlogic.rb", "Manifest", "MIT-LICENSE", "Rakefile", "README.rdoc", "test_app/app/controllers/application.rb", "test_app/app/controllers/companies_controller.rb", "test_app/app/controllers/user_sessions_controller.rb", "test_app/app/controllers/users_controller.rb", "test_app/app/helpers/application_helper.rb", "test_app/app/helpers/companies_helper.rb", "test_app/app/helpers/user_sessions_helper.rb", "test_app/app/helpers/users_helper.rb", "test_app/app/models/company.rb", "test_app/app/models/project.rb", "test_app/app/models/user.rb", "test_app/app/models/user_session.rb", "test_app/app/views/layouts/application.html.erb", "test_app/app/views/user_sessions/new.html.erb", "test_app/app/views/users/_form.erb", "test_app/app/views/users/edit.html.erb", "test_app/app/views/users/new.html.erb", "test_app/app/views/users/show.html.erb", "test_app/config/boot.rb", "test_app/config/database.yml", "test_app/config/environment.rb", "test_app/config/environments/development.rb", "test_app/config/environments/production.rb", "test_app/config/environments/test.rb", "test_app/config/initializers/inflections.rb", "test_app/config/initializers/mime_types.rb", "test_app/config/initializers/new_rails_defaults.rb", "test_app/config/routes.rb", "test_app/db/development.sqlite3", "test_app/db/migrate/20081023040052_create_users.rb", "test_app/db/migrate/20081103003828_create_companies.rb", "test_app/db/migrate/20081103003834_create_projects.rb", "test_app/db/schema.rb", "test_app/db/test.sqlite3", "test_app/doc/README_FOR_APP", "test_app/public/404.html", "test_app/public/422.html", "test_app/public/500.html", "test_app/public/dispatch.cgi", "test_app/public/dispatch.fcgi", "test_app/public/dispatch.rb", "test_app/public/favicon.ico", "test_app/public/images/rails.png", "test_app/public/javascripts/application.js", "test_app/public/javascripts/controls.js", "test_app/public/javascripts/dragdrop.js", "test_app/public/javascripts/effects.js", "test_app/public/javascripts/prototype.js", "test_app/public/robots.txt", "test_app/public/stylesheets/scaffold.css", "test_app/Rakefile", "test_app/README", "test_app/script/about", "test_app/script/console", "test_app/script/dbconsole", "test_app/script/destroy", "test_app/script/generate", "test_app/script/performance/benchmarker", "test_app/script/performance/profiler", "test_app/script/performance/request", "test_app/script/plugin", "test_app/script/process/inspector", "test_app/script/process/reaper", "test_app/script/process/spawner", "test_app/script/runner", "test_app/script/server", "test_app/test/fixtures/companies.yml", "test_app/test/fixtures/projects.yml", "test_app/test/fixtures/users.yml", "test_app/test/functional/companies_controller_test.rb", "test_app/test/functional/user_sessions_controller_test.rb", "test_app/test/functional/users_controller_test.rb", "test_app/test/integration/company_user_session_stories_test.rb", "test_app/test/integration/user_sesion_stories_test.rb", "test_app/test/integration/user_session_config_test.rb", "test_app/test/integration/user_session_test.rb", "test_app/test/test_helper.rb", "test_app/test/unit/account_test.rb", "test_app/test/unit/company_test.rb", "test_app/test/unit/project_test.rb", "test_app/test/unit/user_test.rb", "authlogic.gemspec"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://github.com/binarylogic/authlogic}
14
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Authlogic", "--main", "README.rdoc"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{authlogic}
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{Rails authentication done right}
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 2
23
+
24
+ if current_version >= 3 then
25
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
26
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
27
+ s.add_development_dependency(%q<echoe>, [">= 0"])
28
+ else
29
+ s.add_dependency(%q<activesupport>, [">= 0"])
30
+ s.add_dependency(%q<activerecord>, [">= 0"])
31
+ s.add_dependency(%q<echoe>, [">= 0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<activesupport>, [">= 0"])
35
+ s.add_dependency(%q<activerecord>, [">= 0"])
36
+ s.add_dependency(%q<echoe>, [">= 0"])
37
+ end
38
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require "authlogic"
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + "/authlogic/version"
2
+
3
+ require File.dirname(__FILE__) + "/authlogic/controller_adapters/abstract_adapter"
4
+ require File.dirname(__FILE__) + "/authlogic/controller_adapters/rails_adapter" if defined?(Rails)
5
+
6
+ require File.dirname(__FILE__) + "/authlogic/sha512_crypto_provider"
7
+
8
+ require File.dirname(__FILE__) + "/authlogic/active_record/acts_as_authentic"
9
+ require File.dirname(__FILE__) + "/authlogic/active_record/authenticates_many"
10
+ require File.dirname(__FILE__) + "/authlogic/active_record/scoped_session"
11
+
12
+ require File.dirname(__FILE__) + "/authlogic/session/active_record_trickery"
13
+ require File.dirname(__FILE__) + "/authlogic/session/callbacks"
14
+ require File.dirname(__FILE__) + "/authlogic/session/config"
15
+ require File.dirname(__FILE__) + "/authlogic/session/errors"
16
+ require File.dirname(__FILE__) + "/authlogic/session/base"
17
+
18
+ module Authlogic
19
+ module Session
20
+ class Base
21
+ include ActiveRecordTrickery
22
+ include Callbacks
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,265 @@
1
+ module Authlogic
2
+ module ActiveRecord # :nodoc:
3
+ # = Acts As Authentic
4
+ # Provides and "acts_as" method to include in your models to help with authentication. See method below.
5
+ module ActsAsAuthentic
6
+ # Call this method in your model to add in basic authentication madness that your authlogic session expects.
7
+ #
8
+ # <b>Please keep in mind</b> that based on your configuration the method names could change. For example, if you pass the option:
9
+ #
10
+ # :password_field => :pass
11
+ #
12
+ # The method will not be password=, it will be pass=. Same with valid_password?, it will be valid_pass?, etc.
13
+ #
14
+ # === Methods
15
+ # For example purposes lets assume you have a User model.
16
+ #
17
+ # Class method name Description
18
+ # User.crypto_provider The class that you set in your :crypto_provider option
19
+ # User.forget_all! Finds all records, loops through them, and calls forget! on each record. This is paginated to save on memory.
20
+ # User.unique_token returns unique token generated by your :crypto_provider
21
+ #
22
+ # Named Scopes
23
+ # User.logged_in Find all users who are logged in, based on your :logged_in_timeout option.
24
+ # User.logged_out Same as above, but logged out.
25
+ #
26
+ # Isntace method name
27
+ # user.password= Method name based on the :password_field option. This is used to set the password. Pass the *raw* password to this.
28
+ # user.confirm_password= Confirms the password, needed to change the password.
29
+ # user.valid_password?(pass) Determines if the password passed is valid. The password could be encrypted or raw.
30
+ # user.reset_password! Basically resets the password to a random password using only letters and numbers.
31
+ # user.logged_in? Based on the :logged_in_timeout option. Tells you if the user is logged in or not.
32
+ # user.forget! Changes their remember token, making their cookie and session invalid. A way to log the user out withouth changing their password.
33
+ #
34
+ # === Options
35
+ # * <tt>session_class:</tt> default: "#{name}Session", the related session class. Used so that you don't have to repeat yourself here. A lot of the configuration will be based off of the configuration values of this class.
36
+ # * <tt>crypto_provider:</tt> default: Authlogic::Sha512CryptoProvider, class that provides Sha512 encryption. What ultimately encrypts your password.
37
+ # * <tt>crypto_provider_type:</tt> default: options[:crypto_provider].respond_to?(:decrypt) ? :encryption : :hash. You can explicitly set this if you wish. Since encryptions and hashes are handled different this is the flag Authlogic uses.
38
+ # * <tt>login_field:</tt> default: options[:session_class].login_field, the name of the field used for logging in
39
+ # * <tt>login_field_type:</tt> default: options[:login_field] == :email ? :email : :login, tells authlogic how to validation the field, what regex to use, etc.
40
+ # * <tt>password_field:</tt> default: options[:session_class].password_field, the name of the field to set the password, *NOT* the field the encrypted password is stored
41
+ # * <tt>crypted_password_field:</tt> default: depends on which columns are present, checks: crypted_password, encrypted_password, password_hash, pw_hash, if none are present defaults to crypted_password. This is the name of column that your encrypted password is stored.
42
+ # * <tt>password_salt_field:</tt> default: depends on which columns are present, checks: password_salt, pw_salt, salt, if none are present defaults to password_salt. This is the name of the field your salt is stored, only relevant for a hash crypto provider.
43
+ # * <tt>remember_token_field:</tt> default: options[:session_class].remember_token_field, the name of the field your remember token is stored. What the cookie stores so the session can be "remembered"
44
+ # * <tt>scope:</tt> default: nil, if all of your users belong to an account you might want to scope everything to the account. Just pass :account_id
45
+ # * <tt>logged_in_timeout:</tt> default: 10.minutes, this allows you to specify a time the determines if a user is logged in or out. Useful if you want to count how many users are currently logged in.
46
+ # * <tt>session_ids:</tt> default: [nil], the sessions that we want to automatically reset when a user is created or updated so you don't have to worry about this. Set to [] to disable. Should be an array of ids. See Authlogic::Session::Base#initialize for information on ids. The order is important. The first id should be your main session, the session they need to log into first. This is generally nil, meaning so explicitly set id.
47
+ def acts_as_authentic(options = {})
48
+ # Setup default options
49
+ options[:session_class] ||= "#{name}Session".constantize
50
+ options[:crypto_provider] ||= Sha512CryptoProvider
51
+ options[:crypto_provider_type] ||= options[:crypto_provider].respond_to?(:decrypt) ? :encryption : :hash
52
+ options[:login_field] ||= options[:session_class].login_field
53
+ options[:login_field_type] ||= options[:login_field] == :email ? :email : :login
54
+ options[:password_field] ||= options[:session_class].password_field
55
+ options[:crypted_password_field] ||=
56
+ (column_names.include?("crypted_password") && :crypted_password) ||
57
+ (column_names.include?("encrypted_password") && :encrypted_password) ||
58
+ (column_names.include?("password_hash") && :password_hash) ||
59
+ (column_names.include?("pw_hash") && :pw_hash) ||
60
+ :crypted_password
61
+ options[:password_salt_field] ||=
62
+ (column_names.include?("password_salt") && :password_salt) ||
63
+ (column_names.include?("pw_salt") && :pw_salt) ||
64
+ (column_names.include?("salt") && :salt) ||
65
+ :password_salt
66
+ options[:remember_token_field] ||= options[:session_class].remember_token_field
67
+ options[:logged_in_timeout] ||= 10.minutes
68
+ options[:session_ids] ||= [nil]
69
+
70
+ # Validations
71
+ case options[:login_field_type]
72
+ when :email
73
+ validates_length_of options[:login_field], :within => 6..100
74
+ email_name_regex = '[\w\.%\+\-]+'
75
+ domain_head_regex = '(?:[A-Z0-9\-]+\.)+'
76
+ domain_tld_regex = '(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|jobs|museum)'
77
+ email_regex = /\A#{email_name_regex}@#{domain_head_regex}#{domain_tld_regex}\z/i
78
+ validates_format_of options[:login_field], :with => email_regex, :message => "should look like an email address."
79
+ else
80
+ validates_length_of options[:login_field], :within => 2..100
81
+ validates_format_of options[:login_field], :with => /\A\w[\w\.\-_@]+\z/, :message => "use only letters, numbers, and .-_@ please."
82
+ end
83
+
84
+ validates_uniqueness_of options[:login_field], :scope => options[:scope]
85
+ validates_uniqueness_of options[:remember_token_field]
86
+ validate :validate_password
87
+ validates_numericality_of :login_count, :only_integer => :true, :greater_than_or_equal_to => 0, :allow_nil => true if column_names.include?("login_count")
88
+
89
+ if column_names.include?("last_request_at")
90
+ named_scope :logged_in, lambda { {:conditions => ["last_request_at > ?", options[:logged_in_timeout].ago]} }
91
+ named_scope :logged_out, lambda { {:conditions => ["last_request_at <= ?", options[:logged_in_timeout].ago]} }
92
+ end
93
+
94
+ before_save :get_session_information, :if => :update_sessions?
95
+ after_save :maintain_sessions!, :if => :update_sessions?
96
+
97
+ # Attributes
98
+ attr_writer "confirm_#{options[:password_field]}"
99
+ attr_accessor "tried_to_set_#{options[:password_field]}"
100
+
101
+ # Class methods
102
+ class_eval <<-"end_eval", __FILE__, __LINE__
103
+ def self.unique_token
104
+ crypto_provider.encrypt(Time.now.to_s + (1..10).collect{ rand.to_s }.join)
105
+ end
106
+
107
+ def self.crypto_provider
108
+ #{options[:crypto_provider]}
109
+ end
110
+
111
+ def self.forget_all!
112
+ # Paginate these to save on memory
113
+ records = nil
114
+ i = 0
115
+ begin
116
+ records = find(:all, :limit => 50, :offset => i)
117
+ records.each { |record| record.forget! }
118
+ i += 50
119
+ end while !records.blank?
120
+ end
121
+ end_eval
122
+
123
+ # Instance methods
124
+ if column_names.include?("last_request_at")
125
+ class_eval <<-"end_eval", __FILE__, __LINE__
126
+ def logged_in?
127
+ !last_request_at.nil? && last_request_at > #{options[:logged_in_timeout].to_i}.seconds.ago
128
+ end
129
+ end_eval
130
+ end
131
+
132
+ case options[:crypto_provider_type]
133
+ when :hash
134
+ class_eval <<-"end_eval", __FILE__, __LINE__
135
+ def #{options[:password_field]}=(pass)
136
+ return if pass.blank?
137
+ self.tried_to_set_#{options[:password_field]} = true
138
+ @#{options[:password_field]} = pass
139
+ self.#{options[:remember_token_field]} = self.class.unique_token
140
+ self.#{options[:password_salt_field]} = self.class.unique_token
141
+ self.#{options[:crypted_password_field]} = crypto_provider.encrypt(@#{options[:password_field]} + #{options[:password_salt_field]})
142
+ end
143
+
144
+ def valid_#{options[:password_field]}?(attempted_password)
145
+ return false if attempted_password.blank?
146
+ attempted_password == #{options[:crypted_password_field]} || #{options[:crypted_password_field]} == crypto_provider.encrypt(attempted_password + #{options[:password_salt_field]})
147
+ end
148
+ end_eval
149
+ when :encryption
150
+ class_eval <<-"end_eval", __FILE__, __LINE__
151
+ def #{options[:password_field]}=(pass)
152
+ return if pass.blank?
153
+ self.tried_to_set_#{options[:password_field]} = true
154
+ @#{options[:password_field]} = pass
155
+ self.#{options[:remember_token_field]} = self.class.unique_token
156
+ self.#{options[:crypted_password_field]} = crypto_provider.encrypt(@#{options[:password_field]})
157
+ end
158
+
159
+ def valid_#{options[:password_field]}?(attemtped_password)
160
+ return false if attempted_password.blank?
161
+ attempted_password == #{options[:crypted_password_field]} || #{options[:crypted_password_field]} = crypto_provider.decrypt(attempted_password)
162
+ end
163
+ end_eval
164
+ end
165
+
166
+ class_eval <<-"end_eval", __FILE__, __LINE__
167
+ def #{options[:password_field]}; end
168
+ def confirm_#{options[:password_field]}; end
169
+
170
+ def crypto_provider
171
+ self.class.crypto_provider
172
+ end
173
+
174
+ def forget!
175
+ self.#{options[:remember_token_field]} = self.class.unique_token
176
+ save_without_session_maintenance(false)
177
+ end
178
+
179
+ def reset_#{options[:password_field]}!
180
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
181
+ newpass = ""
182
+ 1.upto(10) { |i| newpass << chars[rand(chars.size-1)] }
183
+ self.#{options[:password_field]} = newpass
184
+ self.confirm_#{options[:password_field]} = newpass
185
+ save_without_session_maintenance(false)
186
+ end
187
+ alias_method :randomize_password!, :reset_password!
188
+
189
+ def save_without_session_maintenance(*args)
190
+ @skip_session_maintenance = true
191
+ result = save(*args)
192
+ @skip_session_maintenance = false
193
+ result
194
+ end
195
+
196
+ protected
197
+ def update_sessions?
198
+ !@skip_session_maintenance && #{options[:session_class]}.activated? && !#{options[:session_ids].inspect}.blank? && #{options[:remember_token_field]}_changed?
199
+ end
200
+
201
+ def get_session_information
202
+ # Need to determine if we are completely logged out, or logged in as another user
203
+ @_sessions = []
204
+ @_logged_out = true
205
+
206
+ #{options[:session_ids].inspect}.each do |session_id|
207
+ session = #{options[:session_class]}.find(*[session_id].compact)
208
+ if session
209
+ if !session.record.blank?
210
+ @_logged_out = false
211
+ @_sessions << session if session.record == self
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ def maintain_sessions!
218
+ if @_logged_out
219
+ create_session!
220
+ elsif !@_sessions.blank?
221
+ update_sessions!
222
+ end
223
+ end
224
+
225
+ def create_session!
226
+ # We only want to automatically login into the first session, since this is the main session. The other sessions are sessions
227
+ # that need to be created after logging into the main session.
228
+ session_id = #{options[:session_ids].inspect}.first
229
+
230
+ # If we are already logged in, ignore this completely. All that we care about is updating ourself.
231
+ next if #{options[:session_class]}.find(*[session_id].compact)
232
+
233
+ # Log me in
234
+ args = [self, session_id].compact
235
+ #{options[:session_class]}.create(*args)
236
+ end
237
+
238
+ def update_sessions!
239
+ # We found sessions above, let's update them with the new info
240
+ @_sessions.each do |stale_session|
241
+ stale_session.unauthorized_record = self
242
+ stale_session.save
243
+ end
244
+ end
245
+
246
+ def tried_to_set_password?
247
+ tried_to_set_password == true
248
+ end
249
+
250
+ def validate_password
251
+ if new_record? || tried_to_set_#{options[:password_field]}?
252
+ if @#{options[:password_field]}.blank?
253
+ errors.add(:#{options[:password_field]}, "can not be blank")
254
+ else
255
+ errors.add(:confirm_#{options[:password_field]}, "did not match") if @confirm_#{options[:password_field]} != @#{options[:password_field]}
256
+ end
257
+ end
258
+ end
259
+ end_eval
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ ActiveRecord::Base.extend Authlogic::ActiveRecord::ActsAsAuthentic
@@ -0,0 +1,19 @@
1
+ module Authlogic
2
+ module ActiveRecord
3
+ module AuthenticatesMany
4
+ def authenticates_many(name, options = {})
5
+ options[:session_class] ||= name.to_s.classify.constantize
6
+ options[:relationship_name] ||= options[:session_class].klass_name.underscore.pluralize
7
+ class_eval <<-"end_eval", __FILE__, __LINE__
8
+ def #{name}
9
+ find_options = #{options[:find_options].inspect} || #{options[:relationship_name]}.scope(:find)
10
+ find_options.delete_if { |key, value| ![:conditions, :include, :joins].include?(key.to_sym) || value.nil? }
11
+ @#{name} ||= Authlogic::ActiveRecord::ScopedSession.new(#{options[:session_class]}, find_options, #{options[:scope_cookies] ? "self.class.model_name.underscore + '_' + self.send(self.class.primary_key).to_s" : "nil"})
12
+ end
13
+ end_eval
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ ActiveRecord::Base.extend Authlogic::ActiveRecord::AuthenticatesMany
@@ -0,0 +1,28 @@
1
+ module Authlogic
2
+ module ActiveRecord
3
+ class ScopedSession # :nodoc:
4
+ attr_accessor :klass, :find_options, :id
5
+
6
+ def initialize(klass, find_options, id)
7
+ self.klass = klass
8
+ self.find_options = find_options
9
+ self.id = id
10
+ end
11
+
12
+ [:create, :create!, :find, :new].each do |method|
13
+ class_eval <<-"end_eval", __FILE__, __LINE__
14
+ def #{method}(*args)
15
+ klass.with_scope(scope_options) do
16
+ klass.#{method}(*args)
17
+ end
18
+ end
19
+ end_eval
20
+ end
21
+
22
+ private
23
+ def scope_options
24
+ {:find_options => find_options, :id => id}
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module Authlogic
2
+ module ControllerAdapters # :nodoc:
3
+ # = Abstract Adapter
4
+ # Allows you to use Authlogic in any framework you want, not just rails. See tha RailsAdapter for an example of how to adapter Authlogic to work with your framework.
5
+ class AbstractAdapter
6
+ attr_accessor :controller
7
+
8
+ def initialize(controller)
9
+ self.controller = controller
10
+ end
11
+
12
+ def authenticate_with_http_basic(*args, &block)
13
+ end
14
+
15
+ def cookies
16
+ end
17
+
18
+ def request
19
+ end
20
+
21
+ def session
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ module Authlogic
2
+ module ControllerAdapters
3
+ # = Rails Adapter
4
+ # Adapts authlogic to work with rails. The point is to close the gap between what authlogic expects and what the rails controller object
5
+ # provides. Similar to how ActiveRecord has an adapter for MySQL, PostgreSQL, SQLite, etc.
6
+ class RailsAdapter < AbstractAdapter
7
+ def authenticate_with_http_basic(*args, &block)
8
+ controller.authenticate_with_http_basic(*args, &block)
9
+ end
10
+
11
+ def cookies
12
+ controller.send(:cookies)
13
+ end
14
+
15
+ def request
16
+ controller.request
17
+ end
18
+
19
+ def session
20
+ controller.session
21
+ end
22
+ end
23
+
24
+ # = Rails Implementation
25
+ # Lets Authlogic know about the controller object, AKA "activates" authlogic.
26
+ module RailsImplementation
27
+ def self.included(klass) # :nodoc:
28
+ klass.prepend_before_filter :set_controller
29
+ end
30
+
31
+ private
32
+ def set_controller
33
+ Authlogic::Session::Base.controller = RailsAdapter.new(self)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ ActionController::Base.send(:include, Authlogic::ControllerAdapters::RailsImplementation)