devise 3.2.0 → 3.3.0
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.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.travis.yml +18 -3
- data/CHANGELOG.md +82 -9
- data/CONTRIBUTING.md +2 -2
- data/Gemfile +7 -9
- data/Gemfile.lock +102 -96
- data/MIT-LICENSE +1 -1
- data/README.md +94 -42
- data/Rakefile +1 -1
- data/app/controllers/devise/confirmations_controller.rb +5 -3
- data/app/controllers/devise/omniauth_callbacks_controller.rb +2 -2
- data/app/controllers/devise/passwords_controller.rb +5 -3
- data/app/controllers/devise/registrations_controller.rb +26 -10
- data/app/controllers/devise/sessions_controller.rb +39 -14
- data/app/controllers/devise/unlocks_controller.rb +4 -2
- data/app/controllers/devise_controller.rb +6 -6
- data/app/helpers/devise_helper.rb +2 -2
- data/app/views/devise/confirmations/new.html.erb +2 -2
- data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
- data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
- data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
- data/app/views/devise/passwords/edit.html.erb +3 -3
- data/app/views/devise/passwords/new.html.erb +2 -2
- data/app/views/devise/registrations/edit.html.erb +6 -6
- data/app/views/devise/registrations/new.html.erb +5 -5
- data/app/views/devise/sessions/new.html.erb +5 -5
- data/app/views/devise/shared/_links.erb +1 -1
- data/app/views/devise/unlocks/new.html.erb +2 -2
- data/config/locales/en.yml +17 -16
- data/devise.gemspec +2 -2
- data/gemfiles/{Gemfile.rails-3.2.x → Gemfile.rails-3.2-stable} +8 -10
- data/gemfiles/Gemfile.rails-3.2-stable.lock +166 -0
- data/gemfiles/Gemfile.rails-4.0-stable +29 -0
- data/gemfiles/Gemfile.rails-4.0-stable.lock +162 -0
- data/gemfiles/Gemfile.rails-head +32 -0
- data/gemfiles/Gemfile.rails-head.lock +190 -0
- data/lib/devise/controllers/helpers.rb +84 -29
- data/lib/devise/controllers/rememberable.rb +3 -3
- data/lib/devise/controllers/scoped_views.rb +1 -1
- data/lib/devise/controllers/sign_in_out.rb +9 -10
- data/lib/devise/controllers/store_location.rb +56 -0
- data/lib/devise/controllers/url_helpers.rb +3 -1
- data/lib/devise/failure_app.rb +12 -10
- data/lib/devise/hooks/activatable.rb +5 -6
- data/lib/devise/hooks/csrf_cleaner.rb +3 -1
- data/lib/devise/hooks/lockable.rb +1 -1
- data/lib/devise/hooks/proxy.rb +2 -2
- data/lib/devise/hooks/rememberable.rb +2 -2
- data/lib/devise/hooks/timeoutable.rb +10 -3
- data/lib/devise/hooks/trackable.rb +1 -1
- data/lib/devise/mailers/helpers.rb +8 -8
- data/lib/devise/mapping.rb +4 -1
- data/lib/devise/models/authenticatable.rb +5 -5
- data/lib/devise/models/confirmable.rb +14 -14
- data/lib/devise/models/database_authenticatable.rb +18 -5
- data/lib/devise/models/lockable.rb +14 -11
- data/lib/devise/models/omniauthable.rb +1 -1
- data/lib/devise/models/recoverable.rb +23 -7
- data/lib/devise/models/rememberable.rb +6 -6
- data/lib/devise/models/timeoutable.rb +2 -2
- data/lib/devise/models/trackable.rb +5 -2
- data/lib/devise/models/validatable.rb +6 -6
- data/lib/devise/modules.rb +10 -10
- data/lib/devise/omniauth/url_helpers.rb +2 -2
- data/lib/devise/orm/active_record.rb +1 -1
- data/lib/devise/orm/mongoid.rb +1 -1
- data/lib/devise/rails/routes.rb +107 -78
- data/lib/devise/rails.rb +7 -1
- data/lib/devise/strategies/authenticatable.rb +11 -4
- data/lib/devise/strategies/base.rb +1 -1
- data/lib/devise/strategies/database_authenticatable.rb +7 -4
- data/lib/devise/test_helpers.rb +2 -2
- data/lib/devise/time_inflector.rb +2 -2
- data/lib/devise/version.rb +1 -1
- data/lib/devise.rb +15 -10
- data/lib/generators/active_record/devise_generator.rb +27 -10
- data/lib/generators/active_record/templates/migration.rb +4 -4
- data/lib/generators/active_record/templates/migration_existing.rb +4 -4
- data/lib/generators/devise/devise_generator.rb +5 -3
- data/lib/generators/devise/install_generator.rb +5 -0
- data/lib/generators/devise/views_generator.rb +31 -18
- data/lib/generators/mongoid/devise_generator.rb +20 -19
- data/lib/generators/templates/README +4 -4
- data/lib/generators/templates/devise.rb +20 -11
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
- data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +2 -2
- data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -4
- data/lib/generators/templates/simple_form_for/passwords/new.html.erb +2 -2
- data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +6 -6
- data/lib/generators/templates/simple_form_for/registrations/new.html.erb +4 -4
- data/lib/generators/templates/simple_form_for/sessions/new.html.erb +4 -4
- data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +2 -2
- data/script/cached-bundle +49 -0
- data/script/s3-put +71 -0
- data/test/controllers/custom_registrations_controller_test.rb +35 -0
- data/test/controllers/helpers_test.rb +89 -31
- data/test/controllers/internal_helpers_test.rb +11 -8
- data/test/controllers/passwords_controller_test.rb +1 -1
- data/test/controllers/sessions_controller_test.rb +29 -25
- data/test/controllers/url_helpers_test.rb +4 -4
- data/test/delegator_test.rb +1 -1
- data/test/devise_test.rb +21 -8
- data/test/failure_app_test.rb +61 -25
- data/test/generators/active_record_generator_test.rb +10 -4
- data/test/generators/devise_generator_test.rb +2 -2
- data/test/generators/mongoid_generator_test.rb +3 -3
- data/test/generators/views_generator_test.rb +30 -1
- data/test/helpers/devise_helper_test.rb +14 -13
- data/test/integration/authenticatable_test.rb +61 -45
- data/test/integration/confirmable_test.rb +95 -55
- data/test/integration/database_authenticatable_test.rb +16 -16
- data/test/integration/http_authenticatable_test.rb +12 -12
- data/test/integration/lockable_test.rb +43 -43
- data/test/integration/omniauthable_test.rb +3 -3
- data/test/integration/recoverable_test.rb +53 -53
- data/test/integration/registerable_test.rb +90 -80
- data/test/integration/rememberable_test.rb +15 -15
- data/test/integration/timeoutable_test.rb +27 -16
- data/test/integration/trackable_test.rb +4 -4
- data/test/mailers/confirmation_instructions_test.rb +7 -7
- data/test/mailers/reset_password_instructions_test.rb +6 -6
- data/test/mailers/unlock_instructions_test.rb +5 -5
- data/test/mapping_test.rb +3 -3
- data/test/models/authenticatable_test.rb +3 -3
- data/test/models/confirmable_test.rb +32 -32
- data/test/models/database_authenticatable_test.rb +32 -27
- data/test/models/lockable_test.rb +57 -33
- data/test/models/recoverable_test.rb +34 -22
- data/test/models/rememberable_test.rb +29 -14
- data/test/models/serializable_test.rb +8 -8
- data/test/models/timeoutable_test.rb +1 -1
- data/test/models/trackable_test.rb +28 -0
- data/test/models/validatable_test.rb +13 -13
- data/test/omniauth/config_test.rb +4 -4
- data/test/omniauth/url_helpers_test.rb +3 -3
- data/test/orm/mongoid.rb +1 -1
- data/test/parameter_sanitizer_test.rb +1 -1
- data/test/rails_app/app/active_record/shim.rb +1 -1
- data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
- data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
- data/test/rails_app/app/controllers/admins/sessions_controller.rb +1 -1
- data/test/rails_app/app/controllers/admins_controller.rb +1 -1
- data/test/rails_app/app/controllers/application_controller.rb +5 -2
- data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
- data/test/rails_app/app/controllers/custom/registrations_controller.rb +21 -0
- data/test/rails_app/app/controllers/home_controller.rb +1 -1
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +1 -1
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +1 -1
- data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +4 -4
- data/test/rails_app/app/controllers/users_controller.rb +6 -6
- data/test/rails_app/app/mailers/users/mailer.rb +4 -4
- data/test/rails_app/app/mongoid/admin.rb +11 -11
- data/test/rails_app/app/mongoid/shim.rb +2 -2
- data/test/rails_app/app/mongoid/user.rb +19 -19
- data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
- data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
- data/test/rails_app/app/views/admins/sessions/new.html.erb +1 -1
- data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -1
- data/test/rails_app/app/views/home/index.html.erb +1 -1
- data/test/rails_app/app/views/home/join.html.erb +1 -1
- data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -1
- data/test/rails_app/app/views/layouts/application.html.erb +1 -1
- data/test/rails_app/config/application.rb +2 -2
- data/test/rails_app/config/boot.rb +7 -1
- data/test/rails_app/config/environments/development.rb +0 -4
- data/test/rails_app/config/environments/production.rb +0 -4
- data/test/rails_app/config/initializers/devise.rb +7 -5
- data/test/rails_app/config/initializers/secret_token.rb +1 -1
- data/test/rails_app/config/routes.rb +60 -42
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +7 -7
- data/test/rails_app/db/schema.rb +21 -17
- data/test/rails_app/lib/shared_admin.rb +4 -4
- data/test/rails_app/lib/shared_user.rb +1 -1
- data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
- data/test/routes_test.rb +72 -58
- data/test/support/action_controller/record_identifier.rb +10 -0
- data/test/support/assertions.rb +2 -3
- data/test/support/helpers.rb +4 -4
- data/test/support/integration.rb +14 -14
- data/test/support/mongoid.yml +6 -0
- data/test/test_helper.rb +2 -7
- data/test/test_helpers_test.rb +25 -35
- data/test/test_models.rb +12 -5
- metadata +53 -38
- data/gemfiles/Gemfile.rails-3.2.x.lock +0 -159
data/README.md
CHANGED
@@ -17,7 +17,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
|
17
17
|
It's composed of 10 modules:
|
18
18
|
|
19
19
|
* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
|
20
|
-
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (https://github.com/intridea/omniauth) support
|
20
|
+
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds Omniauth (https://github.com/intridea/omniauth) support.
|
21
21
|
* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
|
22
22
|
* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
|
23
23
|
* [Registerable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
|
@@ -27,7 +27,7 @@ It's composed of 10 modules:
|
|
27
27
|
* [Validatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
|
28
28
|
* [Lockable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
|
29
29
|
|
30
|
-
Devise is guaranteed to be thread-safe on YARV. Thread-safety support on JRuby is
|
30
|
+
Devise is guaranteed to be thread-safe on YARV. Thread-safety support on JRuby is in progress.
|
31
31
|
|
32
32
|
## Information
|
33
33
|
|
@@ -43,7 +43,7 @@ If you discover a problem with Devise, we would like to know about it. However,
|
|
43
43
|
|
44
44
|
https://github.com/plataformatec/devise/wiki/Bug-reports
|
45
45
|
|
46
|
-
If you found a security bug, do *NOT* use the GitHub issue tracker. Send an email to
|
46
|
+
If you found a security bug, do *NOT* use the GitHub issue tracker. Send an email to opensource@plataformatec.com.br.
|
47
47
|
|
48
48
|
### Mailing list
|
49
49
|
|
@@ -83,7 +83,7 @@ You will usually want to write tests for your changes. To run the test suite, g
|
|
83
83
|
|
84
84
|
If you are building your first Rails application, we recommend you to *not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch, today we have two resources:
|
85
85
|
|
86
|
-
* Michael Hartl's online book: http://railstutorial.org/
|
86
|
+
* Michael Hartl's online book: http://www.railstutorial.org/book/demo_app#sec-modeling_demo_users
|
87
87
|
* Ryan Bates' Railscast: http://railscasts.com/episodes/250-authentication-from-scratch
|
88
88
|
|
89
89
|
Once you have solidified your understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :)
|
@@ -110,18 +110,28 @@ The generator will install an initializer which describes ALL Devise's configura
|
|
110
110
|
rails generate devise MODEL
|
111
111
|
```
|
112
112
|
|
113
|
-
Replace MODEL
|
113
|
+
Replace MODEL with the class name used for the application’s users (it’s frequently `User` but could also be `Admin`). This will create a model (if one does not exist) and configure it with default Devise modules. The generator also configures your `config/routes.rb` file to point to the Devise controller.
|
114
114
|
|
115
|
-
|
115
|
+
Next, check the MODEL for any additional configuration options you might want to add, such as confirmable or lockable. If you add an option, be sure to inspect the migration file (created by the generator if your ORM supports them) and uncomment the appropriate section. For example, if you add the confirmable option in the model, you'll need to uncomment the Confirmable section in the migration. Then run `rake db:migrate`
|
116
|
+
|
117
|
+
Next, you need to set up the default URL options for the Devise mailer in each environment. Here is a possible configuration for `config/environments/development.rb`:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
121
|
+
```
|
122
|
+
|
123
|
+
You should restart your application after changing Devise's configuration options. Otherwise you'll run into strange errors like users being unable to login and route helpers being undefined.
|
116
124
|
|
117
125
|
### Controller filters and helpers
|
118
126
|
|
119
|
-
Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this
|
127
|
+
Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_action (assuming your devise model is 'User'):
|
120
128
|
|
121
129
|
```ruby
|
122
|
-
|
130
|
+
before_action :authenticate_user!
|
123
131
|
```
|
124
132
|
|
133
|
+
If your devise model is something other than User, replace "_user" with "_yourmodel". The same logic applies to the instructions below.
|
134
|
+
|
125
135
|
To verify if a user is signed in, use the following helper:
|
126
136
|
|
127
137
|
```ruby
|
@@ -140,24 +150,18 @@ You can access the session for this scope:
|
|
140
150
|
user_session
|
141
151
|
```
|
142
152
|
|
143
|
-
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect.
|
153
|
+
After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect. For instance, for a `:user` resource, the `user_root_path` will be used if it exists, otherwise the default `root_path` will be used. This means that you need to set the root inside your routes:
|
144
154
|
|
145
155
|
```ruby
|
146
156
|
root to: "home#index"
|
147
157
|
```
|
148
158
|
|
149
|
-
You can also
|
150
|
-
|
151
|
-
Finally, you need to set up default url options for the mailer in each environment. Here is the configuration for "config/environments/development.rb":
|
152
|
-
|
153
|
-
```ruby
|
154
|
-
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
|
155
|
-
```
|
159
|
+
You can also override `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.
|
156
160
|
|
157
|
-
Notice that if your
|
161
|
+
Notice that if your Devise model is called `Member` instead of `User`, for example, then the helpers available are:
|
158
162
|
|
159
163
|
```ruby
|
160
|
-
|
164
|
+
before_action :authenticate_member!
|
161
165
|
|
162
166
|
member_signed_in?
|
163
167
|
|
@@ -168,19 +172,19 @@ member_session
|
|
168
172
|
|
169
173
|
### Configuring Models
|
170
174
|
|
171
|
-
The
|
175
|
+
The Devise method in your models also accepts some options to configure its modules. For example, you can choose the cost of the encryption algorithm with:
|
172
176
|
|
173
177
|
```ruby
|
174
|
-
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :
|
178
|
+
devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 20
|
175
179
|
```
|
176
180
|
|
177
|
-
Besides
|
181
|
+
Besides `:stretches`, you can define `:pepper`, `:encryptor`, `:confirm_within`, `:remember_for`, `:timeout_in`, `:unlock_in` among other options. For more details, see the initializer file that was created when you invoked the "devise:install" generator described above.
|
178
182
|
|
179
183
|
### Strong Parameters
|
180
184
|
|
181
185
|
When you customize your own views, you may end up adding new attributes to forms. Rails 4 moved the parameter sanitization from the model to the controller, causing Devise to handle this concern at the controller as well.
|
182
186
|
|
183
|
-
There are just three actions in Devise that allows any set of parameters to be passed down to the model, therefore requiring sanitization. Their names and the
|
187
|
+
There are just three actions in Devise that allows any set of parameters to be passed down to the model, therefore requiring sanitization. Their names and the permitted parameters by default are:
|
184
188
|
|
185
189
|
* `sign_in` (`Devise::SessionsController#new`) - Permits only the authentication keys (like `email`)
|
186
190
|
* `sign_up` (`Devise::RegistrationsController#create`) - Permits authentication keys plus `password` and `password_confirmation`
|
@@ -190,7 +194,7 @@ In case you want to permit additional parameters (the lazy way™) you can do wi
|
|
190
194
|
|
191
195
|
```ruby
|
192
196
|
class ApplicationController < ActionController::Base
|
193
|
-
|
197
|
+
before_action :configure_permitted_parameters, if: :devise_controller?
|
194
198
|
|
195
199
|
protected
|
196
200
|
|
@@ -200,7 +204,9 @@ class ApplicationController < ActionController::Base
|
|
200
204
|
end
|
201
205
|
```
|
202
206
|
|
203
|
-
|
207
|
+
The above works for any additional fields where the parameters are simple scalar types. If you have nested attributes (say you're using `accepts_nested_attributes_for`), then you will need to tell devise about those nestings and types. Devise allows you to completely change Devise defaults or invoke custom behaviour by passing a block:
|
208
|
+
|
209
|
+
To permit simple scalar values for username and email, use this
|
204
210
|
|
205
211
|
```ruby
|
206
212
|
def configure_permitted_parameters
|
@@ -208,6 +214,17 @@ def configure_permitted_parameters
|
|
208
214
|
end
|
209
215
|
```
|
210
216
|
|
217
|
+
If you have some checkboxes that express the roles a user may take on registration, the browser will send those selected checkboxes as an array. An array is not one of Strong Parameters permitted scalars, so we need to configure Devise thusly:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
def configure_permitted_parameters
|
221
|
+
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit({ roles: [] }, :email, :password, :password_confirmation) }
|
222
|
+
end
|
223
|
+
```
|
224
|
+
For the list of permitted scalars, and how to declare permitted keys in nested hashes and arrays, see
|
225
|
+
|
226
|
+
https://github.com/rails/strong_parameters#nested-parameters
|
227
|
+
|
211
228
|
If you have multiple Devise models, you may want to set up different parameter sanitizer per model. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and add your own logic:
|
212
229
|
|
213
230
|
```ruby
|
@@ -246,14 +263,21 @@ Since Devise is an engine, all its views are packaged inside the gem. These view
|
|
246
263
|
rails generate devise:views
|
247
264
|
```
|
248
265
|
|
249
|
-
If you have more than one Devise model in your application (such as
|
266
|
+
If you have more than one Devise model in your application (such as `User` and `Admin`), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set `config.scoped_views = true` inside the `config/initializers/devise.rb` file.
|
250
267
|
|
251
|
-
After doing so, you will be able to have views based on the role like
|
268
|
+
After doing so, you will be able to have views based on the role 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`. You can also use the generator to generate scoped views:
|
252
269
|
|
253
270
|
```console
|
254
271
|
rails generate devise:views users
|
255
272
|
```
|
256
273
|
|
274
|
+
If you want to generate only a few set of views, like the ones for the `registrable` and `confirmable` module,
|
275
|
+
you can pass a list of modules to the generator with the `-v` flag.
|
276
|
+
|
277
|
+
```console
|
278
|
+
rails generate devise:views -v registrations confirmations
|
279
|
+
```
|
280
|
+
|
257
281
|
### Configuring controllers
|
258
282
|
|
259
283
|
If the customization at the views level is not enough, you can customize each controller by following these steps:
|
@@ -265,24 +289,50 @@ If the customization at the views level is not enough, you can customize each co
|
|
265
289
|
end
|
266
290
|
```
|
267
291
|
|
268
|
-
Note that in the above example, the controller needs to be created in the `app/
|
292
|
+
Note that in the above example, the controller needs to be created in the `app/controllers/admins/` directory.
|
269
293
|
|
270
294
|
2. Tell the router to use this controller:
|
271
295
|
|
272
296
|
```ruby
|
273
|
-
devise_for :admins, :
|
297
|
+
devise_for :admins, controllers: { sessions: "admins/sessions" }
|
298
|
+
```
|
299
|
+
|
300
|
+
3. Copy the views from `devise/sessions` to `admins/sessions`. Since the controller was changed, it won't use the default views located in `devise/sessions`.
|
301
|
+
|
302
|
+
4. Finally, change or extend the desired controller actions.
|
303
|
+
|
304
|
+
You can completely override a controller action:
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
class Admins::SessionsController < Devise::SessionsController
|
308
|
+
def create
|
309
|
+
# custom sign-in code
|
310
|
+
end
|
311
|
+
end
|
274
312
|
```
|
275
313
|
|
276
|
-
|
314
|
+
Or you can simply add new behaviour to it:
|
277
315
|
|
278
|
-
|
316
|
+
```ruby
|
317
|
+
class Admins::SessionsController < Devise::SessionsController
|
318
|
+
def create
|
319
|
+
super do |resource|
|
320
|
+
BackgroundWorker.trigger(resource)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
```
|
325
|
+
|
326
|
+
This is useful for triggering background jobs or logging events during certain actions.
|
327
|
+
|
328
|
+
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. Do not print the entire flash hash, print only specific keys. In some circumstances, Devise adds a `:timedout` key to the flash hash, which is not meant for display. Remove this key from the hash if you intend to print the entire hash.
|
279
329
|
|
280
330
|
### Configuring routes
|
281
331
|
|
282
332
|
Devise also ships with default routes. If you need to customize them, you should probably be able to do it through the devise_for method. It accepts several options like :class_name, :path_prefix and so on, including the possibility to change path names for I18n:
|
283
333
|
|
284
334
|
```ruby
|
285
|
-
devise_for :users, :
|
335
|
+
devise_for :users, path: "auth", path_names: { sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification', unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' }
|
286
336
|
```
|
287
337
|
|
288
338
|
Be sure to check `devise_for` documentation for details.
|
@@ -291,11 +341,11 @@ If you have the need for more deep customization, for instance to also allow "/s
|
|
291
341
|
|
292
342
|
```ruby
|
293
343
|
devise_scope :user do
|
294
|
-
get "sign_in", :
|
344
|
+
get "sign_in", to: "devise/sessions#new"
|
295
345
|
end
|
296
346
|
```
|
297
347
|
|
298
|
-
This way you tell
|
348
|
+
This way you tell Devise to use the scope `:user` when "/sign_in" is accessed. Notice `devise_scope` is also aliased as `as` in your router.
|
299
349
|
|
300
350
|
### I18n
|
301
351
|
|
@@ -337,9 +387,11 @@ Take a look at our locale file to check all available messages. You may also be
|
|
337
387
|
|
338
388
|
https://github.com/plataformatec/devise/wiki/I18n
|
339
389
|
|
390
|
+
Caution: Devise Controllers inherit from ApplicationController. If your app uses multiple locales, you should be sure to set I18n.locale in ApplicationController
|
391
|
+
|
340
392
|
### Test helpers
|
341
393
|
|
342
|
-
Devise includes some
|
394
|
+
Devise includes some test helpers for functional specs. In order to use them, you need to include Devise in your functional tests by adding the following to the bottom of your `test/test_helper.rb` file:
|
343
395
|
|
344
396
|
```ruby
|
345
397
|
class ActionController::TestCase
|
@@ -347,11 +399,11 @@ class ActionController::TestCase
|
|
347
399
|
end
|
348
400
|
```
|
349
401
|
|
350
|
-
If you're using RSpec, you can put the following inside a file named `spec/support/devise.rb`:
|
402
|
+
If you're using RSpec, you can put the following inside a file named `spec/support/devise.rb` or in your `spec/spec_helper.rb`:
|
351
403
|
|
352
404
|
```ruby
|
353
405
|
RSpec.configure do |config|
|
354
|
-
config.include Devise::TestHelpers, :
|
406
|
+
config.include Devise::TestHelpers, type: :controller
|
355
407
|
end
|
356
408
|
```
|
357
409
|
|
@@ -365,11 +417,11 @@ sign_out :user # sign_out(scope)
|
|
365
417
|
sign_out @user # sign_out(resource)
|
366
418
|
```
|
367
419
|
|
368
|
-
There are two things that
|
420
|
+
There are two things that are important to keep in mind:
|
369
421
|
|
370
422
|
1. These helpers are not going to work for integration tests driven by Capybara or Webrat. They are meant to be used with functional tests only. Instead, fill in the form or explicitly set the user in session;
|
371
423
|
|
372
|
-
2. If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request. This is necessary because Devise gets this information from router, but since functional tests do not pass through the router, it needs to be told explicitly. For example, if you are testing the user scope, simply do:
|
424
|
+
2. If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request. This is necessary because Devise gets this information from the router, but since functional tests do not pass through the router, it needs to be told explicitly. For example, if you are testing the user scope, simply do:
|
373
425
|
|
374
426
|
```ruby
|
375
427
|
@request.env["devise.mapping"] = Devise.mappings[:user]
|
@@ -381,7 +433,7 @@ There are two things that is important to keep in mind:
|
|
381
433
|
Devise comes with Omniauth support out of the box to authenticate with other providers. To use it, just specify your omniauth configuration in `config/initializers/devise.rb`:
|
382
434
|
|
383
435
|
```ruby
|
384
|
-
config.omniauth :github, 'APP_ID', 'APP_SECRET', :
|
436
|
+
config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
385
437
|
```
|
386
438
|
|
387
439
|
You can read more about Omniauth support in the wiki:
|
@@ -417,7 +469,7 @@ admin_session
|
|
417
469
|
|
418
470
|
Alternatively, you can simply run the Devise generator.
|
419
471
|
|
420
|
-
Keep in mind that those models will have completely different routes. They **do not** and **cannot** share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend you to use a role-based approach, by either providing a role column or using
|
472
|
+
Keep in mind that those models will have completely different routes. They **do not** and **cannot** share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend you to use a role-based approach, by either providing a role column or using a dedicated gem for authorization.
|
421
473
|
|
422
474
|
### Other ORMs
|
423
475
|
|
@@ -427,7 +479,7 @@ Devise supports ActiveRecord (default) and Mongoid. To choose other ORM, you jus
|
|
427
479
|
|
428
480
|
### Heroku
|
429
481
|
|
430
|
-
Using
|
482
|
+
Using Devise on Heroku with Ruby on Rails 3.1 requires setting:
|
431
483
|
|
432
484
|
```ruby
|
433
485
|
config.assets.initialize_on_precompile = false
|
@@ -449,6 +501,6 @@ https://github.com/plataformatec/devise/graphs/contributors
|
|
449
501
|
|
450
502
|
## License
|
451
503
|
|
452
|
-
MIT License. Copyright 2009-
|
504
|
+
MIT License. Copyright 2009-2014 Plataformatec. http://plataformatec.com.br
|
453
505
|
|
454
506
|
You are not granted rights or licenses to the trademarks of the Plataformatec, including without limitation the Devise name or logo.
|
data/Rakefile
CHANGED
@@ -7,9 +7,10 @@ class Devise::ConfirmationsController < DeviseController
|
|
7
7
|
# POST /resource/confirmation
|
8
8
|
def create
|
9
9
|
self.resource = resource_class.send_confirmation_instructions(resource_params)
|
10
|
+
yield resource if block_given?
|
10
11
|
|
11
12
|
if successfully_sent?(resource)
|
12
|
-
respond_with({}, :
|
13
|
+
respond_with({}, location: after_resending_confirmation_instructions_path_for(resource_name))
|
13
14
|
else
|
14
15
|
respond_with(resource)
|
15
16
|
end
|
@@ -18,12 +19,13 @@ class Devise::ConfirmationsController < DeviseController
|
|
18
19
|
# GET /resource/confirmation?confirmation_token=abcdef
|
19
20
|
def show
|
20
21
|
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
22
|
+
yield resource if block_given?
|
21
23
|
|
22
24
|
if resource.errors.empty?
|
23
25
|
set_flash_message(:notice, :confirmed) if is_flashing_format?
|
24
26
|
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
|
25
27
|
else
|
26
|
-
respond_with_navigational(resource.errors, :
|
28
|
+
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
@@ -36,7 +38,7 @@ class Devise::ConfirmationsController < DeviseController
|
|
36
38
|
|
37
39
|
# The path used after confirmation.
|
38
40
|
def after_confirmation_path_for(resource_name, resource)
|
39
|
-
if signed_in?
|
41
|
+
if signed_in?(resource_name)
|
40
42
|
signed_in_root_path(resource)
|
41
43
|
else
|
42
44
|
new_session_path(resource_name)
|
@@ -2,11 +2,11 @@ class Devise::OmniauthCallbacksController < DeviseController
|
|
2
2
|
prepend_before_filter { request.env["devise.skip_timeout"] = true }
|
3
3
|
|
4
4
|
def passthru
|
5
|
-
render :
|
5
|
+
render status: 404, text: "Not found. Authentication passthru."
|
6
6
|
end
|
7
7
|
|
8
8
|
def failure
|
9
|
-
set_flash_message :alert, :failure, :
|
9
|
+
set_flash_message :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
|
10
10
|
redirect_to after_omniauth_failure_path_for(resource_name)
|
11
11
|
end
|
12
12
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Devise::PasswordsController < DeviseController
|
2
2
|
prepend_before_filter :require_no_authentication
|
3
3
|
# Render the #edit only if coming from a reset password email link
|
4
|
-
append_before_filter :assert_reset_token_passed, :
|
4
|
+
append_before_filter :assert_reset_token_passed, only: :edit
|
5
5
|
|
6
6
|
# GET /resource/password/new
|
7
7
|
def new
|
@@ -11,9 +11,10 @@ class Devise::PasswordsController < DeviseController
|
|
11
11
|
# POST /resource/password
|
12
12
|
def create
|
13
13
|
self.resource = resource_class.send_reset_password_instructions(resource_params)
|
14
|
+
yield resource if block_given?
|
14
15
|
|
15
16
|
if successfully_sent?(resource)
|
16
|
-
respond_with({}, :
|
17
|
+
respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
|
17
18
|
else
|
18
19
|
respond_with(resource)
|
19
20
|
end
|
@@ -28,13 +29,14 @@ class Devise::PasswordsController < DeviseController
|
|
28
29
|
# PUT /resource/password
|
29
30
|
def update
|
30
31
|
self.resource = resource_class.reset_password_by_token(resource_params)
|
32
|
+
yield resource if block_given?
|
31
33
|
|
32
34
|
if resource.errors.empty?
|
33
35
|
resource.unlock_access! if unlockable?(resource)
|
34
36
|
flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
|
35
37
|
set_flash_message(:notice, flash_message) if is_flashing_format?
|
36
38
|
sign_in(resource_name, resource)
|
37
|
-
respond_with resource, :
|
39
|
+
respond_with resource, location: after_resetting_password_path_for(resource)
|
38
40
|
else
|
39
41
|
respond_with resource
|
40
42
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
class Devise::RegistrationsController < DeviseController
|
2
|
-
prepend_before_filter :require_no_authentication, :
|
3
|
-
prepend_before_filter :authenticate_scope!, :
|
2
|
+
prepend_before_filter :require_no_authentication, only: [ :new, :create, :cancel ]
|
3
|
+
prepend_before_filter :authenticate_scope!, only: [:edit, :update, :destroy]
|
4
4
|
|
5
5
|
# GET /resource/sign_up
|
6
6
|
def new
|
7
7
|
build_resource({})
|
8
|
+
@validatable = devise_mapping.validatable?
|
9
|
+
if @validatable
|
10
|
+
@minimum_password_length = resource_class.password_length.min
|
11
|
+
end
|
8
12
|
respond_with self.resource
|
9
13
|
end
|
10
14
|
|
@@ -12,18 +16,24 @@ class Devise::RegistrationsController < DeviseController
|
|
12
16
|
def create
|
13
17
|
build_resource(sign_up_params)
|
14
18
|
|
15
|
-
|
19
|
+
resource_saved = resource.save
|
20
|
+
yield resource if block_given?
|
21
|
+
if resource_saved
|
16
22
|
if resource.active_for_authentication?
|
17
23
|
set_flash_message :notice, :signed_up if is_flashing_format?
|
18
24
|
sign_up(resource_name, resource)
|
19
|
-
respond_with resource, :
|
25
|
+
respond_with resource, location: after_sign_up_path_for(resource)
|
20
26
|
else
|
21
27
|
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
|
22
28
|
expire_data_after_sign_in!
|
23
|
-
respond_with resource, :
|
29
|
+
respond_with resource, location: after_inactive_sign_up_path_for(resource)
|
24
30
|
end
|
25
31
|
else
|
26
32
|
clean_up_passwords resource
|
33
|
+
@validatable = devise_mapping.validatable?
|
34
|
+
if @validatable
|
35
|
+
@minimum_password_length = resource_class.password_length.min
|
36
|
+
end
|
27
37
|
respond_with resource
|
28
38
|
end
|
29
39
|
end
|
@@ -40,14 +50,16 @@ class Devise::RegistrationsController < DeviseController
|
|
40
50
|
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
41
51
|
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
|
42
52
|
|
43
|
-
|
53
|
+
resource_updated = update_resource(resource, account_update_params)
|
54
|
+
yield resource if block_given?
|
55
|
+
if resource_updated
|
44
56
|
if is_flashing_format?
|
45
57
|
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
|
46
58
|
:update_needs_confirmation : :updated
|
47
59
|
set_flash_message :notice, flash_key
|
48
60
|
end
|
49
|
-
sign_in resource_name, resource, :
|
50
|
-
respond_with resource, :
|
61
|
+
sign_in resource_name, resource, bypass: true
|
62
|
+
respond_with resource, location: after_update_path_for(resource)
|
51
63
|
else
|
52
64
|
clean_up_passwords resource
|
53
65
|
respond_with resource
|
@@ -59,6 +71,7 @@ class Devise::RegistrationsController < DeviseController
|
|
59
71
|
resource.destroy
|
60
72
|
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
|
61
73
|
set_flash_message :notice, :destroyed if is_flashing_format?
|
74
|
+
yield resource if block_given?
|
62
75
|
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
|
63
76
|
end
|
64
77
|
|
@@ -107,7 +120,10 @@ class Devise::RegistrationsController < DeviseController
|
|
107
120
|
# The path used after sign up for inactive accounts. You need to overwrite
|
108
121
|
# this method in your own RegistrationsController.
|
109
122
|
def after_inactive_sign_up_path_for(resource)
|
110
|
-
|
123
|
+
scope = Devise::Mapping.find_scope!(resource)
|
124
|
+
router_name = Devise.mappings[scope].router_name
|
125
|
+
context = router_name ? send(router_name) : self
|
126
|
+
context.respond_to?(:root_path) ? context.root_path : "/"
|
111
127
|
end
|
112
128
|
|
113
129
|
# The default url to be used after updating a resource. You need to overwrite
|
@@ -118,7 +134,7 @@ class Devise::RegistrationsController < DeviseController
|
|
118
134
|
|
119
135
|
# Authenticates the current scope and gets the current resource from the session.
|
120
136
|
def authenticate_scope!
|
121
|
-
send(:"authenticate_#{resource_name}!", :
|
137
|
+
send(:"authenticate_#{resource_name}!", force: true)
|
122
138
|
self.resource = send(:"current_#{resource_name}")
|
123
139
|
end
|
124
140
|
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class Devise::SessionsController < DeviseController
|
2
|
-
prepend_before_filter :require_no_authentication, :
|
3
|
-
prepend_before_filter :allow_params_authentication!, :
|
4
|
-
prepend_before_filter :only
|
2
|
+
prepend_before_filter :require_no_authentication, only: [ :new, :create ]
|
3
|
+
prepend_before_filter :allow_params_authentication!, only: :create
|
4
|
+
prepend_before_filter :verify_signed_out_user, only: :destroy
|
5
|
+
prepend_before_filter only: [ :create, :destroy ] { request.env["devise.skip_timeout"] = true }
|
5
6
|
|
6
7
|
# GET /resource/sign_in
|
7
8
|
def new
|
@@ -15,21 +16,16 @@ class Devise::SessionsController < DeviseController
|
|
15
16
|
self.resource = warden.authenticate!(auth_options)
|
16
17
|
set_flash_message(:notice, :signed_in) if is_flashing_format?
|
17
18
|
sign_in(resource_name, resource)
|
18
|
-
|
19
|
+
yield resource if block_given?
|
20
|
+
respond_with resource, location: after_sign_in_path_for(resource)
|
19
21
|
end
|
20
22
|
|
21
23
|
# DELETE /resource/sign_out
|
22
24
|
def destroy
|
23
|
-
redirect_path = after_sign_out_path_for(resource_name)
|
24
25
|
signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
25
26
|
set_flash_message :notice, :signed_out if signed_out && is_flashing_format?
|
26
|
-
|
27
|
-
|
28
|
-
# support returning empty response on GET request
|
29
|
-
respond_to do |format|
|
30
|
-
format.all { head :no_content }
|
31
|
-
format.any(*navigational_formats) { redirect_to redirect_path }
|
32
|
-
end
|
27
|
+
yield if block_given?
|
28
|
+
respond_to_on_destroy
|
33
29
|
end
|
34
30
|
|
35
31
|
protected
|
@@ -42,10 +38,39 @@ class Devise::SessionsController < DeviseController
|
|
42
38
|
methods = resource_class.authentication_keys.dup
|
43
39
|
methods = methods.keys if methods.is_a?(Hash)
|
44
40
|
methods << :password if resource.respond_to?(:password)
|
45
|
-
{ :
|
41
|
+
{ methods: methods, only: [:password] }
|
46
42
|
end
|
47
43
|
|
48
44
|
def auth_options
|
49
|
-
{ :
|
45
|
+
{ scope: resource_name, recall: "#{controller_path}#new" }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Check if there is no signed in user before doing the sign out.
|
51
|
+
#
|
52
|
+
# If there is no signed in user, it will set the flash message and redirect
|
53
|
+
# to the after_sign_out path.
|
54
|
+
def verify_signed_out_user
|
55
|
+
if all_signed_out?
|
56
|
+
set_flash_message :notice, :already_signed_out if is_flashing_format?
|
57
|
+
|
58
|
+
respond_to_on_destroy
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def all_signed_out?
|
63
|
+
users = Devise.mappings.keys.map { |s| warden.user(scope: s, run_callbacks: false) }
|
64
|
+
|
65
|
+
users.all?(&:blank?)
|
66
|
+
end
|
67
|
+
|
68
|
+
def respond_to_on_destroy
|
69
|
+
# We actually need to hardcode this as Rails default responder doesn't
|
70
|
+
# support returning empty response on GET request
|
71
|
+
respond_to do |format|
|
72
|
+
format.all { head :no_content }
|
73
|
+
format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name) }
|
74
|
+
end
|
50
75
|
end
|
51
76
|
end
|
@@ -9,9 +9,10 @@ class Devise::UnlocksController < DeviseController
|
|
9
9
|
# POST /resource/unlock
|
10
10
|
def create
|
11
11
|
self.resource = resource_class.send_unlock_instructions(resource_params)
|
12
|
+
yield resource if block_given?
|
12
13
|
|
13
14
|
if successfully_sent?(resource)
|
14
|
-
respond_with({}, :
|
15
|
+
respond_with({}, location: after_sending_unlock_instructions_path_for(resource))
|
15
16
|
else
|
16
17
|
respond_with(resource)
|
17
18
|
end
|
@@ -20,12 +21,13 @@ class Devise::UnlocksController < DeviseController
|
|
20
21
|
# GET /resource/unlock?unlock_token=abcdef
|
21
22
|
def show
|
22
23
|
self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
|
24
|
+
yield resource if block_given?
|
23
25
|
|
24
26
|
if resource.errors.empty?
|
25
27
|
set_flash_message :notice, :unlocked if is_flashing_format?
|
26
28
|
respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
|
27
29
|
else
|
28
|
-
respond_with_navigational(resource.errors, :
|
30
|
+
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|