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.

@@ -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: responsible for encrypting password and validating authenticity of a user while signing in.
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: responsible for verifying whether an account is already confirmed to sign in, and to send emails with confirmation instructions.
16
- * Recoverable: takes care of reseting the user password and send reset instructions.
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 remember the user from a saved cookie.
19
- * Trackable: tracks sign in count, timestamps and ip.
20
- * Timeoutable: expires sessions without activity in a certain period of time.
21
- * Validatable: creates all needed validations for email and password. It's totally optional, so you're able to to customize validations by yourself.
22
- * Lockable: takes care of locking an account based on the number of failed sign in attempts. Handles unlock via expire and email.
23
- * Activatable: if you need to activate accounts by other means, which are not through confirmation, use this module.
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
- There's an example application using Devise at http://github.com/plataformatec/devise_example .
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 so you need to install it as a gem. Please ensure you have it installed in order to use devise (see installation below).
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 them, you need configure warden and devise gems inside your gemfile:
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, and devise routes must be created inside your config/routes.rb file.
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 setup your migrations. Luckily, devise has some helpers to save you from this boring work:
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
- Remember that Devise don't rely on _attr_accessible_ or _attr_protected_ inside its modules, so be sure to setup what attributes are accessible or protected in your model.
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
- The next setup after setting up your model is to configure your routes. You do this by opening up your config/routes.rb and adding:
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 is going to look inside you User model and create a set of needed routes (you can see them by running `rake routes`).
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
- There are also some options available for configuring your routes, as :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:
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 detailed description.
98
+ Be sure to check devise_for documentation for details.
96
99
 
97
- After this steps, run your migrations, and you are ready to go! But don't finish reading, we still have a lot to tell you:
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 is gonna create some helpers to use inside your controllers and views. To setup a controller that needs user authentication, just add this before_filter:
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, you have the following helper:
108
+ To verify if a user is signed in, use the following helper:
106
109
 
107
110
  user_signed_in?
108
111
 
109
- And to get the current signed in user this helper is available:
112
+ For the current signed-in user, this helper is available:
110
113
 
111
114
  current_user
112
115
 
113
- You have also access to the session for this scope:
116
+ You can access the session for this scope:
114
117
 
115
118
  user_session
116
119
 
117
- After signing in a user, confirming it's account or updating it's 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:
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 better your redirect hooks.
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 also need to setup default url options for the mailer in each environment. Here's is the configuration for config/environments/development.rb:
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 let's you setup as many roles as you want, so let's say you already have this User model and also want an Admin model with just authentication, trackable, lockable and timeoutable stuff and none of confirmation or password recovery. Just follow the same steps:
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 comes with some generators to help you start:
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. You can also generate models through:
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
- A model configured with all devise modules and attr_accessible for default fields will be created. The generator will also create the migration and configure your routes for devise.
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 accept some options to configure its modules. For example, you can chose which encryptor to use in authenticatable simply doing:
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 provide :pepper, :stretches, :confirm_within, :remember_for, :timeout_in, :unlock_in and others. All those are described in the initializer created when you invoke the devise_install generator describer above.
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
- One of Devise goals is to help you bootstrap your application with authentication really fast. Another goal is to not be in your way when you need to customize it.
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 devise is an engine, it has all default views inside the gem. They are good to get you started, but you will want to customize them at some point. And Devise has a generator to copy them all to your application:
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 you have. But what if you need so different views to each of them? Devise also has an easy way to accomplish it: just setup config.scoped_views to true inside "config/initializers/devise.rb".
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 fallback to the default view at "devise/sessions/new".
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" as views anymore, so remember to make a copy of "devise/sessions" to "admin/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 wass successful or not. Devise expects your application to call "flash[:notice]" and "flash[:alert]" as appropriate.
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 setup your locale file this way:
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 like Cucumber, Webrat... Just fill in the form or explicitly set the user in session. For more tips, check the wiki (http://wiki.github.com/plataformatec/devise).
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 it set the desired encryptor in the encryptor initializer config option. You might also need to rename your encrypted password and salt columns to match Devises's one (encrypted_password and password_salt).
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 both ActiveRecord (default) and MongoMapper, and has experimental Datamapper supports (in a sense that Devise test suite does not run completely with Datamapper). To choose other ORM, you just need to configure it in the initializer file.
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 running list of contributors. Check them in the CHANGELOG or do `git shortlog -s -n` in the cloned repository.
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 or want to drop a line, feel free to create an issue on
272
- GitHub or send an e-mail to the mailing list.
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 self.resource.update_with_password(params[resource_name])
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
- self.resource.destroy
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 dup the resource
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
@@ -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
- ALL = []
25
-
26
- # Authentication ones first
27
- ALL.push :authenticatable, :http_authenticatable, :token_authenticatable, :rememberable
28
-
29
- # Misc after
30
- ALL.push :recoverable, :registerable, :validatable
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
- class << self
146
- # Default way to setup Devise. Run script/generate devise_install to create
147
- # a fresh initializer with all configuration values.
148
- def setup
149
- yield self
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
- # TODO Remove me on 1.1.0 final
153
- def orm=(value)
154
- ActiveSupport::Deprecation.warn "Devise.orm= and config.orm= are deprecated. " <<
155
- "Just load \"devise/orm/\#{ORM_NAME}\" if Devise supports your ORM"
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
- # TODO Remove me on 1.1.0 final
159
- def default_url_options
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
- # Sets warden configuration using a block that will be invoked on warden
165
- # initialization.
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
- # A method used internally to setup warden manager from the Rails initialize
180
- # block.
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
- # If the user provided a warden hook, call it now.
188
- @warden_config.try :call, config
189
- end
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
- # Generate a friendly string randomically to be used as token.
192
- def friendly_token
193
- ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n")
194
- end
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
- # Make Devise aware of an 3rd party Devise-module. For convenience.
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
- begin
235
- require 'warden'
236
- rescue
237
- gem 'warden'
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 && devise_mapping.allows?(controller_name)
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 Devise.mappings[scope].try(:trackable?) && warden.authenticated?(scope)
5
- old_current, new_current = record.current_sign_in_at, Time.now
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
@@ -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.for #=> [:authenticatable]
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 for
71
- @for ||= to.devise_modules
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
- # Check if the respective controller has a module in the mapping class.
83
- def allows?(controller)
84
- (self.for & CONTROLLERS[controller.to_sym]).present?
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.for.include?(:confirmable)
111
+ # self.modules.include?(:confirmable)
102
112
  # end
103
113
  #
104
- def self.register(*modules)
105
- modules.each do |m|
106
- class_eval <<-METHOD, __FILE__, __LINE__ + 1
107
- def #{m}?
108
- self.for.include?(:#{m})
109
- end
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
@@ -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
@@ -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.dup)
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.for.each do |mod|
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
@@ -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 = options[:null] || false
13
- encryptor = options[:encryptor] || (respond_to?(:encryptor) ? self.encryptor : :sha1)
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.
@@ -23,7 +23,7 @@ module Devise
23
23
  protected
24
24
 
25
25
  def valid_controller?
26
- params[:controller] =~ /sessions$/
26
+ mapping.controllers[:sessions] == params[:controller]
27
27
  end
28
28
 
29
29
  def valid_params?
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "1.1.pre3".freeze
2
+ VERSION = "1.1.pre4".freeze
3
3
  end
@@ -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, :http_authenticatable, :token_authenticatable, :authenticatable], config.default_strategies
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
- assert_not_nil Devise::CONTROLLERS[:fruits]
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(:fruits)
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)
@@ -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.for
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
- mapping = Devise.mappings[:user]
22
- assert mapping.allows?(:sessions)
23
- assert mapping.allows?(:confirmations)
24
- assert mapping.allows?(:passwords)
25
-
26
- mapping = Devise.mappings[:admin]
27
- assert mapping.allows?(:sessions)
28
- assert_not mapping.allows?(:confirmations)
29
- assert_not mapping.allows?(:passwords)
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.pre3
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-02-24 00:00:00 +01:00
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