我正在使用Trestle Admin,这是我的路线:
trestle_path /admin Trestle::Engine
当不是管理员的用户访问/admin
路由时,我希望CanCanCan能够处理它,就像它处理我的应用程序中的所有其他未授权请求一样。
尽管如此,问题是我无法弄清楚如何在我的ability.rb
中指定该能力,或者我无法弄清楚在何处添加authorize
语句。
当我在应用中访问/admin
时,日志如下所示:
Started GET "/admin" for ::1 at 2019-03-31 01:10:01 -0500
Processing by Trestle::DashboardController#index as HTML
Redirected to http://localhost:3000/admin/login
Filter chain halted as :require_authenticated_user rendered or redirected
Completed 302 Found in 13ms (ActiveRecord: 0.0ms)
所有发生的事情就是它重定向到/admin/login
,这是Trestle引擎处理它的方式。
但是我想让CanCanCan劫持并处理它,就像它通过我的application_controller.rb
中的规则处理整个应用程序中的所有其他未授权请求一样:
rescue_from CanCan::AccessDenied do |exception|
respond_to do |format|
format.json { head :forbidden, content_type: 'text/html' }
format.html { redirect_to main_app.root_url, alert: exception.message }
format.js { head :forbidden, content_type: 'text/html' }
end
end
但是,由于它不是我定义的模型或控制器,因此我不确定在ability.rb
中要指定什么。
我尝试了以下操作,但无济于事:
if user.has_role? :admin
can :manage, :all
else
cannot :read, :trestle
end
或:
if user.has_role? :admin
can :manage, :all
else
cannot :read, :admin
end
我可以做我想做的事吗?
答案 0 :(得分:1)
您可以使用具有路由限制的技巧:
class CanCanConstraint
def initialize(action, resource)
@resource, @action = resource, action
end
def matches?(request)
# this will differ depending on your auth solution, for devise/warden:
current_user = request.env['warden'].user
current_user && Ability.new(current_user).can?(@action, @resource) || false
end
end
mount Trestle::Engine, at: '/admin', constraints: CanCanConstraint.new(:edit, :trestle)
match "/admin/*glob", to: "some_controller_when#trestle_not_authorized"
这种方式/admin
仅在用户被授权并具有许可的情况下导致栈桥,否则第一条路线将不匹配,您可以按照自己喜欢的任何方式处理请求,例如使用全部第二条路线。
取决于安装支架的方式-您可能需要禁用其自动安装(在相应的初始化程序中为config.automount = false
)