【问题标题】:How do I specify an ability for a route created by a Rails engine?如何为 Rails 引擎创建的路线指定能力?
【发布时间】:2019-03-31 06:23:48
【问题描述】:

我正在使用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

我可以做我想做的事吗?

【问题讨论】:

    标签: ruby-on-rails cancancan ruby-on-rails-5.2 trestle-admin


    【解决方案1】:

    您可以使用带有路由约束的 hack:

    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 在相应的初始化程序中)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多