devise 4.1.1 → 4.8.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.
Files changed (255) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +224 -4
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +275 -90
  5. data/app/controllers/devise/confirmations_controller.rb +2 -0
  6. data/app/controllers/devise/omniauth_callbacks_controller.rb +7 -5
  7. data/app/controllers/devise/passwords_controller.rb +3 -0
  8. data/app/controllers/devise/registrations_controller.rb +34 -13
  9. data/app/controllers/devise/sessions_controller.rb +3 -1
  10. data/app/controllers/devise/unlocks_controller.rb +2 -0
  11. data/app/controllers/devise_controller.rb +5 -3
  12. data/app/helpers/devise_helper.rb +23 -18
  13. data/app/mailers/devise/mailer.rb +10 -4
  14. data/app/views/devise/confirmations/new.html.erb +2 -2
  15. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  16. data/app/views/devise/passwords/edit.html.erb +3 -3
  17. data/app/views/devise/passwords/new.html.erb +2 -2
  18. data/app/views/devise/registrations/edit.html.erb +9 -5
  19. data/app/views/devise/registrations/new.html.erb +4 -4
  20. data/app/views/devise/sessions/new.html.erb +4 -4
  21. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  22. data/app/views/devise/shared/_links.html.erb +8 -8
  23. data/app/views/devise/unlocks/new.html.erb +2 -2
  24. data/config/locales/en.yml +5 -2
  25. data/lib/devise.rb +39 -17
  26. data/lib/devise/controllers/helpers.rb +22 -9
  27. data/lib/devise/controllers/rememberable.rb +3 -1
  28. data/lib/devise/controllers/scoped_views.rb +2 -0
  29. data/lib/devise/controllers/sign_in_out.rb +39 -14
  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 +63 -33
  35. data/lib/devise/hooks/activatable.rb +2 -0
  36. data/lib/devise/hooks/csrf_cleaner.rb +2 -0
  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 +4 -2
  42. data/lib/devise/hooks/trackable.rb +2 -0
  43. data/lib/devise/mailers/helpers.rb +6 -3
  44. data/lib/devise/mapping.rb +3 -1
  45. data/lib/devise/models.rb +3 -1
  46. data/lib/devise/models/authenticatable.rb +63 -37
  47. data/lib/devise/models/confirmable.rb +79 -22
  48. data/lib/devise/models/database_authenticatable.rb +86 -17
  49. data/lib/devise/models/lockable.rb +17 -3
  50. data/lib/devise/models/omniauthable.rb +2 -0
  51. data/lib/devise/models/recoverable.rb +32 -20
  52. data/lib/devise/models/registerable.rb +4 -0
  53. data/lib/devise/models/rememberable.rb +5 -3
  54. data/lib/devise/models/timeoutable.rb +2 -0
  55. data/lib/devise/models/trackable.rb +15 -1
  56. data/lib/devise/models/validatable.rb +10 -3
  57. data/lib/devise/modules.rb +2 -0
  58. data/lib/devise/omniauth.rb +4 -5
  59. data/lib/devise/omniauth/config.rb +2 -0
  60. data/lib/devise/omniauth/url_helpers.rb +2 -51
  61. data/lib/devise/orm/active_record.rb +5 -1
  62. data/lib/devise/orm/mongoid.rb +6 -2
  63. data/lib/devise/parameter_filter.rb +4 -0
  64. data/lib/devise/parameter_sanitizer.rb +15 -56
  65. data/lib/devise/rails.rb +6 -6
  66. data/lib/devise/rails/deprecated_constant_accessor.rb +39 -0
  67. data/lib/devise/rails/routes.rb +9 -7
  68. data/lib/devise/rails/warden_compat.rb +2 -0
  69. data/lib/devise/secret_key_finder.rb +27 -0
  70. data/lib/devise/strategies/authenticatable.rb +3 -1
  71. data/lib/devise/strategies/base.rb +2 -0
  72. data/lib/devise/strategies/database_authenticatable.rb +8 -1
  73. data/lib/devise/strategies/rememberable.rb +2 -0
  74. data/lib/devise/test/controller_helpers.rb +167 -0
  75. data/lib/devise/test/integration_helpers.rb +63 -0
  76. data/lib/devise/test_helpers.rb +7 -129
  77. data/lib/devise/time_inflector.rb +2 -0
  78. data/lib/devise/token_generator.rb +2 -0
  79. data/lib/devise/version.rb +3 -1
  80. data/lib/generators/active_record/devise_generator.rb +40 -12
  81. data/lib/generators/active_record/templates/migration.rb +3 -1
  82. data/lib/generators/active_record/templates/migration_existing.rb +2 -0
  83. data/lib/generators/devise/controllers_generator.rb +3 -1
  84. data/lib/generators/devise/devise_generator.rb +5 -3
  85. data/lib/generators/devise/install_generator.rb +3 -5
  86. data/lib/generators/devise/orm_helpers.rb +9 -3
  87. data/lib/generators/devise/views_generator.rb +8 -9
  88. data/lib/generators/mongoid/devise_generator.rb +7 -5
  89. data/lib/generators/templates/README +9 -8
  90. data/lib/generators/templates/controllers/confirmations_controller.rb +2 -0
  91. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +3 -1
  92. data/lib/generators/templates/controllers/passwords_controller.rb +2 -0
  93. data/lib/generators/templates/controllers/registrations_controller.rb +4 -2
  94. data/lib/generators/templates/controllers/sessions_controller.rb +3 -1
  95. data/lib/generators/templates/controllers/unlocks_controller.rb +2 -0
  96. data/lib/generators/templates/devise.rb +49 -6
  97. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  98. data/lib/generators/templates/markerb/password_change.markerb +2 -2
  99. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +5 -1
  100. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +10 -2
  101. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +4 -1
  102. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +11 -3
  103. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +11 -3
  104. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +7 -2
  105. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +4 -1
  106. metadata +16 -297
  107. data/.gitignore +0 -10
  108. data/.travis.yml +0 -44
  109. data/.yardopts +0 -9
  110. data/CODE_OF_CONDUCT.md +0 -22
  111. data/CONTRIBUTING.md +0 -16
  112. data/Gemfile +0 -30
  113. data/Gemfile.lock +0 -182
  114. data/Rakefile +0 -36
  115. data/bin/test +0 -13
  116. data/devise.gemspec +0 -26
  117. data/devise.png +0 -0
  118. data/gemfiles/Gemfile.rails-4.1-stable +0 -30
  119. data/gemfiles/Gemfile.rails-4.1-stable.lock +0 -170
  120. data/gemfiles/Gemfile.rails-4.2-stable +0 -30
  121. data/gemfiles/Gemfile.rails-4.2-stable.lock +0 -192
  122. data/gemfiles/Gemfile.rails-5.0-beta +0 -37
  123. data/gemfiles/Gemfile.rails-5.0-beta.lock +0 -199
  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.ru +0 -4
  220. data/test/rails_app/config/application.rb +0 -44
  221. data/test/rails_app/config/boot.rb +0 -14
  222. data/test/rails_app/config/database.yml +0 -18
  223. data/test/rails_app/config/environment.rb +0 -5
  224. data/test/rails_app/config/environments/development.rb +0 -30
  225. data/test/rails_app/config/environments/production.rb +0 -84
  226. data/test/rails_app/config/environments/test.rb +0 -46
  227. data/test/rails_app/config/initializers/backtrace_silencers.rb +0 -7
  228. data/test/rails_app/config/initializers/devise.rb +0 -180
  229. data/test/rails_app/config/initializers/inflections.rb +0 -2
  230. data/test/rails_app/config/initializers/secret_token.rb +0 -3
  231. data/test/rails_app/config/initializers/session_store.rb +0 -1
  232. data/test/rails_app/config/routes.rb +0 -126
  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
  module Warden::Mixins::Common
2
4
  def request
3
5
  @request ||= ActionDispatch::Request.new(env)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ class SecretKeyFinder
5
+ def initialize(application)
6
+ @application = application
7
+ end
8
+
9
+ def find
10
+ if @application.respond_to?(:credentials) && key_exists?(@application.credentials)
11
+ @application.credentials.secret_key_base
12
+ elsif @application.respond_to?(:secrets) && key_exists?(@application.secrets)
13
+ @application.secrets.secret_key_base
14
+ elsif @application.config.respond_to?(:secret_key_base) && key_exists?(@application.config)
15
+ @application.config.secret_key_base
16
+ elsif @application.respond_to?(:secret_key_base) && key_exists?(@application)
17
+ @application.secret_key_base
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def key_exists?(object)
24
+ object.secret_key_base.present?
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/strategies/base'
2
4
 
3
5
  module Devise
@@ -26,7 +28,7 @@ module Devise
26
28
  private
27
29
 
28
30
  # Receives a resource and check if it is valid by calling valid_for_authentication?
29
- # An optional block that will be triggered while validating can be optionally
31
+ # A block that will be triggered while validating can be optionally
30
32
  # given as parameter. Check Devise::Models::Authenticatable.valid_for_authentication?
31
33
  # for more information.
32
34
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
4
  module Strategies
3
5
  # Base strategy for Devise. Responsible for verifying correct scope and mapping.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/strategies/authenticatable'
2
4
 
3
5
  module Devise
@@ -14,8 +16,13 @@ module Devise
14
16
  success!(resource)
15
17
  end
16
18
 
19
+ # In paranoid mode, hash the password even when a resource doesn't exist for the given authentication key.
20
+ # This is necessary to prevent enumeration attacks - e.g. the request is faster when a resource doesn't
21
+ # exist in the database if the password hashing algorithm is not called.
17
22
  mapping.to.new.password = password if !hashed && Devise.paranoid
18
- fail(:not_found_in_database) unless resource
23
+ unless resource
24
+ Devise.paranoid ? fail(:invalid) : fail(:not_found_in_database)
25
+ end
19
26
  end
20
27
  end
21
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'devise/strategies/authenticatable'
2
4
 
3
5
  module Devise
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ module Test
5
+ # `Devise::Test::ControllerHelpers` provides a facility to test controllers
6
+ # in isolation when using `ActionController::TestCase` allowing you to
7
+ # quickly sign_in or sign_out a user. Do not use
8
+ # `Devise::Test::ControllerHelpers` in integration tests.
9
+ #
10
+ # Examples
11
+ #
12
+ # class PostsTest < ActionController::TestCase
13
+ # include Devise::Test::ControllerHelpers
14
+ #
15
+ # test 'authenticated users can GET index' do
16
+ # sign_in users(:bob)
17
+ #
18
+ # get :index
19
+ # assert_response :success
20
+ # end
21
+ # end
22
+ #
23
+ # Important: you should not test Warden specific behavior (like callbacks)
24
+ # using `Devise::Test::ControllerHelpers` since it is a stub of the actual
25
+ # behavior. Such callbacks should be tested in your integration suite instead.
26
+ module ControllerHelpers
27
+ extend ActiveSupport::Concern
28
+
29
+ included do
30
+ setup :setup_controller_for_warden, :warden
31
+ end
32
+
33
+ # Override process to consider warden.
34
+ def process(*)
35
+ _catch_warden { super }
36
+
37
+ @response
38
+ end
39
+
40
+ ruby2_keywords(:process) if respond_to?(:ruby2_keywords, true)
41
+
42
+ # We need to set up the environment variables and the response in the controller.
43
+ def setup_controller_for_warden #:nodoc:
44
+ @request.env['action_controller.instance'] = @controller
45
+ end
46
+
47
+ # Quick access to Warden::Proxy.
48
+ def warden #:nodoc:
49
+ @request.env['warden'] ||= begin
50
+ manager = Warden::Manager.new(nil) do |config|
51
+ config.merge! Devise.warden_config
52
+ end
53
+ Warden::Proxy.new(@request.env, manager)
54
+ end
55
+ end
56
+
57
+ # sign_in a given resource by storing its keys in the session.
58
+ # This method bypass any warden authentication callback.
59
+ #
60
+ # * +resource+ - The resource that should be authenticated
61
+ # * +scope+ - An optional +Symbol+ with the scope where the resource
62
+ # should be signed in with.
63
+ # Examples:
64
+ #
65
+ # sign_in users(:alice)
66
+ # sign_in users(:alice), scope: :admin
67
+ def sign_in(resource, deprecated = nil, scope: nil)
68
+ if deprecated.present?
69
+ scope = resource
70
+ resource = deprecated
71
+
72
+ ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
73
+ [Devise] sign_in(:#{scope}, resource) on controller tests is deprecated and will be removed from Devise.
74
+ Please use sign_in(resource, scope: :#{scope}) instead.
75
+ DEPRECATION
76
+ end
77
+
78
+ scope ||= Devise::Mapping.find_scope!(resource)
79
+
80
+ warden.instance_variable_get(:@users).delete(scope)
81
+ warden.session_serializer.store(resource, scope)
82
+ end
83
+
84
+ # Sign out a given resource or scope by calling logout on Warden.
85
+ # This method bypass any warden logout callback.
86
+ #
87
+ # Examples:
88
+ #
89
+ # sign_out :user # sign_out(scope)
90
+ # sign_out @user # sign_out(resource)
91
+ #
92
+ def sign_out(resource_or_scope)
93
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
94
+ @controller.instance_variable_set(:"@current_#{scope}", nil)
95
+ user = warden.instance_variable_get(:@users).delete(scope)
96
+ warden.session_serializer.delete(scope, user)
97
+ end
98
+
99
+ protected
100
+
101
+ # Catch warden continuations and handle like the middleware would.
102
+ # Returns nil when interrupted, otherwise the normal result of the block.
103
+ def _catch_warden(&block)
104
+ result = catch(:warden, &block)
105
+
106
+ env = @controller.request.env
107
+
108
+ result ||= {}
109
+
110
+ # Set the response. In production, the rack result is returned
111
+ # from Warden::Manager#call, which the following is modelled on.
112
+ case result
113
+ when Array
114
+ if result.first == 401 && intercept_401?(env) # does this happen during testing?
115
+ _process_unauthenticated(env)
116
+ else
117
+ result
118
+ end
119
+ when Hash
120
+ _process_unauthenticated(env, result)
121
+ else
122
+ result
123
+ end
124
+ end
125
+
126
+ def _process_unauthenticated(env, options = {})
127
+ options[:action] ||= :unauthenticated
128
+ proxy = request.env['warden']
129
+ result = options[:result] || proxy.result
130
+
131
+ ret = case result
132
+ when :redirect
133
+ body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
134
+ [proxy.status, proxy.headers, [body]]
135
+ when :custom
136
+ proxy.custom_response
137
+ else
138
+ request.env["PATH_INFO"] = "/#{options[:action]}"
139
+ request.env["warden.options"] = options
140
+ Warden::Manager._run_callbacks(:before_failure, env, options)
141
+
142
+ status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
143
+ @controller.response.headers.merge!(headers)
144
+ @controller.response.content_type = headers["Content-Type"] unless Rails::VERSION::MAJOR >= 5
145
+ @controller.status = status
146
+ @controller.response_body = response.body
147
+ nil # causes process return @response
148
+ end
149
+
150
+ # ensure that the controller response is set up. In production, this is
151
+ # not necessary since warden returns the results to rack. However, at
152
+ # testing time, we want the response to be available to the testing
153
+ # framework to verify what would be returned to rack.
154
+ if ret.is_a?(Array)
155
+ status, headers, body = *ret
156
+ # ensure the controller response is set to our response.
157
+ @controller.response ||= @response
158
+ @response.status = status
159
+ @response.headers.merge!(headers)
160
+ @response.body = body
161
+ end
162
+
163
+ ret
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ # Devise::Test::IntegrationHelpers is a helper module for facilitating
5
+ # authentication on Rails integration tests to bypass the required steps for
6
+ # signin in or signin out a record.
7
+ #
8
+ # Examples
9
+ #
10
+ # class PostsTest < ActionDispatch::IntegrationTest
11
+ # include Devise::Test::IntegrationHelpers
12
+ #
13
+ # test 'authenticated users can see posts' do
14
+ # sign_in users(:bob)
15
+ #
16
+ # get '/posts'
17
+ # assert_response :success
18
+ # end
19
+ # end
20
+ module Test
21
+ module IntegrationHelpers
22
+ def self.included(base)
23
+ base.class_eval do
24
+ include Warden::Test::Helpers
25
+
26
+ setup :setup_integration_for_devise
27
+ teardown :teardown_integration_for_devise
28
+ end
29
+ end
30
+
31
+ # Signs in a specific resource, mimicking a successful sign in
32
+ # operation through +Devise::SessionsController#create+.
33
+ #
34
+ # * +resource+ - The resource that should be authenticated
35
+ # * +scope+ - An optional +Symbol+ with the scope where the resource
36
+ # should be signed in with.
37
+ def sign_in(resource, scope: nil)
38
+ scope ||= Devise::Mapping.find_scope!(resource)
39
+
40
+ login_as(resource, scope: scope)
41
+ end
42
+
43
+ # Signs out a specific scope from the session.
44
+ #
45
+ # * +resource_or_scope+ - The resource or scope that should be signed out.
46
+ def sign_out(resource_or_scope)
47
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
48
+
49
+ logout scope
50
+ end
51
+
52
+ protected
53
+
54
+ def setup_integration_for_devise
55
+ Warden.test_mode!
56
+ end
57
+
58
+ def teardown_integration_for_devise
59
+ Warden.test_reset!
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,137 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Devise
2
- # Devise::TestHelpers provides a facility to test controllers in isolation
3
- # when using ActionController::TestCase allowing you to quickly sign_in or
4
- # sign_out a user. Do not use Devise::TestHelpers in integration tests.
5
- #
6
- # Notice you should not test Warden specific behavior (like Warden callbacks)
7
- # using Devise::TestHelpers since it is a stub of the actual behavior. Such
8
- # callbacks should be tested in your integration suite instead.
9
4
  module TestHelpers
10
5
  def self.included(base)
11
6
  base.class_eval do
12
- setup :setup_controller_for_warden, :warden if respond_to?(:setup)
13
- end
14
- end
15
-
16
- # Override process to consider warden.
17
- def process(*)
18
- # Make sure we always return @response, a la ActionController::TestCase::Behaviour#process, even if warden interrupts
19
- _catch_warden { super } # || @response # _catch_warden will setup the @response object
20
-
21
- # process needs to return the ActionDispath::TestResponse object
22
- @response
23
- end
24
-
25
- # We need to set up the environment variables and the response in the controller.
26
- def setup_controller_for_warden #:nodoc:
27
- @request.env['action_controller.instance'] = @controller
28
- end
29
-
30
- # Quick access to Warden::Proxy.
31
- def warden #:nodoc:
32
- @request.env['warden'] ||= begin
33
- manager = Warden::Manager.new(nil) do |config|
34
- config.merge! Devise.warden_config
35
- end
36
- Warden::Proxy.new(@request.env, manager)
37
- end
38
- end
39
-
40
- # sign_in a given resource by storing its keys in the session.
41
- # This method bypass any warden authentication callback.
42
- #
43
- # Examples:
44
- #
45
- # sign_in :user, @user # sign_in(scope, resource)
46
- # sign_in @user # sign_in(resource)
47
- #
48
- def sign_in(resource_or_scope, resource=nil)
49
- scope ||= Devise::Mapping.find_scope!(resource_or_scope)
50
- resource ||= resource_or_scope
51
- warden.instance_variable_get(:@users).delete(scope)
52
- warden.session_serializer.store(resource, scope)
53
- end
54
-
55
- # Sign out a given resource or scope by calling logout on Warden.
56
- # This method bypass any warden logout callback.
57
- #
58
- # Examples:
59
- #
60
- # sign_out :user # sign_out(scope)
61
- # sign_out @user # sign_out(resource)
62
- #
63
- def sign_out(resource_or_scope)
64
- scope = Devise::Mapping.find_scope!(resource_or_scope)
65
- @controller.instance_variable_set(:"@current_#{scope}", nil)
66
- user = warden.instance_variable_get(:@users).delete(scope)
67
- warden.session_serializer.delete(scope, user)
68
- end
69
-
70
- protected
71
-
72
- # Catch warden continuations and handle like the middleware would.
73
- # Returns nil when interrupted, otherwise the normal result of the block.
74
- def _catch_warden(&block)
75
- result = catch(:warden, &block)
76
-
77
- env = @controller.request.env
78
-
79
- result ||= {}
80
-
81
- # Set the response. In production, the rack result is returned
82
- # from Warden::Manager#call, which the following is modelled on.
83
- case result
84
- when Array
85
- if result.first == 401 && intercept_401?(env) # does this happen during testing?
86
- _process_unauthenticated(env)
87
- else
88
- result
89
- end
90
- when Hash
91
- _process_unauthenticated(env, result)
92
- else
93
- result
94
- end
95
- end
96
-
97
- def _process_unauthenticated(env, options = {})
98
- options[:action] ||= :unauthenticated
99
- proxy = env['warden']
100
- result = options[:result] || proxy.result
101
-
102
- ret = case result
103
- when :redirect
104
- body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
105
- [proxy.status, proxy.headers, [body]]
106
- when :custom
107
- proxy.custom_response
108
- else
109
- env["PATH_INFO"] = "/#{options[:action]}"
110
- env["warden.options"] = options
111
- Warden::Manager._run_callbacks(:before_failure, env, options)
112
-
113
- status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
114
- @controller.response.headers.merge!(headers)
115
- r_opts = { status: status, content_type: headers["Content-Type"], location: headers["Location"] }
116
- r_opts[Rails.version.start_with?('5') ? :body : :text] = response.body
117
- @controller.send :render, r_opts
118
- nil # causes process return @response
7
+ ActiveSupport::Deprecation.warn <<-DEPRECATION.strip_heredoc
8
+ [Devise] including `Devise::TestHelpers` is deprecated and will be removed from Devise.
9
+ For controller tests, please include `Devise::Test::ControllerHelpers` instead.
10
+ DEPRECATION
11
+ include Devise::Test::ControllerHelpers
119
12
  end
120
-
121
- # ensure that the controller response is set up. In production, this is
122
- # not necessary since warden returns the results to rack. However, at
123
- # testing time, we want the response to be available to the testing
124
- # framework to verify what would be returned to rack.
125
- if ret.is_a?(Array)
126
- # ensure the controller response is set to our response.
127
- @controller.response ||= @response
128
- @response.status = ret.first
129
- @response.headers.clear
130
- ret.second.each { |k,v| @response[k] = v }
131
- @response.body = ret.third
132
- end
133
-
134
- ret
135
13
  end
136
14
  end
137
15
  end