1

I have a number of Rails engines in a Rails app, and each currently has its own constraint class to determine whether to allow the user

mount Flipper::UI.app(Flipper) => '/admin/flipper', :as => "feature_flags", constraints: CanAccessFeaturesUI

Since Current.user is set in the ApplicationController, it is not yet available in routes.rb. Is there any accepted way to make it available to the router, so that I can simply do something roughly like this:

  mount Flipper::UI.app(Flipper) => '/admin/flipper', :as => "feature_flags", constraints: -> do
    Current&.user&.superuser?
  end
2
  • 1
    Did you consider adding a custom middleware to your application which sets Current.user before Rails evaluates routes? Commented Aug 18, 2023 at 2:27
  • @spickermann: yes, that seems to be the best option!
    – iconoclast
    Commented Aug 18, 2023 at 15:38

1 Answer 1

4

Details will depend on what you're using for authentication. For devise, one way would be to just not use Current:

# config/routes.rb

constraints ->(req) { req.env["warden"].user&.superuser? } do
  # TODO: secret routes
end

But devise has this feature built in:

authenticate :user, ->(user) { user.superuser? } do
  # TODO: secret routes
end

https://www.rubydoc.info/gems/devise/4.9.2/ActionDispatch/Routing/Mapper#authenticate-instance_method


To use Current you need to set it in middleware. Because it runs right before routes:

$ bin/rails middleware
...
use Rack::ETag
use Rack::TempfileReaper
use Warden::Manager
# this is the place, after warden to use env["warden"]
#                   and before v
run Stackoverflow::Application.routes
# config/initializers/current_middleware.rb

class CurrentMiddleware
  def initialize app
    @app = app
  end

  def call env
    Current.user = env["warden"].user
    @app.call(env)
  end
end

Rails.application.config.middleware.insert_after Warden::Manager, CurrentMiddleware
constraints -> { Current.user&.superuser? } do
  # TODO: secret routes
end
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.