Techioz Blog

Router.rb で Current.user を取得するための受け入れられた方法

概要

Rails アプリには多数の Rails エンジンがあり、現在、それぞれに独自の制約クラスがあり、ユーザーにアクセスを許可するかどうかを決定します。

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

Current.user は ApplicationController に設定されているため、routes.rb ではまだ使用できません。ルーターでそれを利用できるようにするための受け入れられた方法はありますか。大まかに次のようなことを行うことができます。

  mount Flipper::UI.app(Flipper) => '/admin/flipper', :as => "feature_flags", constraints: -> do
    Current&.user&.superuser?
  end

解決策

詳細は、認証に使用しているものによって異なります。工夫する場合、Current を使用しないのも 1 つの方法です。

# config/routes.rb

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

ただし、device には次の機能が組み込まれています。

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

https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://www.rubydoc.info/gems/devise/4.9.2/ActionDispatch/Routing/Mapper#authenticate-instance_method

Current を使用するには、ミドルウェアで設定する必要があります。ルートの直前に実行されるため、次のようになります。

$ 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