我有一个现有的Rails应用程序,用于Devise
验证User
模型并Pundit
根据Enrollment
链接User
到我的Company
模型的模型进行身份验证.双方User
并Company
都在公寓宝石的公共架构.我不怀疑公寓是问题的一部分,但我想我会提到它.
我使用AdminUser类添加了Active Admin - 我希望将我的管理员用户与应用用户分开.
如果我尝试访问/admin
或/admin/dashboard
获得:
Pundit::PolicyScopingNotPerformedError at /admin/users Pundit::PolicyScopingNotPerformedError
如果我尝试像/admin/users
Pundit 这样的模型似乎忽略了active_admin策略并转到主应用程序策略.在我的情况下,应用程序会抛出异常,因为它是在等一个Enrollment
VS的AdminUser
.
如果我禁用:
##/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
如何让Active Admin在登录后与Pundit合作
我想在这篇文章中一起禁用Pundit(你可以用Devise和Active Admin禁用Pundit吗?)但是这样做会很好.
UPDATE
我已经解决了,但我仍然不知道这是否应该开箱即用,我有一些奇怪的问题导致所有这一切.要点已更新.
我最终使用:
https://viget.com/extend/8-insanely-useful-activeadmin-customizations
还有一点:
有条件的before_action/before_filter的文档
以下是一点答案.我在过滤器中使用过强制AA来强制AA对AA内的资源和集合进行授权.接下来是添加策略范围,但我的大脑现在伤得太厉害了.
我还必须添加另一个过滤器来绕过仪表板上的身份验证,因为它是无头的.到目前为止似乎工作.
更新2
嗯......我想我说的太快了.这一切都只有在我作为常规登录时才有效User
- 如果我退出,它会再次崩溃.
@ dan-tappin我想你已经根据你的评论找到了类似的解决方案,但这里是我最后添加到我的每个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语法在控制器范围内执行的能力,以便仅使用:来限制执行.然后因为before_filter发生在inherrited_resources过滤器之后,我们可以访问"资源",我们可以像对待任何模型实例一样对其进行授权.请参阅:https://github.com/activeadmin/activeadmin/issues/1108#issuecomment-14711733
首先需要策略范围的原因是因为普通的pundit安装需要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.