devise 4.4.3 → 4.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (236) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +174 -4
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +129 -65
  5. data/app/controllers/devise/confirmations_controller.rb +1 -0
  6. data/app/controllers/devise/passwords_controller.rb +3 -2
  7. data/app/controllers/devise/registrations_controller.rb +27 -9
  8. data/app/controllers/devise/sessions_controller.rb +2 -2
  9. data/app/controllers/devise/unlocks_controller.rb +1 -0
  10. data/app/controllers/devise_controller.rb +17 -3
  11. data/app/helpers/devise_helper.rb +21 -18
  12. data/app/mailers/devise/mailer.rb +5 -5
  13. data/app/views/devise/confirmations/new.html.erb +1 -1
  14. data/app/views/devise/passwords/edit.html.erb +3 -3
  15. data/app/views/devise/passwords/new.html.erb +1 -1
  16. data/app/views/devise/registrations/edit.html.erb +5 -5
  17. data/app/views/devise/registrations/new.html.erb +3 -3
  18. data/app/views/devise/sessions/new.html.erb +3 -3
  19. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  20. data/app/views/devise/shared/_links.html.erb +8 -8
  21. data/app/views/devise/unlocks/new.html.erb +1 -1
  22. data/config/locales/en.yml +3 -2
  23. data/lib/devise/controllers/helpers.rb +10 -8
  24. data/lib/devise/controllers/responder.rb +35 -0
  25. data/lib/devise/controllers/sign_in_out.rb +9 -4
  26. data/lib/devise/controllers/url_helpers.rb +1 -1
  27. data/lib/devise/failure_app.rb +41 -8
  28. data/lib/devise/hooks/csrf_cleaner.rb +6 -1
  29. data/lib/devise/hooks/lockable.rb +2 -5
  30. data/lib/devise/hooks/timeoutable.rb +2 -2
  31. data/lib/devise/mapping.rb +1 -1
  32. data/lib/devise/models/authenticatable.rb +51 -48
  33. data/lib/devise/models/confirmable.rb +34 -40
  34. data/lib/devise/models/database_authenticatable.rb +54 -35
  35. data/lib/devise/models/lockable.rb +13 -5
  36. data/lib/devise/models/omniauthable.rb +2 -2
  37. data/lib/devise/models/recoverable.rb +8 -19
  38. data/lib/devise/models/registerable.rb +2 -0
  39. data/lib/devise/models/rememberable.rb +2 -2
  40. data/lib/devise/models/timeoutable.rb +1 -1
  41. data/lib/devise/models/trackable.rb +9 -2
  42. data/lib/devise/models/validatable.rb +4 -9
  43. data/lib/devise/models.rb +1 -0
  44. data/lib/devise/omniauth.rb +2 -5
  45. data/lib/devise/orm.rb +71 -0
  46. data/lib/devise/parameter_filter.rb +2 -0
  47. data/lib/devise/parameter_sanitizer.rb +13 -1
  48. data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
  49. data/lib/devise/rails/routes.rb +6 -6
  50. data/lib/devise/rails.rb +4 -0
  51. data/lib/devise/secret_key_finder.rb +2 -0
  52. data/lib/devise/strategies/authenticatable.rb +1 -1
  53. data/lib/devise/strategies/database_authenticatable.rb +6 -1
  54. data/lib/devise/test/controller_helpers.rb +5 -3
  55. data/lib/devise/test/integration_helpers.rb +1 -1
  56. data/lib/devise/test_helpers.rb +1 -1
  57. data/lib/devise/version.rb +1 -1
  58. data/lib/devise.rb +38 -11
  59. data/lib/generators/active_record/devise_generator.rb +26 -11
  60. data/lib/generators/devise/controllers_generator.rb +1 -1
  61. data/lib/generators/devise/devise_generator.rb +1 -1
  62. data/lib/generators/devise/install_generator.rb +1 -5
  63. data/lib/generators/devise/orm_helpers.rb +2 -2
  64. data/lib/generators/devise/views_generator.rb +1 -1
  65. data/lib/generators/mongoid/devise_generator.rb +5 -5
  66. data/lib/generators/templates/README +9 -1
  67. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +1 -1
  68. data/lib/generators/templates/devise.rb +38 -8
  69. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
  70. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
  71. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +4 -1
  72. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +12 -4
  73. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
  74. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
  75. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
  76. metadata +23 -316
  77. data/.gitignore +0 -10
  78. data/.travis.yml +0 -68
  79. data/.yardopts +0 -9
  80. data/CODE_OF_CONDUCT.md +0 -22
  81. data/CONTRIBUTING.md +0 -79
  82. data/Gemfile +0 -39
  83. data/Gemfile.lock +0 -193
  84. data/ISSUE_TEMPLATE.md +0 -19
  85. data/Rakefile +0 -37
  86. data/bin/test +0 -13
  87. data/devise.gemspec +0 -28
  88. data/devise.png +0 -0
  89. data/gemfiles/Gemfile.rails-4.1-stable +0 -32
  90. data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -171
  91. data/gemfiles/Gemfile.rails-4.2-stable +0 -32
  92. data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
  93. data/gemfiles/Gemfile.rails-5.0-stable +0 -33
  94. data/gemfiles/Gemfile.rails-5.0-stable.lock +0 -192
  95. data/gemfiles/Gemfile.rails-5.2-rc1 +0 -26
  96. data/gemfiles/Gemfile.rails-5.2-rc1.lock +0 -201
  97. data/guides/bug_report_templates/integration_test.rb +0 -106
  98. data/test/controllers/custom_registrations_controller_test.rb +0 -42
  99. data/test/controllers/custom_strategy_test.rb +0 -66
  100. data/test/controllers/helper_methods_test.rb +0 -24
  101. data/test/controllers/helpers_test.rb +0 -318
  102. data/test/controllers/inherited_controller_i18n_messages_test.rb +0 -53
  103. data/test/controllers/internal_helpers_test.rb +0 -129
  104. data/test/controllers/load_hooks_controller_test.rb +0 -21
  105. data/test/controllers/passwords_controller_test.rb +0 -34
  106. data/test/controllers/sessions_controller_test.rb +0 -108
  107. data/test/controllers/url_helpers_test.rb +0 -67
  108. data/test/delegator_test.rb +0 -21
  109. data/test/devise_test.rb +0 -109
  110. data/test/failure_app_test.rb +0 -340
  111. data/test/generators/active_record_generator_test.rb +0 -130
  112. data/test/generators/controllers_generator_test.rb +0 -50
  113. data/test/generators/devise_generator_test.rb +0 -41
  114. data/test/generators/install_generator_test.rb +0 -26
  115. data/test/generators/mongoid_generator_test.rb +0 -25
  116. data/test/generators/views_generator_test.rb +0 -105
  117. data/test/helpers/devise_helper_test.rb +0 -51
  118. data/test/integration/authenticatable_test.rb +0 -706
  119. data/test/integration/confirmable_test.rb +0 -326
  120. data/test/integration/database_authenticatable_test.rb +0 -97
  121. data/test/integration/http_authenticatable_test.rb +0 -114
  122. data/test/integration/lockable_test.rb +0 -242
  123. data/test/integration/mounted_engine_test.rb +0 -38
  124. data/test/integration/omniauthable_test.rb +0 -148
  125. data/test/integration/recoverable_test.rb +0 -349
  126. data/test/integration/registerable_test.rb +0 -365
  127. data/test/integration/rememberable_test.rb +0 -219
  128. data/test/integration/timeoutable_test.rb +0 -186
  129. data/test/integration/trackable_test.rb +0 -99
  130. data/test/mailers/confirmation_instructions_test.rb +0 -117
  131. data/test/mailers/email_changed_test.rb +0 -132
  132. data/test/mailers/mailer_test.rb +0 -20
  133. data/test/mailers/reset_password_instructions_test.rb +0 -98
  134. data/test/mailers/unlock_instructions_test.rb +0 -93
  135. data/test/mapping_test.rb +0 -136
  136. data/test/models/authenticatable_test.rb +0 -25
  137. data/test/models/confirmable_test.rb +0 -549
  138. data/test/models/database_authenticatable_test.rb +0 -283
  139. data/test/models/lockable_test.rb +0 -352
  140. data/test/models/omniauthable_test.rb +0 -9
  141. data/test/models/recoverable_test.rb +0 -263
  142. data/test/models/registerable_test.rb +0 -9
  143. data/test/models/rememberable_test.rb +0 -184
  144. data/test/models/serializable_test.rb +0 -60
  145. data/test/models/timeoutable_test.rb +0 -53
  146. data/test/models/trackable_test.rb +0 -62
  147. data/test/models/validatable_test.rb +0 -121
  148. data/test/models_test.rb +0 -155
  149. data/test/omniauth/config_test.rb +0 -61
  150. data/test/omniauth/url_helpers_test.rb +0 -53
  151. data/test/orm/active_record.rb +0 -24
  152. data/test/orm/mongoid.rb +0 -15
  153. data/test/parameter_sanitizer_test.rb +0 -77
  154. data/test/rails_app/Rakefile +0 -6
  155. data/test/rails_app/app/active_record/admin.rb +0 -8
  156. data/test/rails_app/app/active_record/shim.rb +0 -4
  157. data/test/rails_app/app/active_record/user.rb +0 -20
  158. data/test/rails_app/app/active_record/user_on_engine.rb +0 -9
  159. data/test/rails_app/app/active_record/user_on_main_app.rb +0 -9
  160. data/test/rails_app/app/active_record/user_with_validations.rb +0 -12
  161. data/test/rails_app/app/active_record/user_without_email.rb +0 -10
  162. data/test/rails_app/app/controllers/admins/sessions_controller.rb +0 -8
  163. data/test/rails_app/app/controllers/admins_controller.rb +0 -8
  164. data/test/rails_app/app/controllers/application_controller.rb +0 -13
  165. data/test/rails_app/app/controllers/application_with_fake_engine.rb +0 -32
  166. data/test/rails_app/app/controllers/custom/registrations_controller.rb +0 -33
  167. data/test/rails_app/app/controllers/home_controller.rb +0 -31
  168. data/test/rails_app/app/controllers/publisher/registrations_controller.rb +0 -4
  169. data/test/rails_app/app/controllers/publisher/sessions_controller.rb +0 -4
  170. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +0 -16
  171. data/test/rails_app/app/controllers/users_controller.rb +0 -33
  172. data/test/rails_app/app/helpers/application_helper.rb +0 -5
  173. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +0 -5
  174. data/test/rails_app/app/mailers/users/mailer.rb +0 -5
  175. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +0 -6
  176. data/test/rails_app/app/mongoid/admin.rb +0 -31
  177. data/test/rails_app/app/mongoid/shim.rb +0 -25
  178. data/test/rails_app/app/mongoid/user.rb +0 -50
  179. data/test/rails_app/app/mongoid/user_on_engine.rb +0 -41
  180. data/test/rails_app/app/mongoid/user_on_main_app.rb +0 -41
  181. data/test/rails_app/app/mongoid/user_with_validations.rb +0 -37
  182. data/test/rails_app/app/mongoid/user_without_email.rb +0 -35
  183. data/test/rails_app/app/views/admins/index.html.erb +0 -1
  184. data/test/rails_app/app/views/admins/sessions/new.html.erb +0 -2
  185. data/test/rails_app/app/views/home/admin_dashboard.html.erb +0 -1
  186. data/test/rails_app/app/views/home/index.html.erb +0 -1
  187. data/test/rails_app/app/views/home/join.html.erb +0 -1
  188. data/test/rails_app/app/views/home/private.html.erb +0 -1
  189. data/test/rails_app/app/views/home/user_dashboard.html.erb +0 -1
  190. data/test/rails_app/app/views/layouts/application.html.erb +0 -24
  191. data/test/rails_app/app/views/users/edit_form.html.erb +0 -1
  192. data/test/rails_app/app/views/users/index.html.erb +0 -1
  193. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +0 -1
  194. data/test/rails_app/app/views/users/sessions/new.html.erb +0 -1
  195. data/test/rails_app/bin/bundle +0 -3
  196. data/test/rails_app/bin/rails +0 -4
  197. data/test/rails_app/bin/rake +0 -4
  198. data/test/rails_app/config/application.rb +0 -48
  199. data/test/rails_app/config/boot.rb +0 -27
  200. data/test/rails_app/config/database.yml +0 -18
  201. data/test/rails_app/config/environment.rb +0 -7
  202. data/test/rails_app/config/environments/development.rb +0 -32
  203. data/test/rails_app/config/environments/production.rb +0 -88
  204. data/test/rails_app/config/environments/test.rb +0 -47
  205. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -9
  206. data/test/rails_app/config/initializers/devise.rb +0 -182
  207. data/test/rails_app/config/initializers/inflections.rb +0 -4
  208. data/test/rails_app/config/initializers/secret_token.rb +0 -5
  209. data/test/rails_app/config/initializers/session_store.rb +0 -3
  210. data/test/rails_app/config/routes.rb +0 -128
  211. data/test/rails_app/config.ru +0 -4
  212. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -77
  213. data/test/rails_app/db/schema.rb +0 -57
  214. data/test/rails_app/lib/shared_admin.rb +0 -23
  215. data/test/rails_app/lib/shared_user.rb +0 -32
  216. data/test/rails_app/lib/shared_user_without_email.rb +0 -28
  217. data/test/rails_app/lib/shared_user_without_omniauth.rb +0 -15
  218. data/test/rails_app/public/404.html +0 -26
  219. data/test/rails_app/public/422.html +0 -26
  220. data/test/rails_app/public/500.html +0 -26
  221. data/test/rails_app/public/favicon.ico +0 -0
  222. data/test/rails_test.rb +0 -11
  223. data/test/routes_test.rb +0 -281
  224. data/test/secret_key_finder_test.rb +0 -97
  225. data/test/support/action_controller/record_identifier.rb +0 -12
  226. data/test/support/assertions.rb +0 -30
  227. data/test/support/helpers.rb +0 -83
  228. data/test/support/http_method_compatibility.rb +0 -53
  229. data/test/support/integration.rb +0 -95
  230. data/test/support/locale/en.yml +0 -8
  231. data/test/support/mongoid.yml +0 -6
  232. data/test/support/webrat/integrations/rails.rb +0 -35
  233. data/test/test/controller_helpers_test.rb +0 -193
  234. data/test/test/integration_helpers_test.rb +0 -34
  235. data/test/test_helper.rb +0 -36
  236. data/test/test_models.rb +0 -35
@@ -1,27 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeviseHelper
4
- # A simple way to show error messages for the current devise resource. If you need
5
- # to customize this method, you can either overwrite it in your application helpers or
6
- # copy the views to your application.
7
- #
8
- # This method is intended to stay simple and it is unlikely that we are going to change
9
- # it to add more behavior or options.
4
+ # Retain this method for backwards compatibility, deprecated in favor of modifying the
5
+ # devise/shared/error_messages partial.
10
6
  def devise_error_messages!
11
- return "" if resource.errors.empty?
7
+ Devise.deprecator.warn <<-DEPRECATION.strip_heredoc
8
+ [Devise] `DeviseHelper#devise_error_messages!` is deprecated and will be
9
+ removed in the next major version.
10
+
11
+ Devise now uses a partial under "devise/shared/error_messages" to display
12
+ error messages by default, and make them easier to customize. Update your
13
+ views changing calls from:
14
+
15
+ <%= devise_error_messages! %>
12
16
 
13
- messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
14
- sentence = I18n.t("errors.messages.not_saved",
15
- count: resource.errors.count,
16
- resource: resource.class.model_name.human.downcase)
17
+ to:
17
18
 
18
- html = <<-HTML
19
- <div id="error_explanation">
20
- <h2>#{sentence}</h2>
21
- <ul>#{messages}</ul>
22
- </div>
23
- HTML
19
+ <%= render "devise/shared/error_messages", resource: resource %>
20
+
21
+ To start customizing how errors are displayed, you can copy the partial
22
+ from devise to your `app/views` folder. Alternatively, you can run
23
+ `rails g devise:views` which will copy all of them again to your app.
24
+ DEPRECATION
25
+
26
+ return "" if resource.errors.empty?
24
27
 
25
- html.html_safe
28
+ render "devise/shared/error_messages", resource: resource
26
29
  end
27
30
  end
@@ -4,26 +4,26 @@ if defined?(ActionMailer)
4
4
  class Devise::Mailer < Devise.parent_mailer.constantize
5
5
  include Devise::Mailers::Helpers
6
6
 
7
- def confirmation_instructions(record, token, opts={})
7
+ def confirmation_instructions(record, token, opts = {})
8
8
  @token = token
9
9
  devise_mail(record, :confirmation_instructions, opts)
10
10
  end
11
11
 
12
- def reset_password_instructions(record, token, opts={})
12
+ def reset_password_instructions(record, token, opts = {})
13
13
  @token = token
14
14
  devise_mail(record, :reset_password_instructions, opts)
15
15
  end
16
16
 
17
- def unlock_instructions(record, token, opts={})
17
+ def unlock_instructions(record, token, opts = {})
18
18
  @token = token
19
19
  devise_mail(record, :unlock_instructions, opts)
20
20
  end
21
21
 
22
- def email_changed(record, opts={})
22
+ def email_changed(record, opts = {})
23
23
  devise_mail(record, :email_changed, opts)
24
24
  end
25
25
 
26
- def password_change(record, opts={})
26
+ def password_change(record, opts = {})
27
27
  devise_mail(record, :password_change, opts)
28
28
  end
29
29
  end
@@ -1,7 +1,7 @@
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
7
  <%= f.label :email %><br />
@@ -1,7 +1,7 @@
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">
@@ -9,12 +9,12 @@
9
9
  <% if @minimum_password_length %>
10
10
  <em>(<%= @minimum_password_length %> characters minimum)</em><br />
11
11
  <% end %>
12
- <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
12
+ <%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
13
13
  </div>
14
14
 
15
15
  <div class="field">
16
16
  <%= f.label :password_confirmation, "Confirm new password" %><br />
17
- <%= f.password_field :password_confirmation, autocomplete: "off" %>
17
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
18
18
  </div>
19
19
 
20
20
  <div class="actions">
@@ -1,7 +1,7 @@
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
7
  <%= f.label :email %><br />
@@ -1,7 +1,7 @@
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
7
  <%= f.label :email %><br />
@@ -14,7 +14,7 @@
14
14
 
15
15
  <div class="field">
16
16
  <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
17
- <%= f.password_field :password, autocomplete: "off" %>
17
+ <%= f.password_field :password, autocomplete: "new-password" %>
18
18
  <% if @minimum_password_length %>
19
19
  <br />
20
20
  <em><%= @minimum_password_length %> characters minimum</em>
@@ -23,12 +23,12 @@
23
23
 
24
24
  <div class="field">
25
25
  <%= f.label :password_confirmation %><br />
26
- <%= f.password_field :password_confirmation, autocomplete: "off" %>
26
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
27
27
  </div>
28
28
 
29
29
  <div class="field">
30
30
  <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
31
- <%= f.password_field :current_password, autocomplete: "off" %>
31
+ <%= f.password_field :current_password, autocomplete: "current-password" %>
32
32
  </div>
33
33
 
34
34
  <div class="actions">
@@ -38,6 +38,6 @@
38
38
 
39
39
  <h3>Cancel my account</h3>
40
40
 
41
- <p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
41
+ <div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
42
42
 
43
43
  <%= link_to "Back", :back %>
@@ -1,7 +1,7 @@
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
7
  <%= f.label :email %><br />
@@ -13,12 +13,12 @@
13
13
  <% if @minimum_password_length %>
14
14
  <em>(<%= @minimum_password_length %> characters minimum)</em>
15
15
  <% end %><br />
16
- <%= f.password_field :password, autocomplete: "off" %>
16
+ <%= f.password_field :password, autocomplete: "new-password" %>
17
17
  </div>
18
18
 
19
19
  <div class="field">
20
20
  <%= f.label :password_confirmation %><br />
21
- <%= f.password_field :password_confirmation, autocomplete: "off" %>
21
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
22
22
  </div>
23
23
 
24
24
  <div class="actions">
@@ -8,15 +8,15 @@
8
8
 
9
9
  <div class="field">
10
10
  <%= f.label :password %><br />
11
- <%= f.password_field :password, autocomplete: "off" %>
11
+ <%= f.password_field :password, autocomplete: "current-password" %>
12
12
  </div>
13
13
 
14
- <% if devise_mapping.rememberable? -%>
14
+ <% if devise_mapping.rememberable? %>
15
15
  <div class="field">
16
16
  <%= f.check_box :remember_me %>
17
17
  <%= f.label :remember_me %>
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-cache="false">
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
2
  <%= link_to "Log in", new_session_path(resource_name) %><br />
3
- <% end -%>
3
+ <% end %>
4
4
 
5
5
  <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6
6
  <%= link_to "Sign up", new_registration_path(resource_name) %><br />
7
- <% end -%>
7
+ <% end %>
8
8
 
9
9
  <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
10
10
  <%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
11
- <% end -%>
11
+ <% end %>
12
12
 
13
13
  <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14
14
  <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
15
- <% end -%>
15
+ <% end %>
16
16
 
17
17
  <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18
18
  <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
19
- <% end -%>
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
+ <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %><br />
24
+ <% end %>
25
+ <% end %>
@@ -1,7 +1,7 @@
1
1
  <h2>Resend unlock instructions</h2>
2
2
 
3
3
  <%= form_for(resource, as: resource_name, url: unlock_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
7
  <%= f.label :email %><br />
@@ -1,4 +1,4 @@
1
- # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
1
+ # Additional translations at https://github.com/heartcombo/devise/wiki/I18n
2
2
 
3
3
  en:
4
4
  devise:
@@ -42,8 +42,9 @@ en:
42
42
  signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
43
43
  signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
44
44
  signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
45
- update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
45
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
46
46
  updated: "Your account has been updated successfully."
47
+ updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
47
48
  sessions:
48
49
  signed_in: "Signed in successfully."
49
50
  signed_out: "Signed out successfully."
@@ -36,16 +36,17 @@ module Devise
36
36
  # before_action ->{ authenticate_blogger! :admin } # Redirects to the admin login page
37
37
  # current_blogger :user # Preferably returns a User if one is signed in
38
38
  #
39
- def devise_group(group_name, opts={})
39
+ def devise_group(group_name, opts = {})
40
40
  mappings = "[#{ opts[:contains].map { |m| ":#{m}" }.join(',') }]"
41
41
 
42
42
  class_eval <<-METHODS, __FILE__, __LINE__ + 1
43
- def authenticate_#{group_name}!(favourite=nil, opts={})
43
+ def authenticate_#{group_name}!(favorite = nil, opts = {})
44
44
  unless #{group_name}_signed_in?
45
45
  mappings = #{mappings}
46
- mappings.unshift mappings.delete(favourite.to_sym) if favourite
46
+ mappings.unshift mappings.delete(favorite.to_sym) if favorite
47
47
  mappings.each do |mapping|
48
48
  opts[:scope] = mapping
49
+ opts[:locale] = I18n.locale
49
50
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
50
51
  end
51
52
  end
@@ -57,9 +58,9 @@ module Devise
57
58
  end
58
59
  end
59
60
 
60
- def current_#{group_name}(favourite=nil)
61
+ def current_#{group_name}(favorite = nil)
61
62
  mappings = #{mappings}
62
- mappings.unshift mappings.delete(favourite.to_sym) if favourite
63
+ mappings.unshift mappings.delete(favorite.to_sym) if favorite
63
64
  mappings.each do |mapping|
64
65
  current = warden.authenticate(scope: mapping)
65
66
  return current if current
@@ -113,8 +114,9 @@ module Devise
113
114
  mapping = mapping.name
114
115
 
115
116
  class_eval <<-METHODS, __FILE__, __LINE__ + 1
116
- def authenticate_#{mapping}!(opts={})
117
+ def authenticate_#{mapping}!(opts = {})
117
118
  opts[:scope] = :#{mapping}
119
+ opts[:locale] = I18n.locale
118
120
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
119
121
  end
120
122
 
@@ -252,7 +254,7 @@ module Devise
252
254
  # Overwrite Rails' handle unverified request to sign out all scopes,
253
255
  # clear run strategies and remove cached variables.
254
256
  def handle_unverified_request
255
- super # call the default behaviour which resets/nullifies/raises
257
+ super # call the default behavior which resets/nullifies/raises
256
258
  request.env["devise.skip_storage"] = true
257
259
  sign_out_all_scopes(false)
258
260
  end
@@ -268,7 +270,7 @@ module Devise
268
270
  # Check if flash messages should be emitted. Default is to do it on
269
271
  # navigational formats
270
272
  def is_flashing_format?
271
- is_navigational_format?
273
+ request.respond_to?(:flash) && is_navigational_format?
272
274
  end
273
275
 
274
276
  private
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ module Controllers
5
+ # Custom Responder to configure default statuses that only apply to Devise,
6
+ # and allow to integrate more easily with Hotwire/Turbo.
7
+ class Responder < ActionController::Responder
8
+ if respond_to?(:error_status=) && respond_to?(:redirect_status=)
9
+ self.error_status = :ok
10
+ self.redirect_status = :found
11
+ else
12
+ # TODO: remove this support for older Rails versions, which aren't supported by Turbo
13
+ # and/or responders. It won't allow configuring a custom response, but it allows Devise
14
+ # to use these methods and defaults across the implementation more easily.
15
+ def self.error_status
16
+ :ok
17
+ end
18
+
19
+ def self.redirect_status
20
+ :found
21
+ end
22
+
23
+ def self.error_status=(*)
24
+ warn "[DEVISE] Setting the error status on the Devise responder has no effect with this " \
25
+ "version of `responders`, please make sure you're using a newer version. Check the changelog for more info."
26
+ end
27
+
28
+ def self.redirect_status=(*)
29
+ warn "[DEVISE] Setting the redirect status on the Devise responder has no effect with this " \
30
+ "version of `responders`, please make sure you're using a newer version. Check the changelog for more info."
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -10,7 +10,7 @@ module Devise
10
10
  # cause exceptions to be thrown from this method; if you simply want to check
11
11
  # if a scope has already previously been authenticated without running
12
12
  # authentication hooks, you can directly call `warden.authenticated?(scope: scope)`
13
- def signed_in?(scope=nil)
13
+ def signed_in?(scope = nil)
14
14
  [scope || Devise.mappings.keys].flatten.any? do |_scope|
15
15
  warden.authenticate?(scope: _scope)
16
16
  end
@@ -19,6 +19,9 @@ module Devise
19
19
  # Sign in a user that already was authenticated. This helper is useful for logging
20
20
  # users in after sign up. All options given to sign_in is passed forward
21
21
  # to the set_user method in warden.
22
+ # If you are using a custom warden strategy and the timeoutable module, you have to
23
+ # set `env["devise.skip_timeout"] = true` in the request to use this method, like we do
24
+ # in the sessions controller: https://github.com/heartcombo/devise/blob/main/app/controllers/devise/sessions_controller.rb#L7
22
25
  #
23
26
  # Examples:
24
27
  #
@@ -35,7 +38,7 @@ module Devise
35
38
  expire_data_after_sign_in!
36
39
 
37
40
  if options[:bypass]
38
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
41
+ Devise.deprecator.warn(<<-DEPRECATION.strip_heredoc, caller)
39
42
  [Devise] bypass option is deprecated and it will be removed in future version of Devise.
40
43
  Please use bypass_sign_in method instead.
41
44
  Example:
@@ -74,7 +77,7 @@ module Devise
74
77
  # sign_out :user # sign_out(scope)
75
78
  # sign_out @user # sign_out(resource)
76
79
  #
77
- def sign_out(resource_or_scope=nil)
80
+ def sign_out(resource_or_scope = nil)
78
81
  return sign_out_all_scopes unless resource_or_scope
79
82
  scope = Devise::Mapping.find_scope!(resource_or_scope)
80
83
  user = warden.user(scope: scope, run_callbacks: false) # If there is no user
@@ -89,7 +92,7 @@ module Devise
89
92
  # Sign out all active users or scopes. This helper is useful for signing out all roles
90
93
  # in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout
91
94
  # and false if there was no user logged in on all scopes.
92
- def sign_out_all_scopes(lock=true)
95
+ def sign_out_all_scopes(lock = true)
93
96
  users = Devise.mappings.keys.map { |s| warden.user(scope: s, run_callbacks: false) }
94
97
 
95
98
  warden.logout
@@ -103,10 +106,12 @@ module Devise
103
106
  private
104
107
 
105
108
  def expire_data_after_sign_in!
109
+ # TODO: remove once Rails 5.2+ and forward are only supported.
106
110
  # session.keys will return an empty array if the session is not yet loaded.
107
111
  # This is a bug in both Rack and Rails.
108
112
  # A call to #empty? forces the session to be loaded.
109
113
  session.empty?
114
+
110
115
  session.keys.grep(/^devise\./).each { |k| session.delete(k) }
111
116
  end
112
117
 
@@ -34,7 +34,7 @@ module Devise
34
34
  end
35
35
  end
36
36
 
37
- def self.generate_helpers!(routes=nil)
37
+ def self.generate_helpers!(routes = nil)
38
38
  routes ||= begin
39
39
  mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
40
40
  Devise::URL_HELPERS.slice(*mappings)
@@ -18,6 +18,11 @@ module Devise
18
18
 
19
19
  delegate :flash, to: :request
20
20
 
21
+ include AbstractController::Callbacks
22
+ around_action do |failure_app, action|
23
+ I18n.with_locale(failure_app.i18n_locale, &action)
24
+ end
25
+
21
26
  def self.call(env)
22
27
  @respond ||= action(:respond)
23
28
  @respond.call(env)
@@ -71,8 +76,11 @@ module Devise
71
76
  end
72
77
 
73
78
  flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
74
- # self.response = recall_app(warden_options[:recall]).call(env)
75
- self.response = recall_app(warden_options[:recall]).call(request.env)
79
+ self.response = recall_app(warden_options[:recall]).call(request.env).tap { |response|
80
+ response[0] = Rack::Utils.status_code(
81
+ response[0].in?(300..399) ? Devise.responder.redirect_status : Devise.responder.error_status
82
+ )
83
+ }
76
84
  end
77
85
 
78
86
  def redirect
@@ -104,15 +112,19 @@ module Devise
104
112
  options[:default] = [message]
105
113
  auth_keys = scope_class.authentication_keys
106
114
  keys = (auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys).map { |key| scope_class.human_attribute_name(key) }
107
- options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
115
+ options[:authentication_keys] = keys.join(I18n.t(:"support.array.words_connector"))
108
116
  options = i18n_options(options)
109
117
 
110
- I18n.t(:"#{scope}.#{message}", options)
118
+ I18n.t(:"#{scope}.#{message}", **options)
111
119
  else
112
120
  message.to_s
113
121
  end
114
122
  end
115
123
 
124
+ def i18n_locale
125
+ warden_options[:locale]
126
+ end
127
+
116
128
  def redirect_url
117
129
  if warden_message == :timeout
118
130
  flash[:timedout] = true if is_flashing_format?
@@ -144,11 +156,20 @@ module Devise
144
156
 
145
157
  opts[:format] = request_format unless skip_format?
146
158
 
147
- opts[:script_name] = relative_url_root if relative_url_root?
148
-
149
159
  router_name = Devise.mappings[scope].router_name || Devise.available_router_name
150
160
  context = send(router_name)
151
161
 
162
+ if relative_url_root?
163
+ opts[:script_name] = relative_url_root
164
+
165
+ # We need to add the rootpath to `script_name` manually for applications that use a Rails
166
+ # version lower than 5.1. Otherwise, it is going to generate a wrong path for Engines
167
+ # that use Devise. Remove it when the support of Rails 5.0 is dropped.
168
+ elsif root_path_defined?(context) && !rails_51_and_up?
169
+ rootpath = context.routes.url_helpers.root_path
170
+ opts[:script_name] = rootpath.chomp('/') if rootpath.length > 1
171
+ end
172
+
152
173
  if context.respond_to?(route)
153
174
  context.send(route, opts)
154
175
  elsif respond_to?(:root_url)
@@ -159,7 +180,7 @@ module Devise
159
180
  end
160
181
 
161
182
  def skip_format?
162
- %w(html */*).include? request_format.to_s
183
+ %w(html */* turbo_stream).include? request_format.to_s
163
184
  end
164
185
 
165
186
  # Choose whether we should respond in an HTTP authentication fashion,
@@ -242,7 +263,7 @@ module Devise
242
263
  # Check if flash messages should be emitted. Default is to do it on
243
264
  # navigational formats
244
265
  def is_flashing_format?
245
- is_navigational_format?
266
+ request.respond_to?(:flash) && is_navigational_format?
246
267
  end
247
268
 
248
269
  def request_format
@@ -260,5 +281,17 @@ module Devise
260
281
  def relative_url_root?
261
282
  relative_url_root.present?
262
283
  end
284
+
285
+ ActiveSupport.run_load_hooks(:devise_failure_app, self)
286
+
287
+ private
288
+
289
+ def root_path_defined?(context)
290
+ defined?(context.routes) && context.routes.url_helpers.respond_to?(:root_path)
291
+ end
292
+
293
+ def rails_51_and_up?
294
+ Rails.gem_version >= Gem::Version.new("5.1")
295
+ end
263
296
  end
264
297
  end
@@ -4,6 +4,11 @@ Warden::Manager.after_authentication do |record, warden, options|
4
4
  clean_up_for_winning_strategy = !warden.winning_strategy.respond_to?(:clean_up_csrf?) ||
5
5
  warden.winning_strategy.clean_up_csrf?
6
6
  if Devise.clean_up_csrf_token_on_authentication && clean_up_for_winning_strategy
7
- warden.request.session.try(:delete, :_csrf_token)
7
+ if warden.request.respond_to?(:reset_csrf_token)
8
+ # Rails 7.1+
9
+ warden.request.reset_csrf_token
10
+ else
11
+ warden.request.session.try(:delete, :_csrf_token)
12
+ end
8
13
  end
9
14
  end
@@ -3,10 +3,7 @@
3
3
  # After each sign in, if resource responds to failed_attempts, sets it to 0
4
4
  # This is only triggered when the user is explicitly set (with set_user)
5
5
  Warden::Manager.after_set_user except: :fetch do |record, warden, options|
6
- if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
7
- unless record.failed_attempts.to_i.zero?
8
- record.failed_attempts = 0
9
- record.save(validate: false)
10
- end
6
+ if record.respond_to?(:reset_failed_attempts!) && warden.authenticated?(options[:scope])
7
+ record.reset_failed_attempts!
11
8
  end
12
9
  end
@@ -21,8 +21,8 @@ Warden::Manager.after_set_user do |record, warden, options|
21
21
 
22
22
  proxy = Devise::Hooks::Proxy.new(warden)
23
23
 
24
- if record.timedout?(last_request_at) &&
25
- !env['devise.skip_timeout'] &&
24
+ if !env['devise.skip_timeout'] &&
25
+ record.timedout?(last_request_at) &&
26
26
  !proxy.remember_me_is_active?(record)
27
27
  Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
28
28
  throw :warden, scope: scope, message: :timeout
@@ -46,7 +46,7 @@ module Devise
46
46
  raise "Could not find a valid mapping for #{obj.inspect}"
47
47
  end
48
48
 
49
- def self.find_by_path!(path, path_type=:fullpath)
49
+ def self.find_by_path!(path, path_type = :fullpath)
50
50
  Devise.mappings.each_value { |m| return m if path.include?(m.send(path_type)) }
51
51
  raise "Could not find a valid mapping for path #{path.inspect}"
52
52
  end