Построение ответов Rack Middleware с функциональностью Flash-сообщений

У меня есть приложение Sinatra, которое установлено в приложении Rails под /admin, Приложение Sinatra - это панель администратора, поэтому оно должно быть доступно только авторизованным пользователям.

Для этого я создал часть промежуточного программного обеспечения Rack, которое будет запускаться до вызова приложения Sinatra.

Логика проста -

  1. Если пользователь аутентифицирован, продолжайте как обычно
  2. Если пользователь не прошел проверку подлинности, перенаправьте его в корневой каталог с сообщением о флеш-предупреждении (я использую гем -стойку, чтобы разрешить доступ к флеш-сообщениям в Rack)

Код ниже. Я чувствую, что что-то упустил в redirect метод. Rack::Builder block создает приложение mini-Rack, а блок внутри создает еще одно приложение Rack (Proc), которое создает ответ перенаправления с флэш-сообщением.

Когда я запускаю его, я получаю undefined method 'detect' for nil:NilClassЭто означает, что ни один блок не возвращает действительныйnil ответ. Мне нужно бежать call где-нибудь на одном из этих блоков?

Я использую Puma Webserver, если это поможет.

Спасибо!

require "rack"
require "rack-flash"

class AdminAuthorizer
  def initialize(app)
    @app = app
  end

  def call(env)
    @env = env

    id = @env["rack.session"][:user_id]
    user = User.where(id: id).first

    # Check if user is authorized, otherwise redirect  
    user.admin? ? ok : redirect
  end

  private

  def ok
    @app.call(@env)
  end

  def redirect
    Rack::Builder.new do
      use Rack::Flash, sweep: true, accessorize: true

      run(
        Proc.new do |env|
          env["x-rack.flash"].alert = "Insufficient permissions"

          res = Rack::Response.new
          res.redirect("/")
          res.finish
        end
      )
    end
  end
end

1 ответ

Ладно, разобрался сам с любыми любопытными.

Я должен был использовать env ключ 'action_dispatch.request.flash_hash', который используется Flash Middelware здесь

Я не должен был использовать rack-flash драгоценный камень, хотя я уверен, что это все еще полезно при создании приложений Sinatra и тому подобное

ПРИМЕЧАНИЕ: это на Rails v4.2.4. Я считаю, что в этом было несколько изменений Flash модуль, так что я не знаю, изменился ли этот ключ. Но вы можете подтвердить поиск в последнем репо для аналогичного определения.

require "rack"


class AdminAuthorizer
  FLASH = ActionDispatch::Flash

  def initialize(app)
    @app = app
  end

  def call(env)
    @env = env

    id = @env["rack.session"][:user_id]
    user = User.where(id: id).first

    # Check if user is authorized, otherwise redirect
    user.admin? ? ok : redirect
  end

  private

  def ok
    @app.call(@env)
  end

  def redirect
    # Calls a Rack application (the defined Proc). If you want to do more steps
    # or get fancier, you can wrap this in a Rack::Builder call
    #
    # Rack::Builder.app(redirect_proc)
    #   use (blah)
    #   run (blah)
    # end.call(@env)
    #
    redirect_proc.call(@env)
  end

  def redirect_proc
    Proc.new do |env|
      # Use the key 'action_dispatch.request.flash_hash' to set
      # an new FlashHash object. This will overrite any existing FlashHash
      # object, so use it carefully. You can probably avoid that by checking
      # for an existing one and adding to it.
      env[FLASH::KEY] = FLASH::FlashHash.new(alert: "Insufficient permissions")

      # Construct the redirect response
      res = Rack::Response.new
      res.redirect("/")
      res.finish
    end
  end
end
Другие вопросы по тегам