devise 4.1.1 → 5.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +68 -111
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +315 -98
  5. data/app/controllers/devise/confirmations_controller.rb +3 -0
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +7 -5
  7. data/app/controllers/devise/passwords_controller.rb +10 -2
  8. data/app/controllers/devise/registrations_controller.rb +42 -20
  9. data/app/controllers/devise/sessions_controller.rb +9 -7
  10. data/app/controllers/devise/unlocks_controller.rb +3 -0
  11. data/app/controllers/devise_controller.rb +19 -3
  12. data/app/helpers/devise_helper.rb +3 -23
  13. data/app/mailers/devise/mailer.rb +10 -4
  14. data/app/views/devise/confirmations/new.html.erb +3 -3
  15. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  16. data/app/views/devise/passwords/edit.html.erb +6 -6
  17. data/app/views/devise/passwords/new.html.erb +4 -4
  18. data/app/views/devise/registrations/edit.html.erb +13 -10
  19. data/app/views/devise/registrations/new.html.erb +9 -9
  20. data/app/views/devise/sessions/new.html.erb +8 -8
  21. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  22. data/app/views/devise/shared/_links.html.erb +13 -13
  23. data/app/views/devise/unlocks/new.html.erb +3 -3
  24. data/config/locales/en.yml +5 -2
  25. data/lib/devise/controllers/helpers.rb +24 -9
  26. data/lib/devise/controllers/rememberable.rb +3 -1
  27. data/lib/devise/controllers/responder.rb +35 -0
  28. data/lib/devise/controllers/scoped_views.rb +2 -0
  29. data/lib/devise/controllers/sign_in_out.rb +31 -21
  30. data/lib/devise/controllers/store_location.rb +25 -7
  31. data/lib/devise/controllers/url_helpers.rb +3 -1
  32. data/lib/devise/delegator.rb +2 -0
  33. data/lib/devise/encryptor.rb +2 -0
  34. data/lib/devise/failure_app.rb +71 -38
  35. data/lib/devise/hooks/activatable.rb +3 -1
  36. data/lib/devise/hooks/csrf_cleaner.rb +8 -1
  37. data/lib/devise/hooks/forgetable.rb +2 -0
  38. data/lib/devise/hooks/lockable.rb +4 -2
  39. data/lib/devise/hooks/proxy.rb +3 -1
  40. data/lib/devise/hooks/rememberable.rb +2 -0
  41. data/lib/devise/hooks/timeoutable.rb +5 -3
  42. data/lib/devise/hooks/trackable.rb +2 -0
  43. data/lib/devise/mailers/helpers.rb +15 -18
  44. data/lib/devise/mapping.rb +4 -2
  45. data/lib/devise/models/authenticatable.rb +58 -44
  46. data/lib/devise/models/confirmable.rb +52 -14
  47. data/lib/devise/models/database_authenticatable.rb +52 -20
  48. data/lib/devise/models/lockable.rb +19 -5
  49. data/lib/devise/models/omniauthable.rb +4 -2
  50. data/lib/devise/models/recoverable.rb +22 -21
  51. data/lib/devise/models/registerable.rb +4 -0
  52. data/lib/devise/models/rememberable.rb +6 -4
  53. data/lib/devise/models/timeoutable.rb +3 -1
  54. data/lib/devise/models/trackable.rb +15 -1
  55. data/lib/devise/models/validatable.rb +10 -6
  56. data/lib/devise/models.rb +4 -1
  57. data/lib/devise/modules.rb +2 -0
  58. data/lib/devise/omniauth/config.rb +2 -0
  59. data/lib/devise/omniauth/url_helpers.rb +2 -51
  60. data/lib/devise/omniauth.rb +4 -5
  61. data/lib/devise/orm/active_record.rb +5 -1
  62. data/lib/devise/orm/mongoid.rb +6 -2
  63. data/lib/devise/orm.rb +80 -0
  64. data/lib/devise/parameter_filter.rb +4 -0
  65. data/lib/devise/parameter_sanitizer.rb +16 -58
  66. data/lib/devise/rails/routes.rb +12 -11
  67. data/lib/devise/rails/warden_compat.rb +2 -0
  68. data/lib/devise/rails.rb +16 -6
  69. data/lib/devise/strategies/authenticatable.rb +3 -1
  70. data/lib/devise/strategies/base.rb +2 -0
  71. data/lib/devise/strategies/database_authenticatable.rb +8 -1
  72. data/lib/devise/strategies/rememberable.rb +2 -0
  73. data/lib/devise/test/controller_helpers.rb +156 -0
  74. data/lib/devise/test/integration_helpers.rb +63 -0
  75. data/lib/devise/time_inflector.rb +2 -0
  76. data/lib/devise/token_generator.rb +2 -0
  77. data/lib/devise/version.rb +3 -1
  78. data/lib/devise.rb +69 -28
  79. data/lib/generators/active_record/devise_generator.rb +38 -16
  80. data/lib/generators/active_record/templates/migration.rb +3 -1
  81. data/lib/generators/active_record/templates/migration_existing.rb +2 -0
  82. data/lib/generators/devise/controllers_generator.rb +4 -2
  83. data/lib/generators/devise/devise_generator.rb +5 -3
  84. data/lib/generators/devise/install_generator.rb +3 -5
  85. data/lib/generators/devise/orm_helpers.rb +5 -3
  86. data/lib/generators/devise/views_generator.rb +8 -9
  87. data/lib/generators/mongoid/devise_generator.rb +7 -5
  88. data/lib/generators/templates/README +9 -8
  89. data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
  90. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +3 -1
  91. data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
  92. data/lib/generators/templates/controllers/registrations_controller.rb +4 -2
  93. data/lib/generators/templates/controllers/sessions_controller.rb +3 -1
  94. data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
  95. data/lib/generators/templates/devise.rb +59 -11
  96. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  97. data/lib/generators/templates/markerb/password_change.markerb +2 -2
  98. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
  99. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
  100. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +5 -2
  101. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +12 -4
  102. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
  103. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
  104. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
  105. metadata +23 -302
  106. data/.gitignore +0 -10
  107. data/.travis.yml +0 -44
  108. data/.yardopts +0 -9
  109. data/CODE_OF_CONDUCT.md +0 -22
  110. data/CONTRIBUTING.md +0 -16
  111. data/Gemfile +0 -30
  112. data/Gemfile.lock +0 -182
  113. data/Rakefile +0 -36
  114. data/bin/test +0 -13
  115. data/devise.gemspec +0 -26
  116. data/devise.png +0 -0
  117. data/gemfiles/Gemfile.rails-4.1-stable +0 -30
  118. data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -170
  119. data/gemfiles/Gemfile.rails-4.2-stable +0 -30
  120. data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
  121. data/gemfiles/Gemfile.rails-5.0-beta +0 -37
  122. data/gemfiles/Gemfile.rails-5.0-beta.lock +0 -199
  123. data/lib/devise/test_helpers.rb +0 -137
  124. data/test/controllers/custom_registrations_controller_test.rb +0 -40
  125. data/test/controllers/custom_strategy_test.rb +0 -64
  126. data/test/controllers/helper_methods_test.rb +0 -22
  127. data/test/controllers/helpers_test.rb +0 -316
  128. data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -51
  129. data/test/controllers/internal_helpers_test.rb +0 -127
  130. data/test/controllers/load_hooks_controller_test.rb +0 -19
  131. data/test/controllers/passwords_controller_test.rb +0 -32
  132. data/test/controllers/sessions_controller_test.rb +0 -106
  133. data/test/controllers/url_helpers_test.rb +0 -65
  134. data/test/delegator_test.rb +0 -19
  135. data/test/devise_test.rb +0 -107
  136. data/test/failure_app_test.rb +0 -320
  137. data/test/generators/active_record_generator_test.rb +0 -83
  138. data/test/generators/controllers_generator_test.rb +0 -48
  139. data/test/generators/devise_generator_test.rb +0 -39
  140. data/test/generators/install_generator_test.rb +0 -24
  141. data/test/generators/mongoid_generator_test.rb +0 -23
  142. data/test/generators/views_generator_test.rb +0 -103
  143. data/test/helpers/devise_helper_test.rb +0 -49
  144. data/test/integration/authenticatable_test.rb +0 -698
  145. data/test/integration/confirmable_test.rb +0 -324
  146. data/test/integration/database_authenticatable_test.rb +0 -95
  147. data/test/integration/http_authenticatable_test.rb +0 -106
  148. data/test/integration/lockable_test.rb +0 -240
  149. data/test/integration/omniauthable_test.rb +0 -135
  150. data/test/integration/recoverable_test.rb +0 -347
  151. data/test/integration/registerable_test.rb +0 -357
  152. data/test/integration/rememberable_test.rb +0 -211
  153. data/test/integration/timeoutable_test.rb +0 -184
  154. data/test/integration/trackable_test.rb +0 -92
  155. data/test/mailers/confirmation_instructions_test.rb +0 -115
  156. data/test/mailers/reset_password_instructions_test.rb +0 -96
  157. data/test/mailers/unlock_instructions_test.rb +0 -91
  158. data/test/mapping_test.rb +0 -134
  159. data/test/models/authenticatable_test.rb +0 -23
  160. data/test/models/confirmable_test.rb +0 -511
  161. data/test/models/database_authenticatable_test.rb +0 -269
  162. data/test/models/lockable_test.rb +0 -350
  163. data/test/models/omniauthable_test.rb +0 -7
  164. data/test/models/recoverable_test.rb +0 -251
  165. data/test/models/registerable_test.rb +0 -7
  166. data/test/models/rememberable_test.rb +0 -169
  167. data/test/models/serializable_test.rb +0 -49
  168. data/test/models/timeoutable_test.rb +0 -51
  169. data/test/models/trackable_test.rb +0 -41
  170. data/test/models/validatable_test.rb +0 -119
  171. data/test/models_test.rb +0 -153
  172. data/test/omniauth/config_test.rb +0 -57
  173. data/test/omniauth/url_helpers_test.rb +0 -51
  174. data/test/orm/active_record.rb +0 -17
  175. data/test/orm/mongoid.rb +0 -13
  176. data/test/parameter_sanitizer_test.rb +0 -131
  177. data/test/rails_app/Rakefile +0 -6
  178. data/test/rails_app/app/active_record/admin.rb +0 -6
  179. data/test/rails_app/app/active_record/shim.rb +0 -2
  180. data/test/rails_app/app/active_record/user.rb +0 -7
  181. data/test/rails_app/app/active_record/user_on_engine.rb +0 -7
  182. data/test/rails_app/app/active_record/user_on_main_app.rb +0 -7
  183. data/test/rails_app/app/active_record/user_without_email.rb +0 -8
  184. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -6
  185. data/test/rails_app/app/controllers/admins_controller.rb +0 -6
  186. data/test/rails_app/app/controllers/application_controller.rb +0 -11
  187. data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -30
  188. data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -31
  189. data/test/rails_app/app/controllers/home_controller.rb +0 -29
  190. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -2
  191. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -2
  192. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -14
  193. data/test/rails_app/app/controllers/users_controller.rb +0 -31
  194. data/test/rails_app/app/helpers/application_helper.rb +0 -3
  195. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -3
  196. data/test/rails_app/app/mailers/users/mailer.rb +0 -3
  197. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -4
  198. data/test/rails_app/app/mongoid/admin.rb +0 -29
  199. data/test/rails_app/app/mongoid/shim.rb +0 -23
  200. data/test/rails_app/app/mongoid/user.rb +0 -39
  201. data/test/rails_app/app/mongoid/user_on_engine.rb +0 -39
  202. data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -39
  203. data/test/rails_app/app/mongoid/user_without_email.rb +0 -33
  204. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  205. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  206. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  207. data/test/rails_app/app/views/home/index.html.erb +0 -1
  208. data/test/rails_app/app/views/home/join.html.erb +0 -1
  209. data/test/rails_app/app/views/home/private.html.erb +0 -1
  210. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  211. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  212. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  213. data/test/rails_app/app/views/users/index.html.erb +0 -1
  214. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  215. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  216. data/test/rails_app/bin/bundle +0 -3
  217. data/test/rails_app/bin/rails +0 -4
  218. data/test/rails_app/bin/rake +0 -4
  219. data/test/rails_app/config/application.rb +0 -44
  220. data/test/rails_app/config/boot.rb +0 -14
  221. data/test/rails_app/config/database.yml +0 -18
  222. data/test/rails_app/config/environment.rb +0 -5
  223. data/test/rails_app/config/environments/development.rb +0 -30
  224. data/test/rails_app/config/environments/production.rb +0 -84
  225. data/test/rails_app/config/environments/test.rb +0 -46
  226. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  227. data/test/rails_app/config/initializers/devise.rb +0 -180
  228. data/test/rails_app/config/initializers/inflections.rb +0 -2
  229. data/test/rails_app/config/initializers/secret_token.rb +0 -3
  230. data/test/rails_app/config/initializers/session_store.rb +0 -1
  231. data/test/rails_app/config/routes.rb +0 -126
  232. data/test/rails_app/config.ru +0 -4
  233. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -71
  234. data/test/rails_app/db/schema.rb +0 -55
  235. data/test/rails_app/lib/shared_admin.rb +0 -17
  236. data/test/rails_app/lib/shared_user.rb +0 -30
  237. data/test/rails_app/lib/shared_user_without_email.rb +0 -26
  238. data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -13
  239. data/test/rails_app/public/404.html +0 -26
  240. data/test/rails_app/public/422.html +0 -26
  241. data/test/rails_app/public/500.html +0 -26
  242. data/test/rails_app/public/favicon.ico +0 -0
  243. data/test/rails_test.rb +0 -9
  244. data/test/routes_test.rb +0 -279
  245. data/test/support/action_controller/record_identifier.rb +0 -10
  246. data/test/support/assertions.rb +0 -39
  247. data/test/support/helpers.rb +0 -77
  248. data/test/support/http_method_compatibility.rb +0 -51
  249. data/test/support/integration.rb +0 -92
  250. data/test/support/locale/en.yml +0 -8
  251. data/test/support/mongoid.yml +0 -6
  252. data/test/support/webrat/integrations/rails.rb +0 -33
  253. data/test/test_helper.rb +0 -34
  254. data/test/test_helpers_test.rb +0 -178
  255. data/test/test_models.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Devise::ConfirmationsController < DeviseController
2
4
  # GET /resource/confirmation/new
3
5
  def new
@@ -25,6 +27,7 @@ class Devise::ConfirmationsController < DeviseController
25
27
  set_flash_message!(:notice, :confirmed)
26
28
  respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
27
29
  else
30
+ # TODO: use `error_status` when the default changes to `:unprocessable_entity` / `:unprocessable_content`.
28
31
  respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
29
32
  end
30
33
  end
@@ -1,26 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Devise::OmniauthCallbacksController < DeviseController
2
4
  prepend_before_action { request.env["devise.skip_timeout"] = true }
3
5
 
4
6
  def passthru
5
- render status: 404, text: "Not found. Authentication passthru."
7
+ render status: 404, plain: "Not found. Authentication passthru."
6
8
  end
7
9
 
8
10
  def failure
9
- set_flash_message :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
11
+ set_flash_message! :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
10
12
  redirect_to after_omniauth_failure_path_for(resource_name)
11
13
  end
12
14
 
13
15
  protected
14
16
 
15
17
  def failed_strategy
16
- request.respond_to?(:get_header) ? request.get_header("omniauth.error.strategy") : env["omniauth.error.strategy"]
18
+ request.respond_to?(:get_header) ? request.get_header("omniauth.error.strategy") : request.env["omniauth.error.strategy"]
17
19
  end
18
20
 
19
21
  def failure_message
20
- exception = request.respond_to?(:get_header) ? request.get_header("omniauth.error") : env["omniauth.error"]
22
+ exception = request.respond_to?(:get_header) ? request.get_header("omniauth.error") : request.env["omniauth.error"]
21
23
  error = exception.error_reason if exception.respond_to?(:error_reason)
22
24
  error ||= exception.error if exception.respond_to?(:error)
23
- error ||= (request.respond_to?(:get_header) ? request.get_header("omniauth.error.type") : env["omniauth.error.type"]).to_s
25
+ error ||= (request.respond_to?(:get_header) ? request.get_header("omniauth.error.type") : request.env["omniauth.error.type"]).to_s
24
26
  error.to_s.humanize if error
25
27
  end
26
28
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Devise::PasswordsController < DeviseController
2
4
  prepend_before_action :require_no_authentication
3
5
  # Render the #edit only if coming from a reset password email link
@@ -34,9 +36,10 @@ class Devise::PasswordsController < DeviseController
34
36
 
35
37
  if resource.errors.empty?
36
38
  resource.unlock_access! if unlockable?(resource)
37
- if Devise.sign_in_after_reset_password
39
+ if sign_in_after_reset_password?
38
40
  flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
39
41
  set_flash_message!(:notice, flash_message)
42
+ resource.after_database_authentication
40
43
  sign_in(resource_name, resource)
41
44
  else
42
45
  set_flash_message!(:notice, :updated_not_active)
@@ -50,7 +53,7 @@ class Devise::PasswordsController < DeviseController
50
53
 
51
54
  protected
52
55
  def after_resetting_password_path_for(resource)
53
- Devise.sign_in_after_reset_password ? after_sign_in_path_for(resource) : new_session_path(resource_name)
56
+ sign_in_after_reset_password? ? after_sign_in_path_for(resource) : new_session_path(resource_name)
54
57
  end
55
58
 
56
59
  # The path used after sending reset password instructions
@@ -66,6 +69,11 @@ class Devise::PasswordsController < DeviseController
66
69
  end
67
70
  end
68
71
 
72
+ # Check if the user should be signed in automatically after resetting the password.
73
+ def sign_in_after_reset_password?
74
+ resource_class.sign_in_after_reset_password
75
+ end
76
+
69
77
  # Check if proper Lockable module methods are present & unlock strategy
70
78
  # allows to unlock resource on password reset
71
79
  def unlockable?(resource)
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Devise::RegistrationsController < DeviseController
2
4
  prepend_before_action :require_no_authentication, only: [:new, :create, :cancel]
3
5
  prepend_before_action :authenticate_scope!, only: [:edit, :update, :destroy]
6
+ prepend_before_action :set_minimum_password_length, only: [:new, :edit]
4
7
 
5
8
  # GET /resource/sign_up
6
9
  def new
7
- build_resource({})
8
- set_minimum_password_length
10
+ build_resource
9
11
  yield resource if block_given?
10
- respond_with self.resource
12
+ respond_with resource
11
13
  end
12
14
 
13
15
  # POST /resource
@@ -48,15 +50,13 @@ class Devise::RegistrationsController < DeviseController
48
50
  resource_updated = update_resource(resource, account_update_params)
49
51
  yield resource if block_given?
50
52
  if resource_updated
51
- if is_flashing_format?
52
- flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
53
- :update_needs_confirmation : :updated
54
- set_flash_message :notice, flash_key
55
- end
56
- sign_in resource_name, resource, bypass: true
53
+ set_flash_message_for_update(resource, prev_unconfirmed_email)
54
+ bypass_sign_in resource, scope: resource_name if sign_in_after_change_password?
55
+
57
56
  respond_with resource, location: after_update_path_for(resource)
58
57
  else
59
58
  clean_up_passwords resource
59
+ set_minimum_password_length
60
60
  respond_with resource
61
61
  end
62
62
  end
@@ -67,7 +67,7 @@ class Devise::RegistrationsController < DeviseController
67
67
  Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
68
68
  set_flash_message! :notice, :destroyed
69
69
  yield resource if block_given?
70
- respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
70
+ respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status }
71
71
  end
72
72
 
73
73
  # GET /resource/cancel
@@ -82,12 +82,6 @@ class Devise::RegistrationsController < DeviseController
82
82
 
83
83
  protected
84
84
 
85
- def update_needs_confirmation?(resource, previous)
86
- resource.respond_to?(:pending_reconfirmation?) &&
87
- resource.pending_reconfirmation? &&
88
- previous != resource.unconfirmed_email
89
- end
90
-
91
85
  # By default we want to require a password checks on update.
92
86
  # You can overwrite this method in your own RegistrationsController.
93
87
  def update_resource(resource, params)
@@ -96,8 +90,8 @@ class Devise::RegistrationsController < DeviseController
96
90
 
97
91
  # Build a devise resource passing in the session. Useful to move
98
92
  # temporary session data to the newly created user.
99
- def build_resource(hash=nil)
100
- self.resource = resource_class.new_with_session(hash || {}, session)
93
+ def build_resource(hash = {})
94
+ self.resource = resource_class.new_with_session(hash, session)
101
95
  end
102
96
 
103
97
  # Signs in a user on sign up. You can overwrite this method in your own
@@ -109,7 +103,7 @@ class Devise::RegistrationsController < DeviseController
109
103
  # The path used after sign up. You need to overwrite this method
110
104
  # in your own RegistrationsController.
111
105
  def after_sign_up_path_for(resource)
112
- after_sign_in_path_for(resource)
106
+ after_sign_in_path_for(resource) if is_navigational_format?
113
107
  end
114
108
 
115
109
  # The path used after sign up for inactive accounts. You need to overwrite
@@ -124,7 +118,7 @@ class Devise::RegistrationsController < DeviseController
124
118
  # The default url to be used after updating a resource. You need to overwrite
125
119
  # this method in your own RegistrationsController.
126
120
  def after_update_path_for(resource)
127
- signed_in_root_path(resource)
121
+ sign_in_after_change_password? ? signed_in_root_path(resource) : new_session_path(resource_name)
128
122
  end
129
123
 
130
124
  # Authenticates the current scope and gets the current resource from the session.
@@ -133,6 +127,13 @@ class Devise::RegistrationsController < DeviseController
133
127
  self.resource = send(:"current_#{resource_name}")
134
128
  end
135
129
 
130
+ # Check if the user should be signed in automatically after updating the password.
131
+ def sign_in_after_change_password?
132
+ return true if account_update_params[:password].blank?
133
+
134
+ resource_class.sign_in_after_change_password
135
+ end
136
+
136
137
  def sign_up_params
137
138
  devise_parameter_sanitizer.sanitize(:sign_up)
138
139
  end
@@ -144,4 +145,25 @@ class Devise::RegistrationsController < DeviseController
144
145
  def translation_scope
145
146
  'devise.registrations'
146
147
  end
148
+
149
+ private
150
+
151
+ def set_flash_message_for_update(resource, prev_unconfirmed_email)
152
+ return unless is_flashing_format?
153
+
154
+ flash_key = if update_needs_confirmation?(resource, prev_unconfirmed_email)
155
+ :update_needs_confirmation
156
+ elsif sign_in_after_change_password?
157
+ :updated
158
+ else
159
+ :updated_but_not_signed_in
160
+ end
161
+ set_flash_message :notice, flash_key
162
+ end
163
+
164
+ def update_needs_confirmation?(resource, previous)
165
+ resource.respond_to?(:pending_reconfirmation?) &&
166
+ resource.pending_reconfirmation? &&
167
+ previous != resource.unconfirmed_email
168
+ end
147
169
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Devise::SessionsController < DeviseController
2
4
  prepend_before_action :require_no_authentication, only: [:new, :create]
3
5
  prepend_before_action :allow_params_authentication!, only: :create
4
6
  prepend_before_action :verify_signed_out_user, only: :destroy
5
- prepend_before_action only: [:create, :destroy] { request.env["devise.skip_timeout"] = true }
7
+ prepend_before_action(only: [:create, :destroy]) { request.env["devise.skip_timeout"] = true }
6
8
 
7
9
  # GET /resource/sign_in
8
10
  def new
@@ -26,7 +28,7 @@ class Devise::SessionsController < DeviseController
26
28
  signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
27
29
  set_flash_message! :notice, :signed_out if signed_out
28
30
  yield if block_given?
29
- respond_to_on_destroy
31
+ respond_to_on_destroy(non_navigational_status: :no_content)
30
32
  end
31
33
 
32
34
  protected
@@ -43,7 +45,7 @@ class Devise::SessionsController < DeviseController
43
45
  end
44
46
 
45
47
  def auth_options
46
- { scope: resource_name, recall: "#{controller_path}#new" }
48
+ { scope: resource_name, recall: "#{controller_path}#new", locale: I18n.locale }
47
49
  end
48
50
 
49
51
  def translation_scope
@@ -60,7 +62,7 @@ class Devise::SessionsController < DeviseController
60
62
  if all_signed_out?
61
63
  set_flash_message! :notice, :already_signed_out
62
64
 
63
- respond_to_on_destroy
65
+ respond_to_on_destroy(non_navigational_status: :unauthorized)
64
66
  end
65
67
  end
66
68
 
@@ -70,12 +72,12 @@ class Devise::SessionsController < DeviseController
70
72
  users.all?(&:blank?)
71
73
  end
72
74
 
73
- def respond_to_on_destroy
75
+ def respond_to_on_destroy(non_navigational_status: :no_content)
74
76
  # We actually need to hardcode this as Rails default responder doesn't
75
77
  # support returning empty response on GET request
76
78
  respond_to do |format|
77
- format.all { head :no_content }
78
- format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name) }
79
+ format.all { head non_navigational_status }
80
+ format.any(*navigational_formats) { redirect_to after_sign_out_path_for(resource_name), status: Devise.responder.redirect_status }
79
81
  end
80
82
  end
81
83
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Devise::UnlocksController < DeviseController
2
4
  prepend_before_action :require_no_authentication
3
5
 
@@ -27,6 +29,7 @@ class Devise::UnlocksController < DeviseController
27
29
  set_flash_message! :notice, :unlocked
28
30
  respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
29
31
  else
32
+ # TODO: use `error_status` when the default changes to `:unprocessable_entity` / `:unprocessable_content`.
30
33
  respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
31
34
  end
32
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # All Devise controllers are inherited from here.
2
4
  class DeviseController < Devise.parent_controller.constantize
3
5
  include Devise::Controllers::ScopedViews
@@ -13,6 +15,7 @@ class DeviseController < Devise.parent_controller.constantize
13
15
  end
14
16
 
15
17
  prepend_before_action :assert_is_devise_resource!
18
+ self.responder = Devise.responder
16
19
  respond_to :html if mimes_for_respond_to.empty?
17
20
 
18
21
  # Override prefixes to consider the scoped view.
@@ -20,7 +23,7 @@ class DeviseController < Devise.parent_controller.constantize
20
23
  # Action Controller tests that forces _prefixes to be
21
24
  # loaded before even having a request object.
22
25
  #
23
- # This method should be public as it is is in ActionPack
26
+ # This method should be public as it is in ActionPack
24
27
  # itself. Changing its visibility may break other gems.
25
28
  def _prefixes #:nodoc:
26
29
  @_prefixes ||= if self.class.scoped_views? && request && devise_mapping
@@ -30,6 +33,19 @@ class DeviseController < Devise.parent_controller.constantize
30
33
  end
31
34
  end
32
35
 
36
+ # Override internal methods to exclude `_prefixes` from action methods since
37
+ # we override it above.
38
+ #
39
+ # There was an intentional change in Rails 7.1 that will allow it to become
40
+ # an action method because it's a public method of a non-abstract controller,
41
+ # but we also can't make this abstract because it can affect potential actions
42
+ # defined in the parent controller, so instead we ensure `_prefixes` is going
43
+ # to be considered internal. (and thus, won't become an action method.)
44
+ # Ref: https://github.com/rails/rails/pull/48699
45
+ def self.internal_methods #:nodoc:
46
+ super << :_prefixes
47
+ end
48
+
33
49
  protected
34
50
 
35
51
  # Gets the actual resource stored in the instance variable
@@ -110,7 +126,7 @@ MESSAGE
110
126
  end
111
127
 
112
128
  if authenticated && resource = warden.user(resource_name)
113
- flash[:alert] = I18n.t("devise.failure.already_authenticated")
129
+ set_flash_message(:alert, 'already_authenticated', scope: 'devise.failure')
114
130
  redirect_to after_sign_in_path_for(resource)
115
131
  end
116
132
  end
@@ -182,7 +198,7 @@ MESSAGE
182
198
  options[:default] = Array(options[:default]).unshift(kind.to_sym)
183
199
  options[:resource_name] = resource_name
184
200
  options = devise_i18n_options(options)
185
- I18n.t("#{options[:resource_name]}.#{kind}", options)
201
+ I18n.t("#{options[:resource_name]}.#{kind}", **options)
186
202
  end
187
203
 
188
204
  # Controllers inheriting DeviseController are advised to override this
@@ -1,25 +1,5 @@
1
- module DeviseHelper
2
- # A simple way to show error messages for the current devise resource. If you need
3
- # to customize this method, you can either overwrite it in your application helpers or
4
- # copy the views to your application.
5
- #
6
- # This method is intended to stay simple and it is unlikely that we are going to change
7
- # it to add more behavior or options.
8
- def devise_error_messages!
9
- return "" if resource.errors.empty?
10
-
11
- messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
12
- sentence = I18n.t("errors.messages.not_saved",
13
- count: resource.errors.count,
14
- resource: resource.class.model_name.human.downcase)
1
+ # frozen_string_literal: true
15
2
 
16
- html = <<-HTML
17
- <div id="error_explanation">
18
- <h2>#{sentence}</h2>
19
- <ul>#{messages}</ul>
20
- </div>
21
- HTML
22
-
23
- html.html_safe
24
- end
3
+ # Keeping the helper around for backward compatibility.
4
+ module DeviseHelper
25
5
  end
@@ -1,23 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(ActionMailer)
2
4
  class Devise::Mailer < Devise.parent_mailer.constantize
3
5
  include Devise::Mailers::Helpers
4
6
 
5
- def confirmation_instructions(record, token, opts={})
7
+ def confirmation_instructions(record, token, opts = {})
6
8
  @token = token
7
9
  devise_mail(record, :confirmation_instructions, opts)
8
10
  end
9
11
 
10
- def reset_password_instructions(record, token, opts={})
12
+ def reset_password_instructions(record, token, opts = {})
11
13
  @token = token
12
14
  devise_mail(record, :reset_password_instructions, opts)
13
15
  end
14
16
 
15
- def unlock_instructions(record, token, opts={})
17
+ def unlock_instructions(record, token, opts = {})
16
18
  @token = token
17
19
  devise_mail(record, :unlock_instructions, opts)
18
20
  end
19
21
 
20
- def password_change(record, opts={})
22
+ def email_changed(record, opts = {})
23
+ devise_mail(record, :email_changed, opts)
24
+ end
25
+
26
+ def password_change(record, opts = {})
21
27
  devise_mail(record, :password_change, opts)
22
28
  end
23
29
  end
@@ -1,11 +1,11 @@
1
1
  <h2>Resend confirmation instructions</h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
4
- <%= devise_error_messages! %>
4
+ <%= render "devise/shared/error_messages", resource: resource %>
5
5
 
6
6
  <div class="field">
7
- <%= f.label :email %><br />
8
- <%= f.email_field :email, autofocus: true, value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
7
+ <p><%= f.label :email %></p>
8
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %></p>
9
9
  </div>
10
10
 
11
11
  <div class="actions">
@@ -0,0 +1,7 @@
1
+ <p>Hello <%= @email %>!</p>
2
+
3
+ <% if @resource.try(:unconfirmed_email?) %>
4
+ <p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
5
+ <% else %>
6
+ <p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
7
+ <% end %>
@@ -1,20 +1,20 @@
1
1
  <h2>Change your password</h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
4
- <%= devise_error_messages! %>
4
+ <%= render "devise/shared/error_messages", resource: resource %>
5
5
  <%= f.hidden_field :reset_password_token %>
6
6
 
7
7
  <div class="field">
8
- <%= f.label :password, "New password" %><br />
8
+ <p><%= f.label :password, "New password" %></p>
9
9
  <% if @minimum_password_length %>
10
- <em>(<%= @minimum_password_length %> characters minimum)</em><br />
10
+ <p><em>(<%= @minimum_password_length %> characters minimum)</em></p>
11
11
  <% end %>
12
- <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
12
+ <p><%= f.password_field :password, autofocus: true, autocomplete: "new-password" %></p>
13
13
  </div>
14
14
 
15
15
  <div class="field">
16
- <%= f.label :password_confirmation, "Confirm new password" %><br />
17
- <%= f.password_field :password_confirmation, autocomplete: "off" %>
16
+ <p><%= f.label :password_confirmation, "Confirm new password" %></p>
17
+ <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
18
18
  </div>
19
19
 
20
20
  <div class="actions">
@@ -1,15 +1,15 @@
1
1
  <h2>Forgot your password?</h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
4
- <%= devise_error_messages! %>
4
+ <%= render "devise/shared/error_messages", resource: resource %>
5
5
 
6
6
  <div class="field">
7
- <%= f.label :email %><br />
8
- <%= f.email_field :email, autofocus: true %>
7
+ <p><%= f.label :email %></p>
8
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
9
9
  </div>
10
10
 
11
11
  <div class="actions">
12
- <%= f.submit "Send me reset password instructions" %>
12
+ <%= f.submit "Send me password reset instructions" %>
13
13
  </div>
14
14
  <% end %>
15
15
 
@@ -1,11 +1,11 @@
1
1
  <h2>Edit <%= resource_name.to_s.humanize %></h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
4
- <%= devise_error_messages! %>
4
+ <%= render "devise/shared/error_messages", resource: resource %>
5
5
 
6
6
  <div class="field">
7
- <%= f.label :email %><br />
8
- <%= f.email_field :email, autofocus: true %>
7
+ <p><%= f.label :email %></p>
8
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
9
9
  </div>
10
10
 
11
11
  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
@@ -13,18 +13,21 @@
13
13
  <% end %>
14
14
 
15
15
  <div class="field">
16
- <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
17
- <%= f.password_field :password, autocomplete: "off" %>
16
+ <p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i></p>
17
+ <p><%= f.password_field :password, autocomplete: "new-password" %></p>
18
+ <% if @minimum_password_length %>
19
+ <p><em><%= @minimum_password_length %> characters minimum</em></p>
20
+ <% end %>
18
21
  </div>
19
22
 
20
23
  <div class="field">
21
- <%= f.label :password_confirmation %><br />
22
- <%= f.password_field :password_confirmation, autocomplete: "off" %>
24
+ <p><%= f.label :password_confirmation %></p>
25
+ <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
23
26
  </div>
24
27
 
25
28
  <div class="field">
26
- <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
27
- <%= f.password_field :current_password, autocomplete: "off" %>
29
+ <p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i></p>
30
+ <p><%= f.password_field :current_password, autocomplete: "current-password" %></p>
28
31
  </div>
29
32
 
30
33
  <div class="actions">
@@ -34,6 +37,6 @@
34
37
 
35
38
  <h3>Cancel my account</h3>
36
39
 
37
- <p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
40
+ <div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
38
41
 
39
42
  <%= link_to "Back", :back %>
@@ -1,24 +1,24 @@
1
1
  <h2>Sign up</h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
4
- <%= devise_error_messages! %>
4
+ <%= render "devise/shared/error_messages", resource: resource %>
5
5
 
6
6
  <div class="field">
7
- <%= f.label :email %><br />
8
- <%= f.email_field :email, autofocus: true %>
7
+ <p><%= f.label :email %></p>
8
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
9
9
  </div>
10
10
 
11
11
  <div class="field">
12
- <%= f.label :password %>
12
+ <p><%= f.label :password %></p>
13
13
  <% if @minimum_password_length %>
14
- <em>(<%= @minimum_password_length %> characters minimum)</em>
15
- <% end %><br />
16
- <%= f.password_field :password, autocomplete: "off" %>
14
+ <p><em>(<%= @minimum_password_length %> characters minimum)</em></p>
15
+ <% end %>
16
+ <p><%= f.password_field :password, autocomplete: "new-password" %></p>
17
17
  </div>
18
18
 
19
19
  <div class="field">
20
- <%= f.label :password_confirmation %><br />
21
- <%= f.password_field :password_confirmation, autocomplete: "off" %>
20
+ <p><%= f.label :password_confirmation %></p>
21
+ <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
22
22
  </div>
23
23
 
24
24
  <div class="actions">
@@ -2,21 +2,21 @@
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
4
4
  <div class="field">
5
- <%= f.label :email %><br />
6
- <%= f.email_field :email, autofocus: true %>
5
+ <p><%= f.label :email %></p>
6
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
7
7
  </div>
8
8
 
9
9
  <div class="field">
10
- <%= f.label :password %><br />
11
- <%= f.password_field :password, autocomplete: "off" %>
10
+ <p><%= f.label :password %></p>
11
+ <p><%= f.password_field :password, autocomplete: "current-password" %></p>
12
12
  </div>
13
13
 
14
- <% if devise_mapping.rememberable? -%>
14
+ <% if devise_mapping.rememberable? %>
15
15
  <div class="field">
16
- <%= f.check_box :remember_me %>
17
- <%= f.label :remember_me %>
16
+ <p><%= f.check_box :remember_me %></p>
17
+ <p><%= f.label :remember_me %></p>
18
18
  </div>
19
- <% end -%>
19
+ <% end %>
20
20
 
21
21
  <div class="actions">
22
22
  <%= f.submit "Log in" %>
@@ -0,0 +1,15 @@
1
+ <% if resource.errors.any? %>
2
+ <div id="error_explanation" data-turbo-temporary>
3
+ <h2>
4
+ <%= I18n.t("errors.messages.not_saved",
5
+ count: resource.errors.count,
6
+ resource: resource.class.model_name.human.downcase)
7
+ %>
8
+ </h2>
9
+ <ul>
10
+ <% resource.errors.full_messages.each do |message| %>
11
+ <li><%= message %></li>
12
+ <% end %>
13
+ </ul>
14
+ </div>
15
+ <% end %>
@@ -1,25 +1,25 @@
1
1
  <%- if controller_name != 'sessions' %>
2
- <%= link_to "Log in", new_session_path(resource_name) %><br />
3
- <% end -%>
2
+ <p><%= link_to "Log in", new_session_path(resource_name) %></p>
3
+ <% end %>
4
4
 
5
5
  <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6
- <%= link_to "Sign up", new_registration_path(resource_name) %><br />
7
- <% end -%>
6
+ <p><%= link_to "Sign up", new_registration_path(resource_name) %></p>
7
+ <% end %>
8
8
 
9
9
  <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
10
- <%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
11
- <% end -%>
10
+ <p><%= link_to "Forgot your password?", new_password_path(resource_name) %></p>
11
+ <% end %>
12
12
 
13
13
  <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14
- <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
15
- <% end -%>
14
+ <p><%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %></p>
15
+ <% end %>
16
16
 
17
17
  <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18
- <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
19
- <% end -%>
18
+ <p><%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %></p>
19
+ <% end %>
20
20
 
21
21
  <%- if devise_mapping.omniauthable? %>
22
22
  <%- resource_class.omniauth_providers.each do |provider| %>
23
- <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
24
- <% end -%>
25
- <% end -%>
23
+ <p><%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %></p>
24
+ <% end %>
25
+ <% end %>