【问题标题】:ActiveAdmin checking create authorizationActiveAdmin 检查创建授权
【发布时间】:2017-12-13 15:37:54
【问题描述】:

在我看来,ActiveAdmin 应该主要在两种情况下检查创建授权:

  • UI 需要显示“创建新工单”按钮:在这里,检查 current_user 是否有创建通用工单的权限很有用。

    Cancancan 语法如下所示:

    user.can?(:create, Ticket)
    
  • ActiveAdmin 需要了解资源是否可以在表单提交后实际存储在数据库中:在这里检查当前用户是否可以使用表单“键入”的值存储该票很有用。

    Cancancan 语法如下所示:

     user.can?(:create, Ticket.new({author_id: user.id, some: "x", other: "y", values: "z"}))
    

就是这样!那么为什么 ActiveAdmin 会在为用户显示生成的“创建表单”之前检查以下权限?

user.can?(:create, Ticket.new({author_id: nil, some: nil, other: nil, values: nil}))

如果当前用户只有在author_id = own_user_id 处创建票证的权限怎么办?

在看到表单之前授权就会失败。

【问题讨论】:

    标签: ruby-on-rails activeadmin cancancan


    【解决方案1】:

    我无法解释为什么 ActiveAdmin 是这样编写的,但我可以向您展示我是如何解决类似问题的。

    首先,您需要授予用户ability 以在所有条件下创建所需的记录:

    # app/models/ability.rb
    ...
      can :create, Ticket
    ...
    

    这将获取您过去 ActiveAdmin 的 can? 检查并允许用户查看表单。但我们需要确保author_id 属于当前用户。为此,您可以在保存之前使用before_create 回调设置正确的author_id

    # app/admin/ticket.rb
    ActiveAdmin.register Ticket do
    ...
      before_create do |ticket|
        ticket.author_id = own_user_id
      end
    ...
    end
    

    以上假设您有一个辅助方法或名为own_user_id 的变量可用于ActiveAdmin 模块并返回正确的用户ID。如果您使用的是Devise,则可以将current_user.id 替换为own_user_id

    我承认,这不是最干净的解决方案,但它确实有效。我在自己的项目中实现了类似的东西。

    【讨论】:

    • 那是能力定义。我的意思是使用“can”方法是检查用户是否可以/不能做某事的助手。
    • 这可行,但我更愿意将我的授权规则与应用程序的其余部分分开。当然,这适用于这个 Ticket 示例。但我对所有模型都有授权条件。
    • 我同意。您始终可以为 ActiveAdmin 创建一个单独的(可能是继承的)能力类。可以肯定的是,这不是一个理想的解决方案。
    【解决方案2】:

    我确实如下重写了数据访问类,以使其正常工作。

    我是:

    • 禁用我认为在错误的时间完成的授权
    • 在保存资源之前在授权之前强制验证

      ActiveAdmin::ResourceController::DataAccess.module_eval do
        def build_resource
          get_resource_ivar || begin
            resource = build_new_resource
              resource = apply_decorations(resource)
            run_build_callbacks resource
      
            # this authorization check is the one we don't need anymore
            # authorize_resource! resource
      
            set_resource_ivar resource
          end
        end
      end
      
      ActiveAdmin::ResourceController::DataAccess.module_eval do
        def save_resource(object)
          run_save_callbacks object do
            return false unless object.validate # added it
            authorize_resource! resource        # added it
            object.save(validate: false)        # disabled validation since i do it 2 lines up
          end
        end
      end
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-24
      • 1970-01-01
      • 2016-12-08
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多