-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Reconfigure warden when the middleware stack is rebuilt: #5769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- ### Problem Starting from Rails 7.2, in tests environment, it is possible that Rails will rebuild the middleware stack, which for consequence will create a new Warden middleware that will not be configured by Devise. ### Context Since this commit rails/rails@79fd5b45a27 upstream, when an application uses the `with_routing` helper to create a temporary route set and defines a route that maps to a controller requiring authentication, an error will be raised on request: "RuntimeError: No Failure App provided" The issue is due to a memoization on devise. ### Solution When the `Devise.warden_config` object is modified, reset the memoization.
@Edouard-chin, I tried your branch on my rails project, but I was still getting the test "should not allow portal users to access pipelines" do
Devise.configure_warden! # << added line
sign_in portal_users(:one)
get pipelines_url
assert_response :redirect
assert_redirected_to new_customer_session_path
end I also tried removing the I also tried replacing
UPDATE: adding pp @devise_finalized
pp Devise.class_variable_get(:@@warden_configured)
pp Devise.warden_config On the first call (outside of the test), I see: nil
true
{:default_scope=>:user,
:scope_defaults=>{},
:default_strategies=>{:customer=>[:magic_link_authenticatable], :employee=>[], :portal_user=>[:database_authenticatable, :two_factor_authenticatable]},
:intercept_401=>false,
:failure_app=>#<Devise::Delegator:0x0000755912314da0>} and on the second call (inside the test), I see: true
nil
{:default_scope=>:default, :scope_defaults=>{}, :default_strategies=>{}, :intercept_401=>true} I also tried removing both the |
Here's a combination of changes in rails and devise that got the test working without needing to change the test itself. Rails change diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 7ed155ab1a..5cec99dae3 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -69,7 +69,7 @@ def reset_routes(old_routes, old_integration_session)
app.instance_variable_set(:@routes, old_routes)
app.instance_variable_set(:@app, old_rack_app)
@integration_session = old_integration_session
- @routes = old_routes
+ @routes = old_routes.tap(&:finalize!)
end
end Devise change diff --git a/lib/devise.rb b/lib/devise.rb
index 86d5c395..f0ecc6e4 100644
--- a/lib/devise.rb
+++ b/lib/devise.rb
@@ -294,6 +294,7 @@ module Devise
# Private methods to interface with Warden.
mattr_reader :warden_config
+ mattr_reader :warden_configured
@@warden_config = nil
@@warden_config_blocks = []
def self.warden_config=(config)
diff --git a/lib/devise/rails/routes.rb b/lib/devise/rails/routes.rb
index f43e62fe..637d3774 100644
--- a/lib/devise/rails/routes.rb
+++ b/lib/devise/rails/routes.rb
@@ -7,8 +7,8 @@ module Devise
module RouteSet
def finalize!
result = super
- @devise_finalized ||= begin
- if Devise.router_name.nil? && defined?(@devise_finalized) && self != Rails.application.try(:routes)
+ Devise.warden_configured || begin
+ if Devise.router_name.nil? && Devise.warden_configured && self != Rails.application.try(:routes)
warn "[DEVISE] We have detected that you are using devise_for inside engine routes. " \
"In this case, you probably want to set Devise.router_name = MOUNT_POINT, where " \
"MOUNT_POINT is a symbol representing where this engine will be mounted at. For " \
@@ -18,7 +18,6 @@ module Devise
Devise.configure_warden!
Devise.regenerate_helpers!
- true
end
result
end |
Thanks, I didn't see that Rails' I'll try to figure out a solution. This issue happens when there are at least two tests, one using the |
I opened a fix in Rails rails/rails#54705, as I believe the |
Reconfigure warden when the middleware stack is rebuilt:
Problem
Starting from Rails 7.2, in tests environment, it is possible that Rails will rebuild the middleware stack, which for consequence will create a new Warden middleware that will not be configured by Devise.
Context
Since this commit rails/rails@79fd5b45a27 upstream, when an application uses the
with_routing
helper to create a temporary route set and defines a route that maps to a controller requiring authentication, an error will be raised on request: "RuntimeError: No Failure App provided"The issue is due to a memoization on devise.
Solution
When the
Devise.warden_config
object is modified, reset the memoization.