Построение ответов Rack Middleware с функциональностью Flash-сообщений
У меня есть приложение Sinatra, которое установлено в приложении Rails под /admin
, Приложение Sinatra - это панель администратора, поэтому оно должно быть доступно только авторизованным пользователям.
Для этого я создал часть промежуточного программного обеспечения Rack, которое будет запускаться до вызова приложения Sinatra.
Логика проста -
- Если пользователь аутентифицирован, продолжайте как обычно
- Если пользователь не прошел проверку подлинности, перенаправьте его в корневой каталог с сообщением о флеш-предупреждении (я использую гем -стойку, чтобы разрешить доступ к флеш-сообщениям в 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