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.
- data/CHANGELOG.rdoc +47 -0
- data/MIT-LICENSE +20 -0
- data/Manifest +100 -0
- data/README.rdoc +292 -0
- data/Rakefile +15 -0
- data/authlogic.gemspec +38 -0
- data/init.rb +1 -0
- data/lib/authlogic.rb +25 -0
- data/lib/authlogic/active_record/acts_as_authentic.rb +265 -0
- data/lib/authlogic/active_record/authenticates_many.rb +19 -0
- data/lib/authlogic/active_record/scoped_session.rb +28 -0
- data/lib/authlogic/controller_adapters/abstract_adapter.rb +25 -0
- data/lib/authlogic/controller_adapters/rails_adapter.rb +39 -0
- data/lib/authlogic/session/active_record_trickery.rb +26 -0
- data/lib/authlogic/session/base.rb +510 -0
- data/lib/authlogic/session/callbacks.rb +56 -0
- data/lib/authlogic/session/config.rb +237 -0
- data/lib/authlogic/session/errors.rb +18 -0
- data/lib/authlogic/sha512_crypto_provider.rb +18 -0
- data/lib/authlogic/version.rb +56 -0
- data/test_app/README +256 -0
- data/test_app/Rakefile +10 -0
- data/test_app/app/controllers/application.rb +72 -0
- data/test_app/app/controllers/companies_controller.rb +2 -0
- data/test_app/app/controllers/user_sessions_controller.rb +25 -0
- data/test_app/app/controllers/users_controller.rb +61 -0
- data/test_app/app/helpers/application_helper.rb +3 -0
- data/test_app/app/helpers/companies_helper.rb +2 -0
- data/test_app/app/helpers/user_sessions_helper.rb +2 -0
- data/test_app/app/helpers/users_helper.rb +2 -0
- data/test_app/app/models/company.rb +4 -0
- data/test_app/app/models/project.rb +3 -0
- data/test_app/app/models/user.rb +5 -0
- data/test_app/app/models/user_session.rb +3 -0
- data/test_app/app/views/layouts/application.html.erb +27 -0
- data/test_app/app/views/user_sessions/new.html.erb +15 -0
- data/test_app/app/views/users/_form.erb +15 -0
- data/test_app/app/views/users/edit.html.erb +8 -0
- data/test_app/app/views/users/new.html.erb +8 -0
- data/test_app/app/views/users/show.html.erb +29 -0
- data/test_app/config/boot.rb +109 -0
- data/test_app/config/database.yml +19 -0
- data/test_app/config/environment.rb +69 -0
- data/test_app/config/environments/development.rb +17 -0
- data/test_app/config/environments/production.rb +22 -0
- data/test_app/config/environments/test.rb +22 -0
- data/test_app/config/initializers/inflections.rb +10 -0
- data/test_app/config/initializers/mime_types.rb +5 -0
- data/test_app/config/initializers/new_rails_defaults.rb +17 -0
- data/test_app/config/routes.rb +11 -0
- data/test_app/db/development.sqlite3 +0 -0
- data/test_app/db/migrate/20081023040052_create_users.rb +20 -0
- data/test_app/db/migrate/20081103003828_create_companies.rb +14 -0
- data/test_app/db/migrate/20081103003834_create_projects.rb +18 -0
- data/test_app/db/schema.rb +46 -0
- data/test_app/db/test.sqlite3 +0 -0
- data/test_app/doc/README_FOR_APP +2 -0
- data/test_app/public/404.html +30 -0
- data/test_app/public/422.html +30 -0
- data/test_app/public/500.html +30 -0
- data/test_app/public/dispatch.cgi +10 -0
- data/test_app/public/dispatch.fcgi +24 -0
- data/test_app/public/dispatch.rb +10 -0
- data/test_app/public/favicon.ico +0 -0
- data/test_app/public/images/rails.png +0 -0
- data/test_app/public/javascripts/application.js +2 -0
- data/test_app/public/javascripts/controls.js +963 -0
- data/test_app/public/javascripts/dragdrop.js +972 -0
- data/test_app/public/javascripts/effects.js +1120 -0
- data/test_app/public/javascripts/prototype.js +4225 -0
- data/test_app/public/robots.txt +5 -0
- data/test_app/public/stylesheets/scaffold.css +62 -0
- data/test_app/script/about +4 -0
- data/test_app/script/console +3 -0
- data/test_app/script/dbconsole +3 -0
- data/test_app/script/destroy +3 -0
- data/test_app/script/generate +3 -0
- data/test_app/script/performance/benchmarker +3 -0
- data/test_app/script/performance/profiler +3 -0
- data/test_app/script/performance/request +3 -0
- data/test_app/script/plugin +3 -0
- data/test_app/script/process/inspector +3 -0
- data/test_app/script/process/reaper +3 -0
- data/test_app/script/process/spawner +3 -0
- data/test_app/script/runner +3 -0
- data/test_app/script/server +3 -0
- data/test_app/test/fixtures/companies.yml +7 -0
- data/test_app/test/fixtures/projects.yml +4 -0
- data/test_app/test/fixtures/users.yml +21 -0
- data/test_app/test/functional/companies_controller_test.rb +8 -0
- data/test_app/test/functional/user_sessions_controller_test.rb +36 -0
- data/test_app/test/functional/users_controller_test.rb +8 -0
- data/test_app/test/integration/company_user_session_stories_test.rb +46 -0
- data/test_app/test/integration/user_sesion_stories_test.rb +105 -0
- data/test_app/test/integration/user_session_config_test.rb +24 -0
- data/test_app/test/integration/user_session_test.rb +161 -0
- data/test_app/test/test_helper.rb +81 -0
- data/test_app/test/unit/account_test.rb +8 -0
- data/test_app/test/unit/company_test.rb +8 -0
- data/test_app/test/unit/project_test.rb +8 -0
- data/test_app/test/unit/user_test.rb +80 -0
- metadata +201 -0
data/Rakefile
ADDED
@@ -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
|
data/authlogic.gemspec
ADDED
@@ -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"
|
data/lib/authlogic.rb
ADDED
@@ -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)
|