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.

Files changed (187) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +18 -3
  3. data/CHANGELOG.md +82 -9
  4. data/CONTRIBUTING.md +2 -2
  5. data/Gemfile +7 -9
  6. data/Gemfile.lock +102 -96
  7. data/MIT-LICENSE +1 -1
  8. data/README.md +94 -42
  9. data/Rakefile +1 -1
  10. data/app/controllers/devise/confirmations_controller.rb +5 -3
  11. data/app/controllers/devise/omniauth_callbacks_controller.rb +2 -2
  12. data/app/controllers/devise/passwords_controller.rb +5 -3
  13. data/app/controllers/devise/registrations_controller.rb +26 -10
  14. data/app/controllers/devise/sessions_controller.rb +39 -14
  15. data/app/controllers/devise/unlocks_controller.rb +4 -2
  16. data/app/controllers/devise_controller.rb +6 -6
  17. data/app/helpers/devise_helper.rb +2 -2
  18. data/app/views/devise/confirmations/new.html.erb +2 -2
  19. data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
  20. data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
  21. data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
  22. data/app/views/devise/passwords/edit.html.erb +3 -3
  23. data/app/views/devise/passwords/new.html.erb +2 -2
  24. data/app/views/devise/registrations/edit.html.erb +6 -6
  25. data/app/views/devise/registrations/new.html.erb +5 -5
  26. data/app/views/devise/sessions/new.html.erb +5 -5
  27. data/app/views/devise/shared/_links.erb +1 -1
  28. data/app/views/devise/unlocks/new.html.erb +2 -2
  29. data/config/locales/en.yml +17 -16
  30. data/devise.gemspec +2 -2
  31. data/gemfiles/{Gemfile.rails-3.2.x → Gemfile.rails-3.2-stable} +8 -10
  32. data/gemfiles/Gemfile.rails-3.2-stable.lock +166 -0
  33. data/gemfiles/Gemfile.rails-4.0-stable +29 -0
  34. data/gemfiles/Gemfile.rails-4.0-stable.lock +162 -0
  35. data/gemfiles/Gemfile.rails-head +32 -0
  36. data/gemfiles/Gemfile.rails-head.lock +190 -0
  37. data/lib/devise/controllers/helpers.rb +84 -29
  38. data/lib/devise/controllers/rememberable.rb +3 -3
  39. data/lib/devise/controllers/scoped_views.rb +1 -1
  40. data/lib/devise/controllers/sign_in_out.rb +9 -10
  41. data/lib/devise/controllers/store_location.rb +56 -0
  42. data/lib/devise/controllers/url_helpers.rb +3 -1
  43. data/lib/devise/failure_app.rb +12 -10
  44. data/lib/devise/hooks/activatable.rb +5 -6
  45. data/lib/devise/hooks/csrf_cleaner.rb +3 -1
  46. data/lib/devise/hooks/lockable.rb +1 -1
  47. data/lib/devise/hooks/proxy.rb +2 -2
  48. data/lib/devise/hooks/rememberable.rb +2 -2
  49. data/lib/devise/hooks/timeoutable.rb +10 -3
  50. data/lib/devise/hooks/trackable.rb +1 -1
  51. data/lib/devise/mailers/helpers.rb +8 -8
  52. data/lib/devise/mapping.rb +4 -1
  53. data/lib/devise/models/authenticatable.rb +5 -5
  54. data/lib/devise/models/confirmable.rb +14 -14
  55. data/lib/devise/models/database_authenticatable.rb +18 -5
  56. data/lib/devise/models/lockable.rb +14 -11
  57. data/lib/devise/models/omniauthable.rb +1 -1
  58. data/lib/devise/models/recoverable.rb +23 -7
  59. data/lib/devise/models/rememberable.rb +6 -6
  60. data/lib/devise/models/timeoutable.rb +2 -2
  61. data/lib/devise/models/trackable.rb +5 -2
  62. data/lib/devise/models/validatable.rb +6 -6
  63. data/lib/devise/modules.rb +10 -10
  64. data/lib/devise/omniauth/url_helpers.rb +2 -2
  65. data/lib/devise/orm/active_record.rb +1 -1
  66. data/lib/devise/orm/mongoid.rb +1 -1
  67. data/lib/devise/rails/routes.rb +107 -78
  68. data/lib/devise/rails.rb +7 -1
  69. data/lib/devise/strategies/authenticatable.rb +11 -4
  70. data/lib/devise/strategies/base.rb +1 -1
  71. data/lib/devise/strategies/database_authenticatable.rb +7 -4
  72. data/lib/devise/test_helpers.rb +2 -2
  73. data/lib/devise/time_inflector.rb +2 -2
  74. data/lib/devise/version.rb +1 -1
  75. data/lib/devise.rb +15 -10
  76. data/lib/generators/active_record/devise_generator.rb +27 -10
  77. data/lib/generators/active_record/templates/migration.rb +4 -4
  78. data/lib/generators/active_record/templates/migration_existing.rb +4 -4
  79. data/lib/generators/devise/devise_generator.rb +5 -3
  80. data/lib/generators/devise/install_generator.rb +5 -0
  81. data/lib/generators/devise/views_generator.rb +31 -18
  82. data/lib/generators/mongoid/devise_generator.rb +20 -19
  83. data/lib/generators/templates/README +4 -4
  84. data/lib/generators/templates/devise.rb +20 -11
  85. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  86. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  87. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  88. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +2 -2
  89. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +4 -4
  90. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +2 -2
  91. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +6 -6
  92. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +4 -4
  93. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +4 -4
  94. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +2 -2
  95. data/script/cached-bundle +49 -0
  96. data/script/s3-put +71 -0
  97. data/test/controllers/custom_registrations_controller_test.rb +35 -0
  98. data/test/controllers/helpers_test.rb +89 -31
  99. data/test/controllers/internal_helpers_test.rb +11 -8
  100. data/test/controllers/passwords_controller_test.rb +1 -1
  101. data/test/controllers/sessions_controller_test.rb +29 -25
  102. data/test/controllers/url_helpers_test.rb +4 -4
  103. data/test/delegator_test.rb +1 -1
  104. data/test/devise_test.rb +21 -8
  105. data/test/failure_app_test.rb +61 -25
  106. data/test/generators/active_record_generator_test.rb +10 -4
  107. data/test/generators/devise_generator_test.rb +2 -2
  108. data/test/generators/mongoid_generator_test.rb +3 -3
  109. data/test/generators/views_generator_test.rb +30 -1
  110. data/test/helpers/devise_helper_test.rb +14 -13
  111. data/test/integration/authenticatable_test.rb +61 -45
  112. data/test/integration/confirmable_test.rb +95 -55
  113. data/test/integration/database_authenticatable_test.rb +16 -16
  114. data/test/integration/http_authenticatable_test.rb +12 -12
  115. data/test/integration/lockable_test.rb +43 -43
  116. data/test/integration/omniauthable_test.rb +3 -3
  117. data/test/integration/recoverable_test.rb +53 -53
  118. data/test/integration/registerable_test.rb +90 -80
  119. data/test/integration/rememberable_test.rb +15 -15
  120. data/test/integration/timeoutable_test.rb +27 -16
  121. data/test/integration/trackable_test.rb +4 -4
  122. data/test/mailers/confirmation_instructions_test.rb +7 -7
  123. data/test/mailers/reset_password_instructions_test.rb +6 -6
  124. data/test/mailers/unlock_instructions_test.rb +5 -5
  125. data/test/mapping_test.rb +3 -3
  126. data/test/models/authenticatable_test.rb +3 -3
  127. data/test/models/confirmable_test.rb +32 -32
  128. data/test/models/database_authenticatable_test.rb +32 -27
  129. data/test/models/lockable_test.rb +57 -33
  130. data/test/models/recoverable_test.rb +34 -22
  131. data/test/models/rememberable_test.rb +29 -14
  132. data/test/models/serializable_test.rb +8 -8
  133. data/test/models/timeoutable_test.rb +1 -1
  134. data/test/models/trackable_test.rb +28 -0
  135. data/test/models/validatable_test.rb +13 -13
  136. data/test/omniauth/config_test.rb +4 -4
  137. data/test/omniauth/url_helpers_test.rb +3 -3
  138. data/test/orm/mongoid.rb +1 -1
  139. data/test/parameter_sanitizer_test.rb +1 -1
  140. data/test/rails_app/app/active_record/shim.rb +1 -1
  141. data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
  142. data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
  143. data/test/rails_app/app/controllers/admins/sessions_controller.rb +1 -1
  144. data/test/rails_app/app/controllers/admins_controller.rb +1 -1
  145. data/test/rails_app/app/controllers/application_controller.rb +5 -2
  146. data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
  147. data/test/rails_app/app/controllers/custom/registrations_controller.rb +21 -0
  148. data/test/rails_app/app/controllers/home_controller.rb +1 -1
  149. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +1 -1
  150. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +1 -1
  151. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +4 -4
  152. data/test/rails_app/app/controllers/users_controller.rb +6 -6
  153. data/test/rails_app/app/mailers/users/mailer.rb +4 -4
  154. data/test/rails_app/app/mongoid/admin.rb +11 -11
  155. data/test/rails_app/app/mongoid/shim.rb +2 -2
  156. data/test/rails_app/app/mongoid/user.rb +19 -19
  157. data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
  158. data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
  159. data/test/rails_app/app/views/admins/sessions/new.html.erb +1 -1
  160. data/test/rails_app/app/views/home/admin_dashboard.html.erb +1 -1
  161. data/test/rails_app/app/views/home/index.html.erb +1 -1
  162. data/test/rails_app/app/views/home/join.html.erb +1 -1
  163. data/test/rails_app/app/views/home/user_dashboard.html.erb +1 -1
  164. data/test/rails_app/app/views/layouts/application.html.erb +1 -1
  165. data/test/rails_app/config/application.rb +2 -2
  166. data/test/rails_app/config/boot.rb +7 -1
  167. data/test/rails_app/config/environments/development.rb +0 -4
  168. data/test/rails_app/config/environments/production.rb +0 -4
  169. data/test/rails_app/config/initializers/devise.rb +7 -5
  170. data/test/rails_app/config/initializers/secret_token.rb +1 -1
  171. data/test/rails_app/config/routes.rb +60 -42
  172. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +7 -7
  173. data/test/rails_app/db/schema.rb +21 -17
  174. data/test/rails_app/lib/shared_admin.rb +4 -4
  175. data/test/rails_app/lib/shared_user.rb +1 -1
  176. data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
  177. data/test/routes_test.rb +72 -58
  178. data/test/support/action_controller/record_identifier.rb +10 -0
  179. data/test/support/assertions.rb +2 -3
  180. data/test/support/helpers.rb +4 -4
  181. data/test/support/integration.rb +14 -14
  182. data/test/support/mongoid.yml +6 -0
  183. data/test/test_helper.rb +2 -7
  184. data/test/test_helpers_test.rb +25 -35
  185. data/test/test_models.rb +12 -5
  186. metadata +53 -38
  187. 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 on progress.
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 the maintainers listed at the bottom of the README.
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/chapters/modeling-and-viewing-users-two#top
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 by the class name used for the applications 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. Next, you'll usually run `rake db:migrate` as the generator will have created a migration file (if your ORM supports them). This generator also configures your config/routes.rb file to point to the Devise controller.
113
+ Replace MODEL with the class name used for the application’s users (its 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
- Note that you should re-start your app here if you've already started it. Otherwise you'll run into strange errors like users being unable to login and the route helpers being undefined.
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 before_filter:
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
- before_filter :authenticate_user!
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. 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:
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 overwrite `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.
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 devise model is not called "user" but "member", then the helpers you should use are:
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
- before_filter :authenticate_member!
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 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:
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, :stretches => 20
178
+ devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 20
175
179
  ```
176
180
 
177
- Besides :stretches, you can define :pepper, :encryptor, :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.
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 permited parameters by default are:
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
- before_filter :configure_permitted_parameters, if: :devise_controller?
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
- To completely change Devise defaults or invoke custom behaviour, you can also pass a block:
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 "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 "config/initializers/devise.rb".
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 "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:
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/controller/admins/` directory.
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, :controllers => { :sessions => "admins/sessions" }
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
- 3. And since we changed the controller, it won't use the `"devise/sessions"` views, so remember to copy `"devise/sessions"` to `"admin/sessions"`.
314
+ Or you can simply add new behaviour to it:
277
315
 
278
- 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 specific keys or at least remove the `:timedout` key from the hash as Devise adds this key in some circumstances, this key is not meant for display.
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, :path => "auth", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
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", :to => "devise/sessions#new"
344
+ get "sign_in", to: "devise/sessions#new"
295
345
  end
296
346
  ```
297
347
 
298
- 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.
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 tests 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:
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, :type => :controller
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 is important to keep in mind:
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', :scope => 'user,public_repo'
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 [CanCan](https://github.com/ryanb/cancan).
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 devise on Heroku with Ruby on Rails 3.1 requires setting:
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-2013 Plataformatec. http://plataformatec.com.br
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
@@ -4,7 +4,7 @@ require 'rake/testtask'
4
4
  require 'rdoc/task'
5
5
 
6
6
  desc 'Default: run tests for all ORMs.'
7
- task :default => :test
7
+ task default: :test
8
8
 
9
9
  desc 'Run Devise tests for all ORMs.'
10
10
  task :pre_commit do
@@ -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({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
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, :status => :unprocessable_entity){ render :new }
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 :status => 404, :text => "Not found. Authentication passthru."
5
+ render status: 404, text: "Not found. Authentication passthru."
6
6
  end
7
7
 
8
8
  def failure
9
- set_flash_message :alert, :failure, :kind => OmniAuth::Utils.camelize(failed_strategy.name), :reason => failure_message
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, :only => :edit
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({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
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, :location => after_resetting_password_path_for(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, :only => [ :new, :create, :cancel ]
3
- prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
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
- if resource.save
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, :location => after_sign_up_path_for(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, :location => after_inactive_sign_up_path_for(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
- if update_resource(resource, account_update_params)
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, :bypass => true
50
- respond_with resource, :location => after_update_path_for(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
- respond_to?(:root_path) ? root_path : "/"
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}!", :force => true)
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, :only => [ :new, :create ]
3
- prepend_before_filter :allow_params_authentication!, :only => :create
4
- prepend_before_filter :only => [ :create, :destroy ] { request.env["devise.skip_timeout"] = true }
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
- respond_with resource, :location => after_sign_in_path_for(resource)
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
- # We actually need to hardcode this as Rails default responder doesn't
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
- { :methods => methods, :only => [:password] }
41
+ { methods: methods, only: [:password] }
46
42
  end
47
43
 
48
44
  def auth_options
49
- { :scope => resource_name, :recall => "#{controller_path}#new" }
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({}, :location => after_sending_unlock_instructions_path_for(resource))
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, :status => :unprocessable_entity){ render :new }
30
+ respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
29
31
  end
30
32
  end
31
33