devise 1.1.pre3 → 1.1.pre4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- data/README.rdoc +70 -52
- data/app/controllers/devise/registrations_controller.rb +6 -6
- data/lib/devise.rb +79 -113
- data/lib/devise/controllers/internal_helpers.rb +2 -1
- data/lib/devise/hooks/rememberable.rb +3 -1
- data/lib/devise/hooks/trackable.rb +2 -13
- data/lib/devise/mapping.rb +24 -17
- data/lib/devise/models.rb +0 -11
- data/lib/devise/models/trackable.rb +14 -0
- data/lib/devise/modules.rb +25 -0
- data/lib/devise/rails/routes.rb +9 -6
- data/lib/devise/schema.rb +6 -5
- data/lib/devise/strategies/authenticatable.rb +1 -1
- data/lib/devise/version.rb +1 -1
- data/test/devise_test.rb +3 -4
- data/test/mapping_test.rb +10 -10
- metadata +3 -2
data/README.rdoc
CHANGED
@@ -9,24 +9,27 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
|
9
9
|
|
10
10
|
Right now it's composed of 12 modules:
|
11
11
|
|
12
|
-
* Authenticatable:
|
13
|
-
* Token Authenticatable: validates authenticity of a user while signing in using an authentication token (also known as "single access token").
|
12
|
+
* Authenticatable: encrypts a password and validates the authenticity of a user while signing in.
|
13
|
+
* Token Authenticatable: validates the authenticity of a user while signing in using an authentication token (also known as "single access token").
|
14
14
|
* HttpAuthenticatable: sign in users using basic HTTP authentication.
|
15
|
-
* Confirmable:
|
16
|
-
* Recoverable:
|
15
|
+
* Confirmable: sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
16
|
+
* Recoverable: resets the user password and sends reset instructions.
|
17
17
|
* Registerable: handles signing up users through a registration process.
|
18
|
-
* Rememberable: manages generating and clearing token for
|
19
|
-
* Trackable: tracks sign in count, timestamps and
|
20
|
-
* Timeoutable: expires sessions
|
21
|
-
* Validatable:
|
22
|
-
* Lockable:
|
23
|
-
* Activatable: if you need to activate accounts by
|
18
|
+
* Rememberable: manages generating and clearing a token for remembering the user from a saved cookie.
|
19
|
+
* Trackable: tracks sign in count, timestamps and IP address.
|
20
|
+
* Timeoutable: expires sessions that have no activity in a specified period of time.
|
21
|
+
* Validatable: provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
22
|
+
* Lockable: locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
23
|
+
* Activatable: use this module if you need to activate accounts by means other than confirmation.
|
24
24
|
|
25
|
-
|
25
|
+
== Examples
|
26
|
+
|
27
|
+
* Example application using Devise at http://github.com/plataformatec/devise_example
|
28
|
+
* Example Rails 2.3 web app combining subdomains with Devise at http://github.com/fortuity/subdomain-authentication
|
26
29
|
|
27
30
|
== Dependencies
|
28
31
|
|
29
|
-
Devise is based on Warden (http://github.com/hassox/warden), a Rack Authentication Framework
|
32
|
+
Devise is based on Warden (http://github.com/hassox/warden), a Rack Authentication Framework. You need to install Warden as a gem. Please ensure you have it installed in order to use Devise (see installation below).
|
30
33
|
|
31
34
|
== Installation
|
32
35
|
|
@@ -34,7 +37,7 @@ Devise master branch now supports Rails 3 and is NOT backward compatible. You ca
|
|
34
37
|
|
35
38
|
sudo gem install devise --version=1.1.pre
|
36
39
|
|
37
|
-
After installing
|
40
|
+
After installing the Warden and Devise gems, you need to configure the gems inside your gemfile:
|
38
41
|
|
39
42
|
gem 'warden'
|
40
43
|
gem 'devise'
|
@@ -61,15 +64,15 @@ Or checkout from the v1.0 branch:
|
|
61
64
|
|
62
65
|
This is a walkthrough with all steps you need to setup a devise resource, including model, migration, route files, and optional configuration. You MUST also check out the *Generators* section below to help you start.
|
63
66
|
|
64
|
-
Devise must be set up within the model (or models) you want to use
|
67
|
+
Devise must be set up within the model (or models) you want to use. Devise routes must be created inside your config/routes.rb file.
|
65
68
|
|
66
|
-
We're assuming here you want a User model with some modules, as outlined below:
|
69
|
+
We're assuming here you want a User model with some Devise modules, as outlined below:
|
67
70
|
|
68
71
|
class User < ActiveRecord::Base
|
69
72
|
devise :authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
|
70
73
|
end
|
71
74
|
|
72
|
-
After you choose which modules to use, you need to
|
75
|
+
After you choose which modules to use, you need to set up your migrations. Luckily, Devise has some helpers to save you from this boring work:
|
73
76
|
|
74
77
|
create_table :users do |t|
|
75
78
|
t.authenticatable
|
@@ -80,53 +83,53 @@ After you choose which modules to use, you need to setup your migrations. Luckil
|
|
80
83
|
t.timestamps
|
81
84
|
end
|
82
85
|
|
83
|
-
|
86
|
+
Devise doesn't use _attr_accessible_ or _attr_protected_ inside its modules, so be sure to define attributes as accessible or protected in your model.
|
84
87
|
|
85
|
-
|
88
|
+
Configure your routes after setting up your model. Open your config/routes.rb file and add:
|
86
89
|
|
87
90
|
devise_for :users
|
88
91
|
|
89
|
-
This
|
92
|
+
This will use your User model to create a set of needed routes (you can see them by running `rake routes`).
|
90
93
|
|
91
|
-
|
94
|
+
Options for configuring your routes include :class_name (to set the class for that route), :path_prefix, :as and :path_names, where the last two have the same meaning as in common routes. The available :path_names are:
|
92
95
|
|
93
|
-
devise_for :users, :as => "usuarios", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock' }
|
96
|
+
devise_for :users, :as => "usuarios", :path_names => { :sign_in => 'login', :sign_out => 'logout', :sign_up => 'register', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock' }
|
94
97
|
|
95
|
-
Be sure to check devise_for documentation for
|
98
|
+
Be sure to check devise_for documentation for details.
|
96
99
|
|
97
|
-
After
|
100
|
+
After creating your models and routes, run your migrations, and you are ready to go! But don't stop reading here, we still have a lot to tell you:
|
98
101
|
|
99
102
|
== Controller filters and helpers
|
100
103
|
|
101
|
-
Devise
|
104
|
+
Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_filter:
|
102
105
|
|
103
106
|
before_filter :authenticate_user!
|
104
107
|
|
105
|
-
To verify if a user is signed in,
|
108
|
+
To verify if a user is signed in, use the following helper:
|
106
109
|
|
107
110
|
user_signed_in?
|
108
111
|
|
109
|
-
|
112
|
+
For the current signed-in user, this helper is available:
|
110
113
|
|
111
114
|
current_user
|
112
115
|
|
113
|
-
You
|
116
|
+
You can access the session for this scope:
|
114
117
|
|
115
118
|
user_session
|
116
119
|
|
117
|
-
After signing in a user, confirming
|
120
|
+
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. Example: For a :user resource, it will use user_root_path if it exists, otherwise default root_path will be used. This means that you need to set the root inside your routes:
|
118
121
|
|
119
122
|
root :to => "home"
|
120
123
|
|
121
|
-
You can also overwrite after_sign_in_path_for and after_sign_out_path_for to customize
|
124
|
+
You can also overwrite after_sign_in_path_for and after_sign_out_path_for to customize your redirect hooks.
|
122
125
|
|
123
|
-
Finally, you
|
126
|
+
Finally, you need to set up default url options for the mailer in each environment. Here is the configuration for config/environments/development.rb:
|
124
127
|
|
125
128
|
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
|
126
129
|
|
127
130
|
== Tidying up
|
128
131
|
|
129
|
-
Devise
|
132
|
+
Devise allows you to set up as many roles as you want. For example, you may have a User model and also want an Admin model with just authentication, trackable, lockable and timeoutable features and no confirmation or password-recovery features. Just follow these steps:
|
130
133
|
|
131
134
|
# Create a migration with the required fields
|
132
135
|
create_table :admins do |t|
|
@@ -151,35 +154,37 @@ Devise let's you setup as many roles as you want, so let's say you already have
|
|
151
154
|
|
152
155
|
== Generators
|
153
156
|
|
154
|
-
Devise
|
157
|
+
Devise has generators to help you get started:
|
155
158
|
|
156
159
|
rails generate devise_install
|
157
160
|
|
158
|
-
This will generate an initializer, with a description of all configuration values.
|
161
|
+
This will generate an initializer, with a description of all configuration values.
|
162
|
+
|
163
|
+
You can also generate models:
|
159
164
|
|
160
165
|
rails generate devise Model
|
161
166
|
|
162
|
-
|
167
|
+
This will create a model named "Model" configured with default Devise modules and attr_accessible set for default fields. The generator will also create the migration and configure your routes for Devise.
|
163
168
|
|
164
169
|
== Model configuration
|
165
170
|
|
166
|
-
The devise method in your models also
|
171
|
+
The devise method in your models also accepts some options to configure its modules. For example, you can choose which encryptor to use in authenticatable:
|
167
172
|
|
168
173
|
devise :authenticatable, :confirmable, :recoverable, :encryptor => :bcrypt
|
169
174
|
|
170
|
-
Besides :encryptor, you can
|
175
|
+
Besides :encryptor, you can define :pepper, :stretches, :confirm_within, :remember_for, :timeout_in, :unlock_in and other values. For details, see the initializer file that was created when you invoked the devise_install generator described above.
|
171
176
|
|
172
177
|
== Configuring controllers and views
|
173
178
|
|
174
|
-
|
179
|
+
We built Devise to help you quickly develop an application that uses authentication. We don't want to be in your way when you need to customize it.
|
175
180
|
|
176
|
-
Since
|
181
|
+
Since Devise is an engine, all its default views are packaged inside the gem. The default views will get you started but you may want to customize them. Devise has a generator to copy the default views to your application. After they've been copied to your application, you can make changes as required:
|
177
182
|
|
178
183
|
rails generate devise_views
|
179
184
|
|
180
|
-
If you have more than one role in your application, you will notice that Devise uses the same views for all roles
|
185
|
+
If you have more than one role in your application (such as "user" and "admin"), you will notice that Devise uses the same views for all roles. You may need different views for each role. Devise offers an easy way to customize views for each role. Just set config.scoped_views to "true" inside "config/initializers/devise.rb".
|
181
186
|
|
182
|
-
After doing so you will be able to have views based on the scope like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will
|
187
|
+
After doing so you will be able to have views based on the scope like "users/sessions/new" and "admins/sessions/new". If no view is found within the scope, Devise will use the default view at "devise/sessions/new".
|
183
188
|
|
184
189
|
Finally, if the customization at the views level is not enough, you can customize each controller by following these steps:
|
185
190
|
|
@@ -192,13 +197,13 @@ Finally, if the customization at the views level is not enough, you can customiz
|
|
192
197
|
|
193
198
|
devise_for :admins, :controllers => { :sessions = "admin/sessions" }
|
194
199
|
|
195
|
-
3) And finally, since we changed the controller, it won't use "devise/sessions"
|
200
|
+
3) And finally, since we changed the controller, it won't use the "devise/sessions" views, so remember to copy "devise/sessions" to "admin/sessions".
|
196
201
|
|
197
|
-
Remember that Devise uses flash messages to let users know if sign in
|
202
|
+
Remember that Devise uses flash messages to let users know if sign in was successful or failed. Devise expects your application to call "flash[:notice]" and "flash[:alert]" as appropriate.
|
198
203
|
|
199
204
|
== I18n
|
200
205
|
|
201
|
-
Devise uses flash messages with I18n with the flash keys :success and :failure. To customize your app, you can
|
206
|
+
Devise uses flash messages with I18n with the flash keys :success and :failure. To customize your app, you can set up your locale file:
|
202
207
|
|
203
208
|
en:
|
204
209
|
devise:
|
@@ -215,7 +220,7 @@ You can also create distinct messages based on the resource you've configured us
|
|
215
220
|
admin:
|
216
221
|
signed_in: 'Hello admin!'
|
217
222
|
|
218
|
-
Devise mailer uses the same pattern to create subject messages:
|
223
|
+
The Devise mailer uses the same pattern to create subject messages:
|
219
224
|
|
220
225
|
en:
|
221
226
|
devise:
|
@@ -243,15 +248,15 @@ You can include the Devise Test Helpers in all of your tests by adding the follo
|
|
243
248
|
include Devise::TestHelpers
|
244
249
|
end
|
245
250
|
|
246
|
-
Do not use such helpers for integration tests
|
251
|
+
Do not use such helpers for integration tests such as Cucumber or Webrat. Instead, fill in the form or explicitly set the user in session. For more tips, check the wiki (http://wiki.github.com/plataformatec/devise).
|
247
252
|
|
248
253
|
== Migrating from other solutions
|
249
254
|
|
250
|
-
Devise implements encryption strategies for Clearance, Authlogic and Restful-Authentication. To make use of
|
255
|
+
Devise implements encryption strategies for Clearance, Authlogic and Restful-Authentication. To make use of these strategies, set the desired encryptor in the encryptor initializer config option. You might also need to rename your encrypted password and salt columns to match Devise's fields (encrypted_password and password_salt).
|
251
256
|
|
252
257
|
== Other ORMs
|
253
258
|
|
254
|
-
Devise supports
|
259
|
+
Devise supports ActiveRecord (by default) and MongoMapper. We offer experimental Datamapper support (with the limitation that the Devise test suite does not run completely with Datamapper). To choose other ORM, you just need to configure it in the initializer file.
|
255
260
|
|
256
261
|
== TODO
|
257
262
|
|
@@ -264,15 +269,28 @@ Please refer to TODO file.
|
|
264
269
|
|
265
270
|
== Contributors
|
266
271
|
|
267
|
-
We have a long
|
272
|
+
We have a long list of valued contributors. See the CHANGELOG or do `git shortlog -s -n` in the cloned repository.
|
273
|
+
|
274
|
+
== Related Applications
|
275
|
+
|
276
|
+
* http://github.com/scambra/devise_invitable adds support to Devise for sending invitations by email.
|
277
|
+
|
278
|
+
* http://github.com/grimen/devise_facebook_connectable adds support for Facebook Connect authentication, and optionally fetching user info from Facebook in the same step.
|
268
279
|
|
269
280
|
== Bugs and Feedback
|
270
281
|
|
271
|
-
If you discover any bugs
|
272
|
-
|
282
|
+
If you discover any bugs, please create an issue on GitHub.
|
283
|
+
|
284
|
+
http://github.com/plataformatec/devise/issues
|
285
|
+
|
286
|
+
For support, send an e-mail to the mailing list.
|
287
|
+
|
288
|
+
http://groups.google.com/group/plataformatec-devise
|
289
|
+
|
290
|
+
See the wiki for additional documentation and support.
|
273
291
|
|
274
|
-
http://github.com/plataformatec/devise/issues |
|
275
|
-
http://groups.google.com/group/plataformatec-devise |
|
276
292
|
http://wiki.github.com/plataformatec/devise/
|
277
293
|
|
294
|
+
== License
|
295
|
+
|
278
296
|
MIT License. Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
@@ -30,28 +30,28 @@ class Devise::RegistrationsController < ApplicationController
|
|
30
30
|
|
31
31
|
# PUT /resource
|
32
32
|
def update
|
33
|
-
if
|
33
|
+
if resource.update_with_password(params[resource_name])
|
34
34
|
set_flash_message :notice, :updated
|
35
35
|
redirect_to after_sign_in_path_for(self.resource)
|
36
36
|
else
|
37
|
-
build_resource
|
38
|
-
send(:"current_#{resource_name}").reload
|
39
37
|
render_with_scope :edit
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
43
41
|
# DELETE /resource
|
44
42
|
def destroy
|
45
|
-
|
43
|
+
resource.destroy
|
46
44
|
set_flash_message :notice, :destroyed
|
47
45
|
sign_out_and_redirect(self.resource)
|
48
46
|
end
|
49
47
|
|
50
48
|
protected
|
51
49
|
|
52
|
-
# Authenticates the current scope and
|
50
|
+
# Authenticates the current scope and gets a copy of the current resource.
|
51
|
+
# We need to use a copy because we don't want actions like update changing
|
52
|
+
# the current user in place.
|
53
53
|
def authenticate_scope!
|
54
54
|
send(:"authenticate_#{resource_name}!")
|
55
|
-
self.resource = send(:"current_#{resource_name}")
|
55
|
+
self.resource = resource_class.find(send(:"current_#{resource_name}").id)
|
56
56
|
end
|
57
57
|
end
|
data/lib/devise.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Devise
|
2
2
|
autoload :FailureApp, 'devise/failure_app'
|
3
|
-
autoload :Models, 'devise/models'
|
4
3
|
autoload :Schema, 'devise/schema'
|
5
4
|
autoload :TestHelpers, 'devise/test_helpers'
|
6
5
|
|
@@ -21,39 +20,17 @@ module Devise
|
|
21
20
|
autoload :Sha1, 'devise/encryptors/sha1'
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
# The ones which can sign out after
|
33
|
-
ALL.push :activatable, :confirmable, :lockable, :timeoutable
|
34
|
-
|
35
|
-
# Stats for last, so we make sure the user is really signed in
|
36
|
-
ALL.push :trackable
|
37
|
-
|
38
|
-
# Maps controller names to devise modules.
|
39
|
-
CONTROLLERS = {
|
40
|
-
:sessions => [:authenticatable, :token_authenticatable],
|
41
|
-
:passwords => [:recoverable],
|
42
|
-
:confirmations => [:confirmable],
|
43
|
-
:registrations => [:registerable],
|
44
|
-
:unlocks => [:lockable]
|
45
|
-
}
|
46
|
-
|
47
|
-
# Routes for generating url helpers.
|
48
|
-
ROUTES = [:session, :password, :confirmation, :registration, :unlock]
|
49
|
-
|
50
|
-
STRATEGIES = [:rememberable, :http_authenticatable, :token_authenticatable, :authenticatable]
|
23
|
+
# Constants which holds devise configuration for extensions. Those should
|
24
|
+
# not be modified by the "end user".
|
25
|
+
ALL = []
|
26
|
+
CONTROLLERS = {}
|
27
|
+
ROUTES = []
|
28
|
+
STRATEGIES = []
|
29
|
+
FLASH_MESSAGES = [:unauthenticated]
|
51
30
|
|
31
|
+
# True values used to check params
|
52
32
|
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
53
33
|
|
54
|
-
# Maps the messages types that are used in flash message.
|
55
|
-
FLASH_MESSAGES = [:unauthenticated, :unconfirmed, :invalid, :invalid_token, :timeout, :inactive, :locked]
|
56
|
-
|
57
34
|
# Declare encryptors length which are used in migrations.
|
58
35
|
ENCRYPTORS_LENGTH = {
|
59
36
|
:sha1 => 40,
|
@@ -142,101 +119,90 @@ module Devise
|
|
142
119
|
mattr_accessor :http_authentication_realm
|
143
120
|
@@http_authentication_realm = "Application"
|
144
121
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
122
|
+
# Default way to setup Devise. Run rails generate devise_install to create
|
123
|
+
# a fresh initializer with all configuration values.
|
124
|
+
def self.setup
|
125
|
+
yield self
|
126
|
+
end
|
151
127
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
128
|
+
# Make Devise aware of an 3rd party Devise-module. For convenience.
|
129
|
+
#
|
130
|
+
# == Options:
|
131
|
+
#
|
132
|
+
# +strategy+ - Boolean value representing if this module got a custom *strategy*.
|
133
|
+
# Default is +false+. Note: Devise will auto-detect this in such case if this is true.
|
134
|
+
# +model+ - String representing the load path to a custom *model* for this module (to autoload.)
|
135
|
+
# Default is +nil+ (i.e. +false+).
|
136
|
+
# +controller+ - Symbol representing the name of an exisiting or custom *controller* for this module.
|
137
|
+
# Default is +nil+ (i.e. +false+).
|
138
|
+
# +route+ - Symbol representing the named *router* helper for this module.
|
139
|
+
# Default is +nil+ (i.e. +false+).
|
140
|
+
# +flash+ - Symbol representing the *flash messages* used by this helper.
|
141
|
+
# Default is +nil+ (i.e. +false+).
|
142
|
+
#
|
143
|
+
# == Examples:
|
144
|
+
#
|
145
|
+
# Devise.add_module(:party_module)
|
146
|
+
# Devise.add_module(:party_module, :strategy => true, :controller => :sessions)
|
147
|
+
# Devise.add_module(:party_module, :autoload => 'party_module/model')
|
148
|
+
#
|
149
|
+
def self.add_module(module_name, options = {})
|
150
|
+
ALL << module_name
|
151
|
+
options.assert_valid_keys(:strategy, :model, :controller, :route, :flash)
|
152
|
+
|
153
|
+
{ :strategy => STRATEGIES, :flash => FLASH_MESSAGES, :route => ROUTES }.each do |key, value|
|
154
|
+
next unless options[key]
|
155
|
+
name = (options[key] == true ? module_name : options[key])
|
156
|
+
value.unshift(name) unless value.include?(name)
|
156
157
|
end
|
157
158
|
|
158
|
-
|
159
|
-
|
160
|
-
ActiveSupport::Deprecation.warn "Devise.default_url_options and config.default_url_options are deprecated. " <<
|
161
|
-
"Just modify ApplicationController.default_url_options and Devise will automatically pick it up"
|
159
|
+
if options[:controller]
|
160
|
+
Devise::CONTROLLERS[module_name] = options[:controller].to_sym
|
162
161
|
end
|
163
162
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
# Devise.initialize do |config|
|
168
|
-
# config.confirm_within = 2.days
|
169
|
-
#
|
170
|
-
# config.warden do |manager|
|
171
|
-
# # Configure warden to use other strategies, like oauth.
|
172
|
-
# manager.oauth(:twitter)
|
173
|
-
# end
|
174
|
-
# end
|
175
|
-
def warden(&block)
|
176
|
-
@warden_config = block
|
163
|
+
if options[:model]
|
164
|
+
model_path = (options[:model] == true ? "devise/models/#{module_name}" : options[:model])
|
165
|
+
Devise::Models.send(:autoload, module_name.to_s.camelize.to_sym, model_path)
|
177
166
|
end
|
178
167
|
|
179
|
-
|
180
|
-
|
181
|
-
def configure_warden(config) #:nodoc:
|
182
|
-
config.default_strategies *Devise::STRATEGIES
|
183
|
-
config.failure_app = Devise::FailureApp
|
184
|
-
config.silence_missing_strategies!
|
185
|
-
config.default_scope = Devise.default_scope
|
168
|
+
Devise::Mapping.register module_name
|
169
|
+
end
|
186
170
|
|
187
|
-
|
188
|
-
|
189
|
-
|
171
|
+
# Sets warden configuration using a block that will be invoked on warden
|
172
|
+
# initialization.
|
173
|
+
#
|
174
|
+
# Devise.initialize do |config|
|
175
|
+
# config.confirm_within = 2.days
|
176
|
+
#
|
177
|
+
# config.warden do |manager|
|
178
|
+
# # Configure warden to use other strategies, like oauth.
|
179
|
+
# manager.oauth(:twitter)
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
def self.warden(&block)
|
183
|
+
@warden_config = block
|
184
|
+
end
|
190
185
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
186
|
+
# A method used internally to setup warden manager from the Rails initialize
|
187
|
+
# block.
|
188
|
+
def self.configure_warden(config) #:nodoc:
|
189
|
+
config.default_strategies *Devise::STRATEGIES
|
190
|
+
config.failure_app = Devise::FailureApp
|
191
|
+
config.silence_missing_strategies!
|
192
|
+
config.default_scope = Devise.default_scope
|
195
193
|
|
196
|
-
#
|
197
|
-
|
198
|
-
# == Options:
|
199
|
-
#
|
200
|
-
# +strategy+ - Boolean value representing if this module got a custom *strategy*.
|
201
|
-
# Default is +false+. Note: Devise will auto-detect this in such case if this is true.
|
202
|
-
# +model+ - String representing a load path to a custom *model* for this module (to autoload).
|
203
|
-
# Default is +nil+ (i.e. +false+).
|
204
|
-
# +controller+ - Symbol representing a name of an exisiting or custom *controller* for this module.
|
205
|
-
# Default is +nil+ (i.e. +false+).
|
206
|
-
#
|
207
|
-
# == Examples:
|
208
|
-
#
|
209
|
-
# Devise.add_module(:party_module)
|
210
|
-
# Devise.add_module(:party_module, :strategy => true, :controller => :sessions)
|
211
|
-
# Devise.add_module(:party_module, :model => 'party_module/model')
|
212
|
-
#
|
213
|
-
def add_module(module_name, options = {})
|
214
|
-
Devise::ALL.unshift module_name unless Devise::ALL.include?(module_name)
|
215
|
-
Devise::STRATEGIES.unshift module_name if options[:strategy] && !Devise::STRATEGIES.include?(module_name)
|
216
|
-
|
217
|
-
if options[:controller]
|
218
|
-
controller = options[:controller].to_sym
|
219
|
-
Devise::CONTROLLERS[controller] ||= []
|
220
|
-
Devise::CONTROLLERS[controller].unshift module_name unless Devise::CONTROLLERS[controller].include?(module_name)
|
221
|
-
end
|
222
|
-
|
223
|
-
if options[:model]
|
224
|
-
Devise::Models.module_eval do
|
225
|
-
autoload :"#{module_name.to_s.classify}", options[:model]
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
Devise::Mapping.register module_name
|
230
|
-
end
|
194
|
+
# If the user provided a warden hook, call it now.
|
195
|
+
@warden_config.try :call, config
|
231
196
|
end
|
232
|
-
end
|
233
197
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
require 'warden'
|
198
|
+
# Generate a friendly string randomically to be used as token.
|
199
|
+
def self.friendly_token
|
200
|
+
ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n")
|
201
|
+
end
|
239
202
|
end
|
240
203
|
|
204
|
+
require 'warden'
|
241
205
|
require 'devise/mapping'
|
206
|
+
require 'devise/models'
|
207
|
+
require 'devise/modules'
|
242
208
|
require 'devise/rails'
|
@@ -52,7 +52,8 @@ module Devise
|
|
52
52
|
|
53
53
|
# Checks whether it's a devise mapped resource or not.
|
54
54
|
def is_devise_resource? #:nodoc:
|
55
|
-
raise ActionController::UnknownAction unless devise_mapping &&
|
55
|
+
raise ActionController::UnknownAction unless devise_mapping &&
|
56
|
+
devise_mapping.allowed_controllers.include?(controller_path)
|
56
57
|
end
|
57
58
|
|
58
59
|
# Sets the resource creating an instance variable
|
@@ -22,9 +22,11 @@ end
|
|
22
22
|
# Before logout hook to forget the user in the given scope, only if rememberable
|
23
23
|
# is activated for this scope. Also clear remember token to ensure the user
|
24
24
|
# won't be remembered again.
|
25
|
+
# Notice that we forget the user if the record is frozen. This usually means the
|
26
|
+
# user was just deleted.
|
25
27
|
Warden::Manager.before_logout do |record, warden, scope|
|
26
28
|
if record.respond_to?(:forget_me!)
|
27
|
-
record.forget_me!
|
29
|
+
record.forget_me! unless record.frozen?
|
28
30
|
warden.response.delete_cookie "remember_#{scope}_token"
|
29
31
|
end
|
30
32
|
end
|
@@ -1,18 +1,7 @@
|
|
1
1
|
# After each sign in, update sign in time, sign in count and sign in IP.
|
2
2
|
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
3
3
|
scope = options[:scope]
|
4
|
-
if
|
5
|
-
|
6
|
-
record.last_sign_in_at = old_current || new_current
|
7
|
-
record.current_sign_in_at = new_current
|
8
|
-
|
9
|
-
old_current, new_current = record.current_sign_in_ip, warden.request.remote_ip
|
10
|
-
record.last_sign_in_ip = old_current || new_current
|
11
|
-
record.current_sign_in_ip = new_current
|
12
|
-
|
13
|
-
record.sign_in_count ||= 0
|
14
|
-
record.sign_in_count += 1
|
15
|
-
|
16
|
-
record.save(:validate => false)
|
4
|
+
if record.respond_to?(:update_tracked_fields!) && warden.authenticated?(scope)
|
5
|
+
record.update_tracked_fields!(warden.request)
|
17
6
|
end
|
18
7
|
end
|
data/lib/devise/mapping.rb
CHANGED
@@ -18,11 +18,11 @@ module Devise
|
|
18
18
|
# mapping.to #=> User
|
19
19
|
# # is the class to be loaded from routes, given in the route as :class_name.
|
20
20
|
#
|
21
|
-
# mapping.
|
21
|
+
# mapping.modules #=> [:authenticatable]
|
22
22
|
# # is the modules included in the class
|
23
23
|
#
|
24
24
|
class Mapping #:nodoc:
|
25
|
-
attr_reader :name, :as, :path_names, :path_prefix
|
25
|
+
attr_reader :name, :as, :controllers, :path_names, :path_prefix
|
26
26
|
|
27
27
|
# Loop through all mappings looking for a map that matches with the requested
|
28
28
|
# path (ie /users/sign_in). If a path prefix is given, it's taken into account.
|
@@ -62,15 +62,20 @@ module Devise
|
|
62
62
|
@name = (options.delete(:scope) || name.to_s.singularize).to_sym
|
63
63
|
|
64
64
|
@path_prefix = "/#{options.delete(:path_prefix)}/".squeeze("/")
|
65
|
+
|
66
|
+
@controllers = Hash.new { |h,k| h[k] = "devise/#{k}" }
|
67
|
+
@controllers.merge!(options.delete(:controllers) || {})
|
68
|
+
|
65
69
|
@path_names = Hash.new { |h,k| h[k] = k.to_s }
|
66
70
|
@path_names.merge!(options.delete(:path_names) || {})
|
67
71
|
end
|
68
72
|
|
69
73
|
# Return modules for the mapping.
|
70
|
-
def
|
71
|
-
@
|
74
|
+
def modules
|
75
|
+
@modules ||= to.devise_modules
|
72
76
|
end
|
73
77
|
|
78
|
+
# Gives the class the mapping points to.
|
74
79
|
# Reload mapped class each time when cache_classes is false.
|
75
80
|
def to
|
76
81
|
return @to if @to
|
@@ -79,9 +84,14 @@ module Devise
|
|
79
84
|
klass
|
80
85
|
end
|
81
86
|
|
82
|
-
#
|
83
|
-
|
84
|
-
|
87
|
+
# Keep a list of allowed controllers for this mapping. It's useful to ensure
|
88
|
+
# that an Admin cannot access the registrations controller unless it has
|
89
|
+
# :registerable in the model.
|
90
|
+
def allowed_controllers
|
91
|
+
@allowed_controllers ||= begin
|
92
|
+
canonical = CONTROLLERS.values_at(*self.modules).compact
|
93
|
+
@controllers.values_at(*canonical)
|
94
|
+
end
|
85
95
|
end
|
86
96
|
|
87
97
|
# Return in which position in the path prefix devise should find the as mapping.
|
@@ -98,18 +108,15 @@ module Devise
|
|
98
108
|
# Example:
|
99
109
|
#
|
100
110
|
# def confirmable?
|
101
|
-
# self.
|
111
|
+
# self.modules.include?(:confirmable)
|
102
112
|
# end
|
103
113
|
#
|
104
|
-
def self.register(
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
METHOD
|
111
|
-
end
|
114
|
+
def self.register(m)
|
115
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
116
|
+
def #{m}?
|
117
|
+
self.modules.include?(:#{m})
|
118
|
+
end
|
119
|
+
METHOD
|
112
120
|
end
|
113
|
-
Devise::Mapping.register *ALL
|
114
121
|
end
|
115
122
|
end
|
data/lib/devise/models.rb
CHANGED
@@ -1,16 +1,5 @@
|
|
1
1
|
module Devise
|
2
2
|
module Models
|
3
|
-
autoload :Activatable, 'devise/models/activatable'
|
4
|
-
autoload :Authenticatable, 'devise/models/authenticatable'
|
5
|
-
autoload :Confirmable, 'devise/models/confirmable'
|
6
|
-
autoload :Lockable, 'devise/models/lockable'
|
7
|
-
autoload :Recoverable, 'devise/models/recoverable'
|
8
|
-
autoload :Rememberable, 'devise/models/rememberable'
|
9
|
-
autoload :Registerable, 'devise/models/registerable'
|
10
|
-
autoload :Timeoutable, 'devise/models/timeoutable'
|
11
|
-
autoload :Trackable, 'devise/models/trackable'
|
12
|
-
autoload :Validatable, 'devise/models/validatable'
|
13
|
-
|
14
3
|
# Creates configuration values for Devise and for the given module.
|
15
4
|
#
|
16
5
|
# Devise::Models.config(Devise::Authenticable, :stretches, 10)
|
@@ -11,6 +11,20 @@ module Devise
|
|
11
11
|
# * last_sign_in_at - Holds the remote ip of the previous sign in
|
12
12
|
#
|
13
13
|
module Trackable
|
14
|
+
def update_tracked_fields!(request)
|
15
|
+
old_current, new_current = self.current_sign_in_at, Time.now
|
16
|
+
self.last_sign_in_at = old_current || new_current
|
17
|
+
self.current_sign_in_at = new_current
|
18
|
+
|
19
|
+
old_current, new_current = self.current_sign_in_ip, request.remote_ip
|
20
|
+
self.last_sign_in_ip = old_current || new_current
|
21
|
+
self.current_sign_in_ip = new_current
|
22
|
+
|
23
|
+
self.sign_in_count ||= 0
|
24
|
+
self.sign_in_count += 1
|
25
|
+
|
26
|
+
save(:validate => false)
|
27
|
+
end
|
14
28
|
end
|
15
29
|
end
|
16
30
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support/core_ext/object/with_options'
|
2
|
+
|
3
|
+
Devise.with_options :model => true do |d|
|
4
|
+
# Strategies first
|
5
|
+
d.with_options :strategy => true do |s|
|
6
|
+
s.add_module :authenticatable, :controller => :sessions, :flash => :invalid, :route => :session
|
7
|
+
s.add_module :http_authenticatable
|
8
|
+
s.add_module :token_authenticatable, :controller => :sessions, :flash => :invalid_token, :route => :session
|
9
|
+
s.add_module :rememberable
|
10
|
+
end
|
11
|
+
|
12
|
+
# Misc after
|
13
|
+
d.add_module :recoverable, :controller => :passwords, :route => :password
|
14
|
+
d.add_module :registerable, :controller => :registrations, :route => :registration
|
15
|
+
d.add_module :validatable
|
16
|
+
|
17
|
+
# The ones which can sign out after
|
18
|
+
d.add_module :activatable, :flash => :inactive
|
19
|
+
d.add_module :confirmable, :controller => :confirmations, :flash => :unconfirmed, :route => :confirmation
|
20
|
+
d.add_module :lockable, :controller => :unlocks, :flash => :locked, :route => :unlock
|
21
|
+
d.add_module :timeoutable, :flash => :timeout
|
22
|
+
|
23
|
+
# Stats for last, so we make sure the user is really signed in
|
24
|
+
d.add_module :trackable
|
25
|
+
end
|
data/lib/devise/rails/routes.rb
CHANGED
@@ -87,17 +87,20 @@ module ActionDispatch::Routing
|
|
87
87
|
options = resources.extract_options!
|
88
88
|
resources.map!(&:to_sym)
|
89
89
|
|
90
|
-
controllers = Hash.new { |h,k| h[k] = "devise/#{k}" }
|
91
|
-
controllers.merge!(options.delete(:controllers) || {})
|
92
|
-
|
93
90
|
resources.each do |resource|
|
94
|
-
mapping = Devise::Mapping.new(resource, options
|
91
|
+
mapping = Devise::Mapping.new(resource, options)
|
92
|
+
|
93
|
+
unless mapping.to.respond_to?(:devise)
|
94
|
+
raise "#{mapping.to.name} does not respond to 'devise' method. This usually means you haven't " <<
|
95
|
+
"loaded your ORM file or it's being loaded to late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
|
96
|
+
"inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
|
97
|
+
end
|
95
98
|
|
96
99
|
Devise.default_scope ||= mapping.name
|
97
100
|
Devise.mappings[mapping.name] = mapping
|
98
101
|
|
99
|
-
mapping.
|
100
|
-
send(mod, mapping, controllers) if self.respond_to?(mod, true)
|
102
|
+
mapping.modules.each do |mod|
|
103
|
+
send(mod, mapping, mapping.controllers) if self.respond_to?(mod, true)
|
101
104
|
end
|
102
105
|
end
|
103
106
|
end
|
data/lib/devise/schema.rb
CHANGED
@@ -9,12 +9,13 @@ module Devise
|
|
9
9
|
# * :null - When true, allow columns to be null.
|
10
10
|
# * :encryptor - The encryptor going to be used, necessary for setting the proper encrypter password length.
|
11
11
|
def authenticatable(options={})
|
12
|
-
null
|
13
|
-
|
12
|
+
null = options[:null] || false
|
13
|
+
default = options[:default]
|
14
|
+
encryptor = options[:encryptor] || (respond_to?(:encryptor) ? self.encryptor : :sha1)
|
14
15
|
|
15
|
-
apply_schema :email, String, :null => null
|
16
|
-
apply_schema :encrypted_password, String, :null => null, :limit => Devise::ENCRYPTORS_LENGTH[encryptor]
|
17
|
-
apply_schema :password_salt, String, :null => null
|
16
|
+
apply_schema :email, String, :null => null, :default => default
|
17
|
+
apply_schema :encrypted_password, String, :null => null, :default => default, :limit => Devise::ENCRYPTORS_LENGTH[encryptor]
|
18
|
+
apply_schema :password_salt, String, :null => null, :default => default
|
18
19
|
end
|
19
20
|
|
20
21
|
# Creates authentication_token.
|
data/lib/devise/version.rb
CHANGED
data/test/devise_test.rb
CHANGED
@@ -25,7 +25,7 @@ class DeviseTest < ActiveSupport::TestCase
|
|
25
25
|
Devise.configure_warden(config)
|
26
26
|
|
27
27
|
assert_equal Devise::FailureApp, config.failure_app
|
28
|
-
assert_equal [:rememberable, :
|
28
|
+
assert_equal [:rememberable, :token_authenticatable, :http_authenticatable, :authenticatable], config.default_strategies
|
29
29
|
assert_equal :user, config.default_scope
|
30
30
|
assert config.silence_missing_strategies?
|
31
31
|
end
|
@@ -58,10 +58,9 @@ class DeviseTest < ActiveSupport::TestCase
|
|
58
58
|
Devise::STRATEGIES.delete(:banana)
|
59
59
|
|
60
60
|
assert_nothing_raised(Exception) { Devise.add_module(:kivi, :controller => :fruits) }
|
61
|
-
|
62
|
-
assert_equal 1, Devise::CONTROLLERS[:fruits].select { |v| v == :kivi }.size
|
61
|
+
assert_equal :fruits, Devise::CONTROLLERS[:kivi]
|
63
62
|
Devise::ALL.delete(:kivi)
|
64
|
-
Devise::CONTROLLERS.delete(:
|
63
|
+
Devise::CONTROLLERS.delete(:kivi)
|
65
64
|
|
66
65
|
assert_nothing_raised(Exception) { Devise.add_module(:authenticatable_again, :model => 'devise/model/authenticatable') }
|
67
66
|
assert defined?(Devise::Models::AuthenticatableAgain)
|
data/test/mapping_test.rb
CHANGED
@@ -5,7 +5,7 @@ class MappingTest < ActiveSupport::TestCase
|
|
5
5
|
test 'store options' do
|
6
6
|
mapping = Devise.mappings[:user]
|
7
7
|
assert_equal User, mapping.to
|
8
|
-
assert_equal User.devise_modules, mapping.
|
8
|
+
assert_equal User.devise_modules, mapping.modules
|
9
9
|
assert_equal :users, mapping.as
|
10
10
|
end
|
11
11
|
|
@@ -18,15 +18,15 @@ class MappingTest < ActiveSupport::TestCase
|
|
18
18
|
end
|
19
19
|
|
20
20
|
test 'allows a controller depending on the mapping' do
|
21
|
-
|
22
|
-
assert
|
23
|
-
assert
|
24
|
-
assert
|
25
|
-
|
26
|
-
|
27
|
-
assert
|
28
|
-
assert_not
|
29
|
-
assert_not
|
21
|
+
allowed = Devise.mappings[:user].allowed_controllers
|
22
|
+
assert allowed.include?("devise/sessions")
|
23
|
+
assert allowed.include?("devise/confirmations")
|
24
|
+
assert allowed.include?("devise/passwords")
|
25
|
+
|
26
|
+
allowed = Devise.mappings[:admin].allowed_controllers
|
27
|
+
assert allowed.include?("sessions")
|
28
|
+
assert_not allowed.include?("devise/confirmations")
|
29
|
+
assert_not allowed.include?("devise/passwords")
|
30
30
|
end
|
31
31
|
|
32
32
|
test 'find mapping by path' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.pre4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jos\xC3\xA9 Valim"
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-
|
13
|
+
date: 2010-03-03 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -90,6 +90,7 @@ files:
|
|
90
90
|
- lib/devise/models/token_authenticatable.rb
|
91
91
|
- lib/devise/models/trackable.rb
|
92
92
|
- lib/devise/models/validatable.rb
|
93
|
+
- lib/devise/modules.rb
|
93
94
|
- lib/devise/orm/active_record.rb
|
94
95
|
- lib/devise/orm/data_mapper.rb
|
95
96
|
- lib/devise/orm/mongo_mapper.rb
|