devise 4.1.1 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -7
  3. data/CHANGELOG.md +46 -2
  4. data/CONTRIBUTING.md +30 -7
  5. data/Gemfile +14 -7
  6. data/Gemfile.lock +96 -81
  7. data/README.md +89 -37
  8. data/app/controllers/devise/omniauth_callbacks_controller.rb +3 -3
  9. data/app/controllers/devise/registrations_controller.rb +3 -3
  10. data/app/views/devise/registrations/edit.html.erb +4 -0
  11. data/gemfiles/Gemfile.rails-4.1-stable +4 -4
  12. data/gemfiles/Gemfile.rails-4.1-stable.lock +27 -23
  13. data/gemfiles/Gemfile.rails-4.2-stable +4 -4
  14. data/gemfiles/Gemfile.rails-4.2-stable.lock +58 -54
  15. data/guides/bug_report_templates/integration_test.rb +104 -0
  16. data/lib/devise.rb +21 -14
  17. data/lib/devise/controllers/helpers.rb +12 -1
  18. data/lib/devise/controllers/rememberable.rb +1 -1
  19. data/lib/devise/controllers/sign_in_out.rb +25 -10
  20. data/lib/devise/failure_app.rb +25 -17
  21. data/lib/devise/hooks/proxy.rb +1 -1
  22. data/lib/devise/models/authenticatable.rb +23 -2
  23. data/lib/devise/models/confirmable.rb +13 -7
  24. data/lib/devise/models/database_authenticatable.rb +0 -5
  25. data/lib/devise/models/recoverable.rb +10 -15
  26. data/lib/devise/omniauth/url_helpers.rb +0 -51
  27. data/lib/devise/orm/active_record.rb +3 -1
  28. data/lib/devise/orm/mongoid.rb +4 -2
  29. data/lib/devise/parameter_sanitizer.rb +0 -55
  30. data/lib/devise/rails.rb +3 -1
  31. data/lib/devise/test/controller_helpers.rb +162 -0
  32. data/lib/devise/test/integration_helpers.rb +61 -0
  33. data/lib/devise/test_helpers.rb +5 -129
  34. data/lib/devise/version.rb +1 -1
  35. data/lib/generators/templates/README +1 -8
  36. data/lib/generators/templates/devise.rb +6 -0
  37. data/test/controllers/custom_registrations_controller_test.rb +1 -1
  38. data/test/controllers/custom_strategy_test.rb +1 -1
  39. data/test/controllers/helpers_test.rb +4 -4
  40. data/test/controllers/internal_helpers_test.rb +1 -1
  41. data/test/controllers/passwords_controller_test.rb +1 -1
  42. data/test/controllers/sessions_controller_test.rb +2 -2
  43. data/test/devise_test.rb +9 -9
  44. data/test/failure_app_test.rb +18 -0
  45. data/test/integration/authenticatable_test.rb +36 -36
  46. data/test/integration/confirmable_test.rb +7 -7
  47. data/test/integration/database_authenticatable_test.rb +5 -5
  48. data/test/integration/http_authenticatable_test.rb +2 -2
  49. data/test/integration/lockable_test.rb +1 -1
  50. data/test/integration/mounted_engine_test.rb +36 -0
  51. data/test/integration/omniauthable_test.rb +1 -1
  52. data/test/integration/recoverable_test.rb +4 -4
  53. data/test/integration/registerable_test.rb +12 -6
  54. data/test/integration/rememberable_test.rb +10 -10
  55. data/test/integration/timeoutable_test.rb +5 -5
  56. data/test/mapping_test.rb +1 -1
  57. data/test/models/confirmable_test.rb +33 -25
  58. data/test/models/database_authenticatable_test.rb +13 -13
  59. data/test/models/lockable_test.rb +16 -16
  60. data/test/models/omniauthable_test.rb +1 -1
  61. data/test/models/recoverable_test.rb +10 -10
  62. data/test/models/registerable_test.rb +1 -1
  63. data/test/models/rememberable_test.rb +16 -3
  64. data/test/models/serializable_test.rb +5 -0
  65. data/test/models/timeoutable_test.rb +7 -7
  66. data/test/models/trackable_test.rb +1 -1
  67. data/test/models/validatable_test.rb +1 -1
  68. data/test/models_test.rb +2 -2
  69. data/test/parameter_sanitizer_test.rb +0 -56
  70. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +1 -1
  71. data/test/rails_app/config/environments/production.rb +3 -1
  72. data/test/rails_app/config/environments/test.rb +5 -6
  73. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +5 -1
  74. data/test/support/assertions.rb +0 -11
  75. data/test/{test_helpers_test.rb → test/controller_helpers_test.rb} +2 -2
  76. data/test/test/integration_helpers_test.rb +32 -0
  77. metadata +11 -6
  78. data/gemfiles/Gemfile.rails-5.0-beta +0 -37
  79. data/gemfiles/Gemfile.rails-5.0-beta.lock +0 -199
@@ -50,13 +50,11 @@ module Devise
50
50
  end
51
51
 
52
52
  def recall
53
- config = Rails.application.config
54
-
55
- header_info = if config.try(:relative_url_root)
56
- base_path = Pathname.new(config.relative_url_root)
53
+ header_info = if relative_url_root?
54
+ base_path = Pathname.new(relative_url_root)
57
55
  full_path = Pathname.new(attempted_path)
58
56
 
59
- { "SCRIPT_NAME" => config.relative_url_root,
57
+ { "SCRIPT_NAME" => relative_url_root,
60
58
  "PATH_INFO" => '/' + full_path.relative_path_from(base_path).to_s }
61
59
  else
62
60
  { "PATH_INFO" => attempted_path }
@@ -66,7 +64,7 @@ module Devise
66
64
  if request.respond_to?(:set_header)
67
65
  request.set_header(var, value)
68
66
  else
69
- env[var] = value
67
+ request.env[var] = value
70
68
  end
71
69
  end
72
70
 
@@ -135,18 +133,16 @@ module Devise
135
133
 
136
134
  def scope_url
137
135
  opts = {}
136
+
137
+ # Initialize script_name with nil to prevent infinite loops in
138
+ # authenticated mounted engines in rails 4.2 and 5.0
139
+ opts[:script_name] = nil
140
+
138
141
  route = route(scope)
139
- opts[:format] = request_format unless skip_format?
140
142
 
141
- config = Rails.application.config
143
+ opts[:format] = request_format unless skip_format?
142
144
 
143
- if config.respond_to?(:relative_url_root)
144
- # Rails 4.2 goes into an infinite loop if opts[:script_name] is unset
145
- rails_4_2 = (Rails::VERSION::MAJOR >= 4) && (Rails::VERSION::MINOR >= 2)
146
- if config.relative_url_root.present? || rails_4_2
147
- opts[:script_name] = config.relative_url_root
148
- end
149
- end
145
+ opts[:script_name] = relative_url_root if relative_url_root?
150
146
 
151
147
  router_name = Devise.mappings[scope].router_name || Devise.available_router_name
152
148
  context = send(router_name)
@@ -206,11 +202,11 @@ module Devise
206
202
  end
207
203
 
208
204
  def warden
209
- request.respond_to?(:get_header) ? request.get_header("warden") : env["warden"]
205
+ request.respond_to?(:get_header) ? request.get_header("warden") : request.env["warden"]
210
206
  end
211
207
 
212
208
  def warden_options
213
- request.respond_to?(:get_header) ? request.get_header("warden.options") : env["warden.options"]
209
+ request.respond_to?(:get_header) ? request.get_header("warden.options") : request.env["warden.options"]
214
210
  end
215
211
 
216
212
  def warden_message
@@ -250,5 +246,17 @@ module Devise
250
246
  def request_format
251
247
  @request_format ||= request.format.try(:ref)
252
248
  end
249
+
250
+ def relative_url_root
251
+ @relative_url_root ||= begin
252
+ config = Rails.application.config
253
+
254
+ config.try(:relative_url_root) || config.action_controller.try(:relative_url_root)
255
+ end
256
+ end
257
+
258
+ def relative_url_root?
259
+ relative_url_root.present?
260
+ end
253
261
  end
254
262
  end
@@ -7,7 +7,7 @@ module Devise
7
7
  include Devise::Controllers::SignInOut
8
8
 
9
9
  attr_reader :warden
10
- delegate :cookies, :env, to: :warden
10
+ delegate :cookies, :request, to: :warden
11
11
 
12
12
  def initialize(warden)
13
13
  @warden = warden
@@ -114,6 +114,15 @@ module Devise
114
114
  super(options)
115
115
  end
116
116
 
117
+ # Redefine inspect using serializable_hash, to ensure we don't accidentally
118
+ # leak passwords into exceptions.
119
+ def inspect
120
+ inspection = serializable_hash.collect do |k,v|
121
+ "#{k}: #{respond_to?(:attribute_for_inspect) ? attribute_for_inspect(k) : v.inspect}"
122
+ end
123
+ "#<#{self.class} #{inspection.join(", ")}>"
124
+ end
125
+
117
126
  protected
118
127
 
119
128
  def devise_mailer
@@ -143,13 +152,25 @@ module Devise
143
152
  # if new_record? || changed?
144
153
  # pending_notifications << [notification, args]
145
154
  # else
146
- # devise_mailer.send(notification, self, *args).deliver
155
+ # message = devise_mailer.send(notification, self, *args)
156
+ # Remove once we move to Rails 4.2+ only.
157
+ # if message.respond_to?(:deliver_now)
158
+ # message.deliver_now
159
+ # else
160
+ # message.deliver
161
+ # end
147
162
  # end
148
163
  # end
149
164
  #
150
165
  # def send_pending_notifications
151
166
  # pending_notifications.each do |notification, args|
152
- # devise_mailer.send(notification, self, *args).deliver
167
+ # message = devise_mailer.send(notification, self, *args)
168
+ # Remove once we move to Rails 4.2+ only.
169
+ # if message.respond_to?(:deliver_now)
170
+ # message.deliver_now
171
+ # else
172
+ # message.deliver
173
+ # end
153
174
  # end
154
175
  #
155
176
  # # Empty the pending notifications array because the
@@ -43,7 +43,7 @@ module Devise
43
43
 
44
44
  included do
45
45
  before_create :generate_confirmation_token, if: :confirmation_required?
46
- after_create :skip_reconfirmation!, if: :send_confirmation_notification?
46
+ after_create :skip_reconfirmation_in_callback!, if: :send_confirmation_notification?
47
47
  if respond_to?(:after_commit) # ActiveRecord
48
48
  after_commit :send_on_create_confirmation_instructions, on: :create, if: :send_confirmation_notification?
49
49
  after_commit :send_reconfirmation_instructions, on: :update, if: :reconfirmation_required?
@@ -56,6 +56,7 @@ module Devise
56
56
 
57
57
  def initialize(*args, &block)
58
58
  @bypass_confirmation_postpone = false
59
+ @skip_reconfirmation_in_callback = false
59
60
  @reconfirmation_required = false
60
61
  @skip_confirmation_notification = false
61
62
  @raw_confirmation_token = nil
@@ -97,11 +98,6 @@ module Devise
97
98
  end
98
99
  end
99
100
 
100
- def confirm!(args={})
101
- ActiveSupport::Deprecation.warn "confirm! is deprecated in favor of confirm"
102
- confirm(args)
103
- end
104
-
105
101
  # Verifies whether a user is confirmed or not
106
102
  def confirmed?
107
103
  !!confirmed_at
@@ -170,6 +166,12 @@ module Devise
170
166
 
171
167
  protected
172
168
 
169
+ # To not require reconfirmation after creating with #save called in a
170
+ # callback call skip_create_confirmation!
171
+ def skip_reconfirmation_in_callback!
172
+ @skip_reconfirmation_in_callback = true
173
+ end
174
+
173
175
  # A callback method used to deliver confirmation
174
176
  # instructions on creation. This can be overridden
175
177
  # in models to map to a nice sign up e-mail.
@@ -258,7 +260,11 @@ module Devise
258
260
  end
259
261
 
260
262
  def postpone_email_change?
261
- postpone = self.class.reconfirmable && email_changed? && !@bypass_confirmation_postpone && self.email.present?
263
+ postpone = self.class.reconfirmable &&
264
+ email_changed? &&
265
+ !@bypass_confirmation_postpone &&
266
+ self.email.present? &&
267
+ (!@skip_reconfirmation_in_callback || !self.email_was.nil?)
262
268
  @bypass_confirmation_postpone = false
263
269
  postpone
264
270
  end
@@ -1,11 +1,6 @@
1
1
  require 'devise/strategies/database_authenticatable'
2
2
 
3
3
  module Devise
4
- def self.bcrypt(klass, password)
5
- ActiveSupport::Deprecation.warn "Devise.bcrypt is deprecated; use Devise::Encryptor.digest instead"
6
- Devise::Encryptor.digest(klass, password)
7
- end
8
-
9
4
  module Models
10
5
  # Authenticatable Module, responsible for hashing the password and
11
6
  # validating the authenticity of a user while signing in.
@@ -27,11 +27,7 @@ module Devise
27
27
  end
28
28
 
29
29
  included do
30
- before_update do
31
- if (respond_to?(:email_changed?) && email_changed?) || encrypted_password_changed?
32
- clear_reset_password_token
33
- end
34
- end
30
+ before_update :clear_reset_password_token, if: :clear_reset_password_token?
35
31
  end
36
32
 
37
33
  # Update password saving the record and clearing token. Returns true if
@@ -40,19 +36,9 @@ module Devise
40
36
  self.password = new_password
41
37
  self.password_confirmation = new_password_confirmation
42
38
 
43
- if respond_to?(:after_password_reset) && valid?
44
- ActiveSupport::Deprecation.warn "after_password_reset is deprecated"
45
- after_password_reset
46
- end
47
-
48
39
  save
49
40
  end
50
41
 
51
- def reset_password!(new_password, new_password_confirmation)
52
- ActiveSupport::Deprecation.warn "reset_password! is deprecated in favor of reset_password"
53
- reset_password(new_password, new_password_confirmation)
54
- end
55
-
56
42
  # Resets reset password token and send reset password instructions by email.
57
43
  # Returns the token sent in the e-mail.
58
44
  def send_reset_password_instructions
@@ -107,6 +93,15 @@ module Devise
107
93
  send_devise_notification(:reset_password_instructions, token, {})
108
94
  end
109
95
 
96
+ def clear_reset_password_token?
97
+ encrypted_password_changed = respond_to?(:encrypted_password_changed?) && encrypted_password_changed?
98
+ authentication_keys_changed = self.class.authentication_keys.any? do |attribute|
99
+ respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?")
100
+ end
101
+
102
+ authentication_keys_changed || encrypted_password_changed
103
+ end
104
+
110
105
  module ClassMethods
111
106
  # Attempt to find a user by password reset token. If a user is found, return it
112
107
  # If a user is not found, return nil
@@ -1,57 +1,6 @@
1
1
  module Devise
2
2
  module OmniAuth
3
3
  module UrlHelpers
4
- def self.define_helpers(mapping)
5
- return unless mapping.omniauthable?
6
-
7
- mapping = mapping.name
8
-
9
- class_eval do
10
- define_method("#{mapping}_omniauth_authorize_path") do |provider, *args|
11
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
12
- [Devise] #{mapping}_omniauth_authorize_path(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
13
-
14
- Please use #{mapping}_#{provider}_omniauth_authorize_path instead.
15
- DEPRECATION
16
- send("#{mapping}_#{provider}_omniauth_authorize_path", *args)
17
- end
18
-
19
- define_method("#{mapping}_omniauth_authorize_url") do |provider, *args|
20
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
21
- [Devise] #{mapping}_omniauth_authorize_url(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
22
-
23
- Please use #{mapping}_#{provider}_omniauth_authorize_url instead.
24
- DEPRECATION
25
- send("#{mapping}_#{provider}_omniauth_authorize_url", *args)
26
- end
27
-
28
- define_method("#{mapping}_omniauth_callback_path") do |provider, *args|
29
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
30
- [Devise] #{mapping}_omniauth_callback_path(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
31
-
32
- Please use #{mapping}_#{provider}_omniauth_callback_path instead.
33
- DEPRECATION
34
- send("#{mapping}_#{provider}_omniauth_callback_path", *args)
35
- end
36
-
37
- define_method("#{mapping}_omniauth_callback_url") do |provider, *args|
38
- ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc)
39
- [Devise] #{mapping}_omniauth_callback_url(#{provider.inspect}) is deprecated and it will be removed from Devise 4.2.
40
-
41
- Please use #{mapping}_#{provider}_omniauth_callback_url instead.
42
- DEPRECATION
43
- send("#{mapping}_#{provider}_omniauth_callback_url", *args)
44
- end
45
- end
46
-
47
- ActiveSupport.on_load(:action_controller) do
48
- if respond_to?(:helper_method)
49
- helper_method "#{mapping}_omniauth_authorize_path", "#{mapping}_omniauth_authorize_url"
50
- helper_method "#{mapping}_omniauth_callback_path", "#{mapping}_omniauth_callback_url"
51
- end
52
- end
53
- end
54
-
55
4
  def omniauth_authorize_path(resource_or_scope, provider, *args)
56
5
  scope = Devise::Mapping.find_scope!(resource_or_scope)
57
6
  _devise_route_context.send("#{scope}_#{provider}_omniauth_authorize_path", *args)
@@ -1,3 +1,5 @@
1
1
  require 'orm_adapter/adapters/active_record'
2
2
 
3
- ActiveRecord::Base.extend Devise::Models
3
+ ActiveSupport.on_load(:active_record) do
4
+ extend Devise::Models
5
+ end
@@ -1,3 +1,5 @@
1
- require 'orm_adapter/adapters/mongoid'
1
+ ActiveSupport.on_load(:mongoid) do
2
+ require 'orm_adapter/adapters/mongoid'
2
3
 
3
- Mongoid::Document::ClassMethods.send :include, Devise::Models
4
+ Mongoid::Document::ClassMethods.send :include, Devise::Models
5
+ end
@@ -68,12 +68,6 @@ module Devise
68
68
  def sanitize(action)
69
69
  permissions = @permitted[action]
70
70
 
71
- # DEPRECATED: Remove this branch on Devise 4.2.
72
- if respond_to?(action, true)
73
- deprecate_instance_method_sanitization(action)
74
- return cast_to_hash send(action)
75
- end
76
-
77
71
  if permissions.respond_to?(:call)
78
72
  cast_to_hash permissions.call(default_params)
79
73
  elsif permissions.present?
@@ -127,17 +121,6 @@ module Devise
127
121
  end
128
122
  end
129
123
 
130
- # DEPRECATED: Remove this method on Devise 4.2.
131
- def for(action, &block) # :nodoc:
132
- if block_given?
133
- deprecate_for_with_block(action)
134
- permit(action, &block)
135
- else
136
- deprecate_for_without_block(action)
137
- @permitted[action] or unknown_action!(action)
138
- end
139
- end
140
-
141
124
  private
142
125
 
143
126
  # Cast a sanitized +ActionController::Parameters+ to a +HashWithIndifferentAccess+
@@ -172,43 +155,5 @@ module Devise
172
155
  devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
173
156
  MESSAGE
174
157
  end
175
-
176
- def deprecate_for_with_block(action)
177
- ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
178
- [Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.2.
179
- Please use the `permit` method:
180
-
181
- devise_parameter_sanitizer.permit(:#{action}) do |user|
182
- # Your block here.
183
- end
184
- MESSAGE
185
- end
186
-
187
- def deprecate_for_without_block(action)
188
- ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
189
- [Devise] Changing the sanitized parameters through "#{self.class.name}#for(#{action}) is deprecated and it will be removed from Devise 4.2.
190
- Please use the `permit` method to add or remove any key:
191
-
192
- To add any new key, use the `keys` keyword argument:
193
- devise_parameter_sanitizer.permit(:#{action}, keys: [:param1, :param2, :param3])
194
-
195
- To remove any existing key, use the `except` keyword argument:
196
- devise_parameter_sanitizer.permit(:#{action}, except: [:email])
197
- MESSAGE
198
- end
199
-
200
- def deprecate_instance_method_sanitization(action)
201
- ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
202
- [Devise] Parameter sanitization through a "#{self.class.name}##{action}" method is deprecated and it will be removed from Devise 4.2.
203
- Please use the `permit` method on your sanitizer `initialize` method.
204
-
205
- class #{self.class.name} < Devise::ParameterSanitizer
206
- def initialize(*)
207
- super
208
- permit(:#{action}, keys: [:param1, :param2, :param3])
209
- end
210
- end
211
- MESSAGE
212
- end
213
158
  end
214
159
  end
@@ -11,7 +11,9 @@ module Devise
11
11
  end
12
12
 
13
13
  # Force routes to be loaded if we are doing any eager load.
14
- config.before_eager_load { |app| app.reload_routes! }
14
+ config.before_eager_load do |app|
15
+ app.reload_routes! if Devise.reload_routes
16
+ end
15
17
 
16
18
  initializer "devise.url_helpers" do
17
19
  Devise.include_helpers(Devise::Controllers)
@@ -0,0 +1,162 @@
1
+ module Devise
2
+ module Test
3
+ # `Devise::Test::ControllerHelpers` provides a facility to test controllers
4
+ # in isolation when using `ActionController::TestCase` allowing you to
5
+ # quickly sign_in or sign_out a user. Do not use
6
+ # `Devise::Test::ControllerHelpers` in integration tests.
7
+ #
8
+ # Examples
9
+ #
10
+ # class PostsTest < ActionController::TestCase
11
+ # include Devise::Test::ControllerHelpers
12
+ #
13
+ # test 'authenticated users can GET index' do
14
+ # sign_in users(:bob)
15
+ #
16
+ # get :index
17
+ # assert_response :success
18
+ # end
19
+ # end
20
+ #
21
+ # Important: you should not test Warden specific behavior (like callbacks)
22
+ # using `Devise::Test::ControllerHelpers` since it is a stub of the actual
23
+ # behavior. Such callbacks should be tested in your integration suite instead.
24
+ module ControllerHelpers
25
+ extend ActiveSupport::Concern
26
+
27
+ included do
28
+ setup :setup_controller_for_warden, :warden
29
+ end
30
+
31
+ # Override process to consider warden.
32
+ def process(*)
33
+ _catch_warden { super }
34
+
35
+ @response
36
+ end
37
+
38
+ # We need to set up the environment variables and the response in the controller.
39
+ def setup_controller_for_warden #:nodoc:
40
+ @request.env['action_controller.instance'] = @controller
41
+ end
42
+
43
+ # Quick access to Warden::Proxy.
44
+ def warden #:nodoc:
45
+ @request.env['warden'] ||= begin
46
+ manager = Warden::Manager.new(nil) do |config|
47
+ config.merge! Devise.warden_config
48
+ end
49
+ Warden::Proxy.new(@request.env, manager)
50
+ end
51
+ end
52
+
53
+ # sign_in a given resource by storing its keys in the session.
54
+ # This method bypass any warden authentication callback.
55
+ #
56
+ # * +resource+ - The resource that should be authenticated
57
+ # * +scope+ - An optional +Symbol+ with the scope where the resource
58
+ # should be signed in with.
59
+ # Examples:
60
+ #
61
+ # sign_in users(:alice)
62
+ # sign_in users(:alice), scope: :admin
63
+ def sign_in(resource, deprecated = nil, scope: nil)
64
+ if deprecated.present?
65
+ scope = resource
66
+ resource = deprecated
67
+
68
+ ActiveSupport::Deprecation.warn <<-DEPRECATION
69
+ [Devise] sign_in(:#{scope}, resource) on controller tests is deprecated and will be removed from Devise.
70
+ Please use sign_in(resource, scope: :#{scope}) instead.
71
+ DEPRECATION
72
+ end
73
+
74
+ scope ||= Devise::Mapping.find_scope!(resource)
75
+
76
+ warden.instance_variable_get(:@users).delete(scope)
77
+ warden.session_serializer.store(resource, scope)
78
+ end
79
+
80
+ # Sign out a given resource or scope by calling logout on Warden.
81
+ # This method bypass any warden logout callback.
82
+ #
83
+ # Examples:
84
+ #
85
+ # sign_out :user # sign_out(scope)
86
+ # sign_out @user # sign_out(resource)
87
+ #
88
+ def sign_out(resource_or_scope)
89
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
90
+ @controller.instance_variable_set(:"@current_#{scope}", nil)
91
+ user = warden.instance_variable_get(:@users).delete(scope)
92
+ warden.session_serializer.delete(scope, user)
93
+ end
94
+
95
+ protected
96
+
97
+ # Catch warden continuations and handle like the middleware would.
98
+ # Returns nil when interrupted, otherwise the normal result of the block.
99
+ def _catch_warden(&block)
100
+ result = catch(:warden, &block)
101
+
102
+ env = @controller.request.env
103
+
104
+ result ||= {}
105
+
106
+ # Set the response. In production, the rack result is returned
107
+ # from Warden::Manager#call, which the following is modelled on.
108
+ case result
109
+ when Array
110
+ if result.first == 401 && intercept_401?(env) # does this happen during testing?
111
+ _process_unauthenticated(env)
112
+ else
113
+ result
114
+ end
115
+ when Hash
116
+ _process_unauthenticated(env, result)
117
+ else
118
+ result
119
+ end
120
+ end
121
+
122
+ def _process_unauthenticated(env, options = {})
123
+ options[:action] ||= :unauthenticated
124
+ proxy = request.env['warden']
125
+ result = options[:result] || proxy.result
126
+
127
+ ret = case result
128
+ when :redirect
129
+ body = proxy.message || "You are being redirected to #{proxy.headers['Location']}"
130
+ [proxy.status, proxy.headers, [body]]
131
+ when :custom
132
+ proxy.custom_response
133
+ else
134
+ request.env["PATH_INFO"] = "/#{options[:action]}"
135
+ request.env["warden.options"] = options
136
+ Warden::Manager._run_callbacks(:before_failure, env, options)
137
+
138
+ status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
139
+ @controller.response.headers.merge!(headers)
140
+ @controller.status = status
141
+ @controller.response.body = response.body
142
+ nil # causes process return @response
143
+ end
144
+
145
+ # ensure that the controller response is set up. In production, this is
146
+ # not necessary since warden returns the results to rack. However, at
147
+ # testing time, we want the response to be available to the testing
148
+ # framework to verify what would be returned to rack.
149
+ if ret.is_a?(Array)
150
+ status, headers, body = *ret
151
+ # ensure the controller response is set to our response.
152
+ @controller.response ||= @response
153
+ @response.status = status
154
+ @response.headers.merge!(headers)
155
+ @response.body = body
156
+ end
157
+
158
+ ret
159
+ end
160
+ end
161
+ end
162
+ end