adva_user 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README +114 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/adva_user.gemspec +17 -0
- data/app/controllers/admin/base_account_controller.rb +13 -0
- data/app/controllers/admin/users_controller.rb +95 -0
- data/app/controllers/password_controller.rb +36 -0
- data/app/controllers/session_controller.rb +30 -0
- data/app/helpers/users_helper.rb +27 -0
- data/app/models/account.rb +7 -0
- data/app/models/membership.rb +16 -0
- data/app/models/password_mailer.rb +43 -0
- data/app/models/user.rb +106 -0
- data/app/views/admin/users/_form.html.erb +29 -0
- data/app/views/admin/users/_sidebar.html.erb +8 -0
- data/app/views/admin/users/edit.html.erb +7 -0
- data/app/views/admin/users/index.html.erb +13 -0
- data/app/views/admin/users/new.html.erb +5 -0
- data/app/views/admin/users/show.html.erb +27 -0
- data/app/views/layouts/login.html.erb +24 -0
- data/app/views/password/edit.html.erb +14 -0
- data/app/views/password/new.html.erb +13 -0
- data/app/views/password_mailer/reset_password_email.html.erb +3 -0
- data/app/views/password_mailer/updated_password_email.html.erb +1 -0
- data/app/views/session/new.html.erb +17 -0
- data/config/initializers/menus.rb +25 -0
- data/config/routes.rb +14 -0
- data/db/migrate/20080402000001_create_users_table.rb +33 -0
- data/db/migrate/20080402000005_create_memberships_table.rb +13 -0
- data/db/migrate/20090625124502_create_accounts.rb +13 -0
- data/db/migrate/20090625133231_add_account_to_user.rb +10 -0
- data/lib/action_controller/authenticate_anonymous.rb +70 -0
- data/lib/action_controller/authenticate_user.rb +201 -0
- data/lib/active_record/belongs_to_author.rb +37 -0
- data/lib/adva_user.rb +28 -0
- data/lib/adva_user/version.rb +3 -0
- data/lib/login/helper_integration.rb +11 -0
- data/lib/login/mail_config.rb +39 -0
- data/test/contexts.rb +42 -0
- data/test/fixtures.rb +18 -0
- data/test/functional/admin/users_controller_test.rb +176 -0
- data/test/functional/password_controller_test.rb +96 -0
- data/test/functional/session_controller_test.rb +1 -0
- data/test/functional/user_controller_test.rb +95 -0
- data/test/integration/anonymous_login_test.rb +39 -0
- data/test/integration/edit_user_test.rb +44 -0
- data/test/integration/memberships_test.rb +52 -0
- data/test/integration/user_deletion_test.rb +27 -0
- data/test/integration/user_login_test.rb +53 -0
- data/test/integration/user_login_with_remember_me_test.rb +20 -0
- data/test/integration/user_registration_test.rb +64 -0
- data/test/test_helper.rb +1 -0
- data/test/unit/cells/user_cell_test.rb +13 -0
- data/test/unit/helpers/users_helper_test.rb +52 -0
- data/test/unit/models/account_test.rb +21 -0
- data/test/unit/models/anonymous_test.rb +54 -0
- data/test/unit/models/password_mailer_test.rb +26 -0
- data/test/unit/models/user_mailer_test.rb +16 -0
- data/test/unit/models/user_test.rb +173 -0
- data/vendor/gems/authentication/.gitignore +17 -0
- data/vendor/gems/authentication/Gemfile +4 -0
- data/vendor/gems/authentication/LICENSE +22 -0
- data/vendor/gems/authentication/MIT-LICENSE +38 -0
- data/vendor/gems/authentication/README +39 -0
- data/vendor/gems/authentication/README.md +29 -0
- data/vendor/gems/authentication/RUNNING_UNIT_TESTS +13 -0
- data/vendor/gems/authentication/Rakefile +61 -0
- data/vendor/gems/authentication/authentication.gemspec +17 -0
- data/vendor/gems/authentication/lib/authentication.rb +270 -0
- data/vendor/gems/authentication/lib/authentication/active_record_extensions.rb +11 -0
- data/vendor/gems/authentication/lib/authentication/bogus.rb +13 -0
- data/vendor/gems/authentication/lib/authentication/hash_helper.rb +26 -0
- data/vendor/gems/authentication/lib/authentication/ldap.rb +49 -0
- data/vendor/gems/authentication/lib/authentication/remember_me.rb +52 -0
- data/vendor/gems/authentication/lib/authentication/salted_hash.rb +53 -0
- data/vendor/gems/authentication/lib/authentication/single_token.rb +53 -0
- data/vendor/gems/authentication/lib/authentication/version.rb +3 -0
- data/vendor/gems/authentication/lib/radius/dictionary +207 -0
- data/vendor/gems/authentication/test_backup/abstract_unit.rb +30 -0
- data/vendor/gems/authentication/test_backup/active_record_extension_test.rb +17 -0
- data/vendor/gems/authentication/test_backup/authentication_test.rb +231 -0
- data/vendor/gems/authentication/test_backup/database.yml +12 -0
- data/vendor/gems/authentication/test_backup/fixtures/user.rb +3 -0
- data/vendor/gems/authentication/test_backup/fixtures/users.yml +3 -0
- data/vendor/gems/authentication/test_backup/options_test.rb +100 -0
- data/vendor/gems/authentication/test_backup/remember_me_test.rb +41 -0
- data/vendor/gems/authentication/test_backup/salted_hash_test.rb +38 -0
- data/vendor/gems/authentication/test_backup/schema.rb +10 -0
- data/vendor/gems/authentication/test_backup/single_token_test.rb +44 -0
- data/vendor/gems/authentication/test_backup/test_helper.rb +8 -0
- metadata +157 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2012 Micah Geisel
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Maintainers
|
|
2
|
+
-----------
|
|
3
|
+
Copyright (c) 2007-2008 CorData <cordata.org>
|
|
4
|
+
Copyright (c) 2007-2008 Eric Anderson <eric@pixelwareinc.com>
|
|
5
|
+
|
|
6
|
+
Contributors
|
|
7
|
+
------------
|
|
8
|
+
Copyright (c) 2008 Bart Duchesne <bduc@dyndaco.com>
|
|
9
|
+
All of LDAP, Radius
|
|
10
|
+
Most of Bogus and environment-based configuration support
|
|
11
|
+
|
|
12
|
+
3rd Party Code
|
|
13
|
+
--------------
|
|
14
|
+
Radius Authentication Module:
|
|
15
|
+
Copyright (C) 2002 Rafael R. Sevilla <dido@imperium.ph>
|
|
16
|
+
Licensed under LGPL
|
|
17
|
+
|
|
18
|
+
Everything not 3rd Party Code is licensed under the following
|
|
19
|
+
MIT-LICENSE:
|
|
20
|
+
|
|
21
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
22
|
+
a copy of this software and associated documentation files (the
|
|
23
|
+
"Software"), to deal in the Software without restriction, including
|
|
24
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
25
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
26
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
27
|
+
the following conditions:
|
|
28
|
+
|
|
29
|
+
The above copyright notice and this permission notice shall be
|
|
30
|
+
included in all copies or substantial portions of the Software.
|
|
31
|
+
|
|
32
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
33
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
34
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
35
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
36
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
37
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
38
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
= authentication plugin
|
|
2
|
+
|
|
3
|
+
This plugin provide the infrastructure for implementing a pluggable
|
|
4
|
+
authentication system. This plugin only provides support for the
|
|
5
|
+
lower-level model functionality to carry out various authentication
|
|
6
|
+
actions. Higher level functions that the user interacts with
|
|
7
|
+
(login pages, forgot my password, etc.) should be implemented by the
|
|
8
|
+
application or a plugin like the login plugin which is designed for
|
|
9
|
+
this purpose.
|
|
10
|
+
|
|
11
|
+
See the #Authentication module for overview info
|
|
12
|
+
|
|
13
|
+
= Installation
|
|
14
|
+
|
|
15
|
+
== Standard Method
|
|
16
|
+
|
|
17
|
+
ruby ./script/plugin install http://authentication.rubyforge.org/svn/trunk
|
|
18
|
+
mv vendor/plugins/trunk vendor/plugins/authentication
|
|
19
|
+
|
|
20
|
+
== Piston Method
|
|
21
|
+
|
|
22
|
+
piston import http://authentication.rubyforge.org/svn/trunk vendor/plugins/authentication
|
|
23
|
+
|
|
24
|
+
= NOTICE
|
|
25
|
+
|
|
26
|
+
Since this plugin does not yet contain many modules that it hopes to
|
|
27
|
+
one day (POP3, etc.) the internal API is not set in stone. I wanted to
|
|
28
|
+
leave a place for plugging in other authentication systems but do not
|
|
29
|
+
yet actually have any need for any besides a salted hash and basic
|
|
30
|
+
tokens. This means as the others are added the internals will probably
|
|
31
|
+
change to account for the variety.
|
|
32
|
+
|
|
33
|
+
= NOTICE
|
|
34
|
+
|
|
35
|
+
Since nobody uses all aspects of this program different people are
|
|
36
|
+
maintaining different parts. If you have any questions about a specific
|
|
37
|
+
authentication module contact correct person:
|
|
38
|
+
|
|
39
|
+
Bart Duchesne <bduc@dyndaco.com> - LDAP and Radius auth modules
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Authentication
|
|
2
|
+
|
|
3
|
+
TODO: Write a gem description
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'authentication'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install authentication
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
TODO: Write usage instructions here
|
|
22
|
+
|
|
23
|
+
## Contributing
|
|
24
|
+
|
|
25
|
+
1. Fork it
|
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
29
|
+
5. Create new Pull Request
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
== Creating the test database
|
|
2
|
+
|
|
3
|
+
The test databases will be created from the info specified in
|
|
4
|
+
test/database.yml. Either change that file to match your database or
|
|
5
|
+
change your database to match that file.
|
|
6
|
+
|
|
7
|
+
== Running with Rake
|
|
8
|
+
|
|
9
|
+
The easiest way to run the unit tests is through Rake. By default
|
|
10
|
+
sqlite will be the database run. Just change your env variable DB to be
|
|
11
|
+
the database adaptor (specified in database.yml) that you want to use.
|
|
12
|
+
The database and permissions must already be setup but the tables will
|
|
13
|
+
be created for you from schema.rb.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
require "bundler/gem_tasks"
|
|
3
|
+
|
|
4
|
+
PKG_NAME = 'authentication'
|
|
5
|
+
PKG_VERSION = 0.02
|
|
6
|
+
|
|
7
|
+
require 'rake/testtask'
|
|
8
|
+
require 'rake/rdoctask'
|
|
9
|
+
require 'rake/packagetask'
|
|
10
|
+
|
|
11
|
+
desc 'Default: run unit tests.'
|
|
12
|
+
task :default => :test
|
|
13
|
+
|
|
14
|
+
desc "Test the #{PKG_NAME} plugin."
|
|
15
|
+
Rake::TestTask.new(:test) do |t|
|
|
16
|
+
t.libs << 'lib'
|
|
17
|
+
t.pattern = 'test/**/*_test.rb'
|
|
18
|
+
t.verbose = true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc "Generate documentation for the #{PKG_NAME} plugin"
|
|
22
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
23
|
+
rdoc.rdoc_dir = 'html'
|
|
24
|
+
rdoc.title = PKG_NAME
|
|
25
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
26
|
+
rdoc.rdoc_files.include('README')
|
|
27
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Rake::PackageTask.new(PKG_NAME, PKG_VERSION) do |pkg|
|
|
31
|
+
pkg.need_tar_gz = true
|
|
32
|
+
pkg.package_files.include('{lib,test}/**/*')
|
|
33
|
+
pkg.package_files.include('README')
|
|
34
|
+
pkg.package_files.include('MIT-LICENSE')
|
|
35
|
+
pkg.package_files.include('Rakefile')
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc 'Tag release'
|
|
39
|
+
task :tag do
|
|
40
|
+
svn_root = "svn+ssh://rubyforge.org/var/svn/#{PKG_NAME}"
|
|
41
|
+
sh %(svn cp #{svn_root}/trunk #{svn_root}/tags/rel-#{PKG_VERSION} -m "Tag #{PKG_NAME} release #{PKG_VERSION}")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
desc 'Push a release to rubyforge'
|
|
45
|
+
task :release => [:package, :tag, :rdoc] do
|
|
46
|
+
|
|
47
|
+
sh %{scp -rq html/* rubyforge.org:/var/www/gforge-projects/#{PKG_NAME}}
|
|
48
|
+
|
|
49
|
+
require 'rubyforge'
|
|
50
|
+
|
|
51
|
+
rubyforge = RubyForge.new
|
|
52
|
+
rubyforge.login
|
|
53
|
+
|
|
54
|
+
package = [PKG_NAME, PKG_VERSION] * '-'
|
|
55
|
+
rubyforge.add_release(PKG_NAME, PKG_NAME, PKG_VERSION, "pkg/#{package}.tar.gz")
|
|
56
|
+
rubyforge.post_news(PKG_NAME, "#{PKG_NAME} #{PKG_VERSION} Released", <<BODY)
|
|
57
|
+
A new version of #{PKG_NAME} has been released. Please see
|
|
58
|
+
http://#{PKG_NAME}.rubyforge.org for full information. See the SCM
|
|
59
|
+
log messages for what has changed.
|
|
60
|
+
BODY
|
|
61
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/authentication/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.authors = ["Micah Geisel"]
|
|
6
|
+
gem.email = ["micah@botandrose.com"]
|
|
7
|
+
gem.description = %q{TODO: Write a gem description}
|
|
8
|
+
gem.summary = %q{TODO: Write a gem summary}
|
|
9
|
+
gem.homepage = ""
|
|
10
|
+
|
|
11
|
+
gem.files = `git ls-files`.split($\)
|
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
14
|
+
gem.name = "authentication"
|
|
15
|
+
gem.require_paths = ["lib"]
|
|
16
|
+
gem.version = Authentication::VERSION
|
|
17
|
+
end
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
require "authentication/version"
|
|
2
|
+
require 'authentication/salted_hash'
|
|
3
|
+
require 'authentication/remember_me'
|
|
4
|
+
require 'authentication/single_token'
|
|
5
|
+
|
|
6
|
+
# This module provides the infrastructure for implementing a pluggable
|
|
7
|
+
# authentication system.
|
|
8
|
+
#
|
|
9
|
+
# This plugin was created in similar spirit to the Authen::Simple CPAN
|
|
10
|
+
# module in Perl. The internal design is different but the goal is the
|
|
11
|
+
# same. A chain of authentication systems can be registered. When a user
|
|
12
|
+
# attempts to authenticate it will cycle through this chain until it can
|
|
13
|
+
# authenticate successfully.
|
|
14
|
+
#
|
|
15
|
+
# This allows you to have multiple authentication attempts (perhaps a
|
|
16
|
+
# ActiveDirectory auth, followed by a POP3 auth, followed by an auth on
|
|
17
|
+
# the local database). This also allows the authentication mechanism to
|
|
18
|
+
# be switched out with mimimal affects on the code.
|
|
19
|
+
#
|
|
20
|
+
# The goal is eventually to include with this plugin a variety of
|
|
21
|
+
# authentication methods with sane defaults. Depending on the
|
|
22
|
+
# environment the authentication method can be easily changed and
|
|
23
|
+
# chained. Right now we only support authenticating with the local
|
|
24
|
+
# database.
|
|
25
|
+
#
|
|
26
|
+
# See Authentication::Macros for usage info
|
|
27
|
+
module Authentication
|
|
28
|
+
|
|
29
|
+
mattr_accessor :default_scheme
|
|
30
|
+
self.default_scheme = {
|
|
31
|
+
:authenticate_with => 'Authentication::SaltedHash',
|
|
32
|
+
:token_with => [
|
|
33
|
+
'Authentication::RememberMe',
|
|
34
|
+
'Authentication::SingleToken'
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module Macros
|
|
39
|
+
|
|
40
|
+
# Should be called on whatever ActiveRecord::Base subclass is
|
|
41
|
+
# being authenticated (i.e. User, Profile, etc.). The common
|
|
42
|
+
# case should look something like:
|
|
43
|
+
#
|
|
44
|
+
# class User < ActiveRecord::Base
|
|
45
|
+
# acts_as_authenticated_user
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# Most of the time you will simply call this method with no
|
|
49
|
+
# arguments. In this case sane defaults will cause the
|
|
50
|
+
# application to authenticate with the local database. These
|
|
51
|
+
# sane defaults will attempt to provide you with the following:
|
|
52
|
+
#
|
|
53
|
+
# * A salted hash password authentication
|
|
54
|
+
# * A single token authentication ideal for URL tokens
|
|
55
|
+
# * A remember me authentication ideal for cookie remember me
|
|
56
|
+
# functionality
|
|
57
|
+
#
|
|
58
|
+
# Those methods will only be provided if the model being
|
|
59
|
+
# authenticated provides the proper fields. See the documentation
|
|
60
|
+
# on those various authentication modules for what is required
|
|
61
|
+
# to make a module work.
|
|
62
|
+
#
|
|
63
|
+
# If you are interested in using other modules then you need to know
|
|
64
|
+
# the following:
|
|
65
|
+
#
|
|
66
|
+
# There are two types of authentication modules.
|
|
67
|
+
# The password auth type has the traditional user/password
|
|
68
|
+
# requirement to authenticate. A user can also typically change
|
|
69
|
+
# their password (although this is not required). An example
|
|
70
|
+
# of this module is the Authentication::SaltedHash module.
|
|
71
|
+
#
|
|
72
|
+
# The other type of module is a token module. A token module
|
|
73
|
+
# typically consist of a user and some sort of token that is
|
|
74
|
+
# not usually user entered. For example a single-signon system
|
|
75
|
+
# may use a token to avoid having to prompt the user. Examples
|
|
76
|
+
# of token modules are the Authentication::SingleToken module
|
|
77
|
+
# and the Authentication::RememberMe module. A token module may
|
|
78
|
+
# authenticate many different tokens for the same user. This allows
|
|
79
|
+
# a token module to assign different valid tokens to different
|
|
80
|
+
# systems so that a token can be revoked if desired. Token
|
|
81
|
+
# authentications often also have a time expiration that a token
|
|
82
|
+
# is valid for. After that time has expired the token no longer
|
|
83
|
+
# works.
|
|
84
|
+
#
|
|
85
|
+
# If you desire to change the modules used this macro method
|
|
86
|
+
# accepts two options in the option hash. The option
|
|
87
|
+
# :authenticate_with is how you specify one or more password auth
|
|
88
|
+
# modules. The option :token_with is how you specify one or more
|
|
89
|
+
# token modules to authenticate with.
|
|
90
|
+
#
|
|
91
|
+
# Both options can accept values in following formats:
|
|
92
|
+
#
|
|
93
|
+
# single module::
|
|
94
|
+
# In this case a single module name is provided to authenticate
|
|
95
|
+
# against. For example:
|
|
96
|
+
# acts_as_authenticated_user :authenticate_with => 'Authentication::POP3'
|
|
97
|
+
# chain of modules::
|
|
98
|
+
# In this case a list of modules will be used to authenticate
|
|
99
|
+
# against. If any of them are a success then the user
|
|
100
|
+
# authenticates. Otherwise the user will not successfully login.
|
|
101
|
+
# For example:
|
|
102
|
+
# acts_as_authenticated_user :authenticate_with =>
|
|
103
|
+
# ['Authentication::ActiveDirectory', 'Authentication::POP3']
|
|
104
|
+
# module with arguments::
|
|
105
|
+
# In this case a single module is being used but it has arguments
|
|
106
|
+
# which are passed to the module when instantated. For example:
|
|
107
|
+
# acts_as_authenticated_user :authenticate_with =>
|
|
108
|
+
# {'Authentication::POP3' => ['pop3.example.org', 110]}
|
|
109
|
+
# In this case the code will call
|
|
110
|
+
# Authentication::POP3.new('pop3.example.org', 110) when
|
|
111
|
+
# instantionating the object. More than likely the authentication
|
|
112
|
+
# module will just have one argument which is an option hash. In
|
|
113
|
+
# this case you might initialize that module like the following:
|
|
114
|
+
# acts_as_authenticated_user :authenticate_with =>
|
|
115
|
+
# {'Authentication::POP3' =>
|
|
116
|
+
# {:server => 'pop3.example.org', :port => 110}}
|
|
117
|
+
# chain of modules with arguments::
|
|
118
|
+
# You can also chain modules and use arguments. In this case you
|
|
119
|
+
# just pass the method an array of hashes. For example:
|
|
120
|
+
# acts_as_authenticated_user :authenticate_with =>
|
|
121
|
+
# [
|
|
122
|
+
# {'Authentication::POP3' =>
|
|
123
|
+
# {:server => 'pop3.example.com', :port => 5000}},
|
|
124
|
+
# {'Autnentication::ActiveDirectory' =>
|
|
125
|
+
# {:server => 'ad.example.com'}}
|
|
126
|
+
# ]
|
|
127
|
+
#
|
|
128
|
+
# If you wish to provide a different scheme depending on the
|
|
129
|
+
# environment (i.e. production vs. development) then you can
|
|
130
|
+
# assign your argument to the Module method "default_scheme"
|
|
131
|
+
# on the Authentication module in the proper environment file.
|
|
132
|
+
# For example:
|
|
133
|
+
#
|
|
134
|
+
# Authentication.default_scheme = {
|
|
135
|
+
# :authenticate_with => 'Authentication::POP3',
|
|
136
|
+
# :token_with => []
|
|
137
|
+
# }
|
|
138
|
+
#
|
|
139
|
+
# This would authenticate with POP3 and not provide any token
|
|
140
|
+
# mechanism.
|
|
141
|
+
def acts_as_authenticated_user(options={})
|
|
142
|
+
options.reverse_merge! Authentication.default_scheme
|
|
143
|
+
|
|
144
|
+
# Process arguments and store in instantiated auth modules
|
|
145
|
+
{
|
|
146
|
+
:authenticate_with => :authentication_modules,
|
|
147
|
+
:token_with => :token_modules,
|
|
148
|
+
}.each do |option, mod_type|
|
|
149
|
+
mods = [options[option]].flatten.compact
|
|
150
|
+
mods = mods.inject([]) do |memo, mod|
|
|
151
|
+
if mod.is_a? Hash
|
|
152
|
+
mod.each do |m, args|
|
|
153
|
+
args = [args] unless args.is_a? Array
|
|
154
|
+
memo << m.constantize.new(*args)
|
|
155
|
+
end
|
|
156
|
+
else
|
|
157
|
+
memo << mod.constantize.new
|
|
158
|
+
end
|
|
159
|
+
memo
|
|
160
|
+
end
|
|
161
|
+
class_attribute mod_type
|
|
162
|
+
private
|
|
163
|
+
self.send "#{mod_type.to_s}=".to_sym, mods
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
include Authentication::InstanceMethods
|
|
167
|
+
if method_defined?(:password=) # TODO rather have these in the client class?
|
|
168
|
+
before_validation :assign_password
|
|
169
|
+
# after_save :reset_password
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Methods that are mixed into the authenticated object as instance
|
|
175
|
+
# methods.
|
|
176
|
+
module InstanceMethods
|
|
177
|
+
# If the given password will authenticate the object using
|
|
178
|
+
# the chain of authentication modules configured then true is
|
|
179
|
+
# returned. Otherwise false is returned. Both token modules
|
|
180
|
+
# and password auth modules are checked.
|
|
181
|
+
def authenticate(password)
|
|
182
|
+
mods = [
|
|
183
|
+
self.class.token_modules,
|
|
184
|
+
self.class.authentication_modules
|
|
185
|
+
].flatten.compact
|
|
186
|
+
mods.each {|mod| return true if mod.authenticate self, password}
|
|
187
|
+
false
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Will create a new token that can be used to login without a
|
|
191
|
+
# password (or basically you can consider this just a really
|
|
192
|
+
# complex password). If this token is passed into the authenticate
|
|
193
|
+
# method then true should be returned. This method takes the
|
|
194
|
+
# following three arguments:
|
|
195
|
+
#
|
|
196
|
+
# name:: Depending on the token modules used will determine if this
|
|
197
|
+
# argument has any meaning. Sometimes a token module will only
|
|
198
|
+
# respond to one name. Other times it will respond to any name.
|
|
199
|
+
# The reason for this parameter is to allow a token module to
|
|
200
|
+
# have multiple tokens it accepts so that it can then later revoke
|
|
201
|
+
# only some tokens if needed. For example a site trying to provide
|
|
202
|
+
# single-signon service may give out a token for each foreign system
|
|
203
|
+
# that interacts with it. Then later when that token is used the
|
|
204
|
+
# token module can note what system it authenticated for and if at
|
|
205
|
+
# some point it stops trusting the foreign system it can revoke
|
|
206
|
+
# that token without revoking the other tokens it has assigned.
|
|
207
|
+
#
|
|
208
|
+
# An expiration date can also be given although not all token
|
|
209
|
+
# modules will do anythign with this expiration date.
|
|
210
|
+
#
|
|
211
|
+
# NOTE: If the token generated is attached to the model (default
|
|
212
|
+
# behavior) then the token may not actually valid until the model
|
|
213
|
+
# has been saved. To be sure always call save after getting a new
|
|
214
|
+
# token if you want to be sure to keep that token.
|
|
215
|
+
def assign_token(name, expire=3.days.from_now)
|
|
216
|
+
self.class.token_modules.each do |mod|
|
|
217
|
+
token = mod.assign_token self, name, expire if mod.respond_to? :assign_token
|
|
218
|
+
return token if token
|
|
219
|
+
end
|
|
220
|
+
nil
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def assign_token!(*args)
|
|
224
|
+
assign_token(*args).tap do |token|
|
|
225
|
+
save!
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Will assign a new password that will by crypted on when the
|
|
230
|
+
# model is saved. If multiple password auth modules are configured
|
|
231
|
+
# then each one will be given a copy of this new password. This
|
|
232
|
+
# could be a useful method of syncing your passwords across
|
|
233
|
+
# different systems. Not all password auth modules support the
|
|
234
|
+
# ability to change passwords.
|
|
235
|
+
attr_writer :password
|
|
236
|
+
|
|
237
|
+
# For confirmation validation
|
|
238
|
+
# previously this was private, which seems to cause validates_presence_of :password
|
|
239
|
+
# to fail, therefor made it public
|
|
240
|
+
attr_reader :password
|
|
241
|
+
|
|
242
|
+
private
|
|
243
|
+
|
|
244
|
+
# before_validation callback let authentication modules set password.
|
|
245
|
+
# If a module does not allow setting a password it should just not implement
|
|
246
|
+
# the assign_password function.
|
|
247
|
+
#
|
|
248
|
+
# NOTE: If password is blank nothing is done. This is to prevent
|
|
249
|
+
# the common case of empty passwords on a form from blanking out a
|
|
250
|
+
# password. The side effect is that you cannot specifically have a
|
|
251
|
+
# blank password.
|
|
252
|
+
def assign_password
|
|
253
|
+
return true if password.blank?
|
|
254
|
+
self.class.authentication_modules.each do |mod|
|
|
255
|
+
mod.assign_password self, password if mod.respond_to? :assign_password
|
|
256
|
+
end
|
|
257
|
+
true
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Callback after save to ensure cleartext password is deleted
|
|
261
|
+
def reset_password
|
|
262
|
+
self.password = nil
|
|
263
|
+
self.password_confirmation = nil if respond_to? :password_confirmation
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
require 'authentication/active_record_extensions'
|
|
269
|
+
ActiveRecord::Base.extend Authentication::Macros
|
|
270
|
+
|