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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README +114 -0
  6. data/README.md +29 -0
  7. data/Rakefile +2 -0
  8. data/adva_user.gemspec +17 -0
  9. data/app/controllers/admin/base_account_controller.rb +13 -0
  10. data/app/controllers/admin/users_controller.rb +95 -0
  11. data/app/controllers/password_controller.rb +36 -0
  12. data/app/controllers/session_controller.rb +30 -0
  13. data/app/helpers/users_helper.rb +27 -0
  14. data/app/models/account.rb +7 -0
  15. data/app/models/membership.rb +16 -0
  16. data/app/models/password_mailer.rb +43 -0
  17. data/app/models/user.rb +106 -0
  18. data/app/views/admin/users/_form.html.erb +29 -0
  19. data/app/views/admin/users/_sidebar.html.erb +8 -0
  20. data/app/views/admin/users/edit.html.erb +7 -0
  21. data/app/views/admin/users/index.html.erb +13 -0
  22. data/app/views/admin/users/new.html.erb +5 -0
  23. data/app/views/admin/users/show.html.erb +27 -0
  24. data/app/views/layouts/login.html.erb +24 -0
  25. data/app/views/password/edit.html.erb +14 -0
  26. data/app/views/password/new.html.erb +13 -0
  27. data/app/views/password_mailer/reset_password_email.html.erb +3 -0
  28. data/app/views/password_mailer/updated_password_email.html.erb +1 -0
  29. data/app/views/session/new.html.erb +17 -0
  30. data/config/initializers/menus.rb +25 -0
  31. data/config/routes.rb +14 -0
  32. data/db/migrate/20080402000001_create_users_table.rb +33 -0
  33. data/db/migrate/20080402000005_create_memberships_table.rb +13 -0
  34. data/db/migrate/20090625124502_create_accounts.rb +13 -0
  35. data/db/migrate/20090625133231_add_account_to_user.rb +10 -0
  36. data/lib/action_controller/authenticate_anonymous.rb +70 -0
  37. data/lib/action_controller/authenticate_user.rb +201 -0
  38. data/lib/active_record/belongs_to_author.rb +37 -0
  39. data/lib/adva_user.rb +28 -0
  40. data/lib/adva_user/version.rb +3 -0
  41. data/lib/login/helper_integration.rb +11 -0
  42. data/lib/login/mail_config.rb +39 -0
  43. data/test/contexts.rb +42 -0
  44. data/test/fixtures.rb +18 -0
  45. data/test/functional/admin/users_controller_test.rb +176 -0
  46. data/test/functional/password_controller_test.rb +96 -0
  47. data/test/functional/session_controller_test.rb +1 -0
  48. data/test/functional/user_controller_test.rb +95 -0
  49. data/test/integration/anonymous_login_test.rb +39 -0
  50. data/test/integration/edit_user_test.rb +44 -0
  51. data/test/integration/memberships_test.rb +52 -0
  52. data/test/integration/user_deletion_test.rb +27 -0
  53. data/test/integration/user_login_test.rb +53 -0
  54. data/test/integration/user_login_with_remember_me_test.rb +20 -0
  55. data/test/integration/user_registration_test.rb +64 -0
  56. data/test/test_helper.rb +1 -0
  57. data/test/unit/cells/user_cell_test.rb +13 -0
  58. data/test/unit/helpers/users_helper_test.rb +52 -0
  59. data/test/unit/models/account_test.rb +21 -0
  60. data/test/unit/models/anonymous_test.rb +54 -0
  61. data/test/unit/models/password_mailer_test.rb +26 -0
  62. data/test/unit/models/user_mailer_test.rb +16 -0
  63. data/test/unit/models/user_test.rb +173 -0
  64. data/vendor/gems/authentication/.gitignore +17 -0
  65. data/vendor/gems/authentication/Gemfile +4 -0
  66. data/vendor/gems/authentication/LICENSE +22 -0
  67. data/vendor/gems/authentication/MIT-LICENSE +38 -0
  68. data/vendor/gems/authentication/README +39 -0
  69. data/vendor/gems/authentication/README.md +29 -0
  70. data/vendor/gems/authentication/RUNNING_UNIT_TESTS +13 -0
  71. data/vendor/gems/authentication/Rakefile +61 -0
  72. data/vendor/gems/authentication/authentication.gemspec +17 -0
  73. data/vendor/gems/authentication/lib/authentication.rb +270 -0
  74. data/vendor/gems/authentication/lib/authentication/active_record_extensions.rb +11 -0
  75. data/vendor/gems/authentication/lib/authentication/bogus.rb +13 -0
  76. data/vendor/gems/authentication/lib/authentication/hash_helper.rb +26 -0
  77. data/vendor/gems/authentication/lib/authentication/ldap.rb +49 -0
  78. data/vendor/gems/authentication/lib/authentication/remember_me.rb +52 -0
  79. data/vendor/gems/authentication/lib/authentication/salted_hash.rb +53 -0
  80. data/vendor/gems/authentication/lib/authentication/single_token.rb +53 -0
  81. data/vendor/gems/authentication/lib/authentication/version.rb +3 -0
  82. data/vendor/gems/authentication/lib/radius/dictionary +207 -0
  83. data/vendor/gems/authentication/test_backup/abstract_unit.rb +30 -0
  84. data/vendor/gems/authentication/test_backup/active_record_extension_test.rb +17 -0
  85. data/vendor/gems/authentication/test_backup/authentication_test.rb +231 -0
  86. data/vendor/gems/authentication/test_backup/database.yml +12 -0
  87. data/vendor/gems/authentication/test_backup/fixtures/user.rb +3 -0
  88. data/vendor/gems/authentication/test_backup/fixtures/users.yml +3 -0
  89. data/vendor/gems/authentication/test_backup/options_test.rb +100 -0
  90. data/vendor/gems/authentication/test_backup/remember_me_test.rb +41 -0
  91. data/vendor/gems/authentication/test_backup/salted_hash_test.rb +38 -0
  92. data/vendor/gems/authentication/test_backup/schema.rb +10 -0
  93. data/vendor/gems/authentication/test_backup/single_token_test.rb +44 -0
  94. data/vendor/gems/authentication/test_backup/test_helper.rb +8 -0
  95. metadata +157 -0
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in authentication.gemspec
4
+ gemspec
@@ -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
+