【问题标题】:Active Admin, Devise and Pundit (Pundit::PolicyScopingNotPerformedError)活跃的管理员、设计和权威 (Pundit::PolicyScopingNotPerformedError)
【发布时间】:2016-01-07 20:35:10
【问题描述】:

我有一个现有的 Rails 应用程序,其中 DeviseUser 模型进行身份验证,Pundit 针对将 Enrollment 模型链接到我的 Company 模型的 Enrollment 模型进行身份验证。 UserCompany 都在公寓 gem 的公共模式中。我不怀疑公寓是问题的一部分,但我想我会提到它。

我使用 AdminUser 类添加了 Active Admin - 我想让我的管理员用户与应用程序用户分开。

如果我尝试访问 /admin/admin/dashboard,我会得到:

Pundit::PolicyScopingNotPerformedError at /admin/users
Pundit::PolicyScopingNotPerformedError

如果我尝试使用 /admin/users 之类的模型,Pundit 似乎会忽略 active_admin 策略并转到主要应用程序策略。在我的情况下,应用程序会引发异常,因为它需要 EnrollmentAdminUser

如果我禁用:

##/config/initializers/active_admin.rb
  config.authorization_adapter = ActiveAdmin::PunditAdapter

##/controllers/application_controller
  after_action :verify_authorized, except: [:landing, :dashboard], unless: :devise_controller?
  after_action :verify_policy_scoped, only: [:index]

一切正常,但我在主应用程序中丢失了 Pundit 等。

这是我的代码的要点:

https://gist.github.com/jasper502/4b2f1b8b6f21a26c64a5

以下是可以在此问题上找到的相关帖子:

https://gorails.com/forum/using-pundit-with-activeadmin

How to get Active Admin to work with Pundit after login

我希望在这篇文章 (Can you disable Pundit with Devise and Active Admin?) 中将 Pundit 全部禁用,但如果能做到这一点就好了。

更新

我有解决办法,但我仍然不知道这是否应该开箱即用,而且我有一些奇怪的问题导致了这一切。更新了要点。

我最终使用了:

https://viget.com/extend/8-insanely-useful-activeadmin-customizations

还有一点:

Documentation for conditional before_action/before_filter

以及下面的一些答案。我强行插入一个过滤器以强制 AA 对 AA 内部的资源和集合调用授权。接下来是添加策略范围,但现在我的大脑太痛了。

我还必须添加另一个过滤器来绕过仪表板上的身份验证,因为它是无头的。到目前为止似乎有效。

更新 2

嗯……我觉得我说得太早了。这一切只有在我以常规 User 身份登录时才有效 - 如果我退出,一切都会再次崩溃。

【问题讨论】:

    标签: ruby-on-rails devise activeadmin pundit


    【解决方案1】:

    @dan-tappin 我想您已经根据您的 cmets 找到了类似的解决方案,但这是我最终添加到每个 AA 模型注册中的内容:

    #app/admin/user.rb
    ActiveAdmin.register User do
      controller do
        before_filter :authorize_index, only: :index
        def authorize_index
          policy_scope(User)
        end
    
        before_filter :authorize_show_edit_destroy, only: [:show, :edit, :destroy]
        def authorize_show_edit_destroy
          authorize resource
        end
      end
    end
    

    基本上,这利用了使用普通 rails before_filter 语法在控制器范围内执行的能力,以限制使用 :only 的执行。然后因为 before_filter 发生在 inherrited_resources 过滤器之后,我们可以访问“资源”,我们可以像通常对任何模型实例一样授权它。见:https://github.com/activeadmin/activeadmin/issues/1108#issuecomment-14711733

    首先需要策略范围的原因是因为正常的权威安装需要 application_controller.rb 中的以下内容

    #app/controllers/application_controller.rb:
    class ApplicationController < ActionController::Base
      # Prevent CSRF attacks by raising an exception.
      # For APIs, you may want to use :null_session instead.
      include Pundit
      protect_from_forgery with: :exception
    
      #before_action :authenticate_is_admin!
    
      after_action :verify_authorized, except: [:index, :dashboard], unless: :devise_controller?
      after_action :verify_policy_scoped, only: :index, unless: :devise_controller?
    
      rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
    
      private
      def authenticate_admin!
        redirect_to new_user_session_path unless current_user.admin?
      end
    
      private
      def pundit_user
        current_user
      end
    
      private
      def user_not_authorized
        flash[:error] = "You are not authorized to perform this action."
        redirect_to(request.referrer || new_user_session_path)
      end
    end
    

    它期望对所有索引操作的模型的策略范围进行调用。仪表板控制器默认呈现索引操作,因此需要这个 before_filter hack。

    【讨论】:

    • 谢谢。您可以修改 ApplicationController,而不是 admin/{resource}.rb 中的第一个 before_filterafter_action :verify_policy_scoped, only: :index, unless: :devise_or_pundit_controller? ... def devise_or_pundit_controller? devise_controller? || self.class.name.match(/^Admin/) end
    • 好干净!
    【解决方案2】:

    您可以使用 skip_policy_scope 跳过 Active Admin 控制器中的范围吗?

    documentation

    如果您在控制器中使用 verify_authorized 但需要 有条件绕过验证,可以使用skip_authorization。为了 绕过verify_policy_scoped,使用skip_policy_scope

    【讨论】:

    • 我可能会这样做,除非那样会完全消除范围的能力,并且也不能解决我的策略没有被加载的问题。
    • 嗯...我似乎可以做到这一点的唯一方法是使用来自viget.com/extend/8-insanely-useful-activeadmin-customizations 的#1 现在我收到Pundit::AuthorizationNotPerformedError 错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多