I’m integrating Pundit into a project for authorization and its documentation suggests adding this to your project as a general fallback plan when authorization fails:
class ApplicationController < ActionController::Base
include Pundit::Authorization
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
private
def user_not_authorized
flash[:alert] = "You are not authorized to perform this action."
redirect_back(fallback_location: root_path)
end
end
This works great when you’re not dealing with Turbo Frames and Turbo Streams, but when inside of a Turbo Frame or using Turbo Streams I noticed that the flash message will never get shown. I’ve also tried using flash.now[:alert] and it results in the same outcome of the flash message not being shown.
Any thoughts on how to workaround this without having to disable Turbo for these actions? In my exact use case I’m operating inside of a nested frame (think tabbed navigation and inside of each tab there’s fully self contained frames). Disabling frames and streams isn’t an option here.
Ideally I wouldn’t want to break out of the frame, I’d like to stay on the page / frame and show a flash message “now” mentioning they can’t perform that action.
In a perfect world it would work something like this:
def user_not_authorized
respond_to do |format|
format.html do
flash[:alert] = "You are not authorized to perform this action."
redirect_back(fallback_location: root_path)
end
format.turbo_stream do
flash.now[:alert] = "You are not authorized to perform this action."
turbo_stream.prepend "flash", partial: "shared/flash"
end
end
end
With the above code, on authorization failure no alert message gets shown and the html format gets executed (I verified that by printing a message to the terminal in that block). This makes sense because Pundit doesn’t send the request as a turbo_stream so that format never gets a chance to execute.
I was hoping someone figured out a way to patch this until Pundit is modified to support it out of the box.