13

我对 Rails 很陌生,并且对以下策略有疑问(使用Pundit):我想比较两个对象:@recordand @foo,如您在此处看到的:

class BarPolicy < ApplicationPolicy
  def show?
    @record.foo_id == @foo
  end
end

我没有找到将第二个参数传递给权威方法(@foo)的好方法。

我想做类似的事情:

class BarsController < ApplicationController
  def test
    authorize bar, @foo, :show? # Throws ArgumentError
    ...
  end
end

但是 Pundit 授权方法只允许两个参数。有没有办法解决这个问题?

谢谢!

4

3 回答 3

17

我在这里找到了答案。

这是我的方式:

在 中添加一个pundit_user函数ApplicationController

class ApplicationController < ActionController::Base
include Pundit
def pundit_user
    CurrentContext.new(current_user, foo)
end

创建CurrentContext类:

/lib/pundit/current_context.rb
class CurrentContext
  attr_reader :user, :foo

  def initialize(user, foo)
    @user = user
    @foo = foo
  end
end

更新初始化 Pundit 方法。

class ApplicationPolicy
  attr_reader :user, :record, :foo

  def initialize(context, record)
    @user = context.user
    @foo = context.foo
    @record = record
  end
end
于 2015-01-30T15:56:30.123 回答
1

依赖于当前用户和领域模型是一种代码味道,但如果确实需要,那么您可以使用具有任意数量参数的自定义查询方法,如果不满足要求则引发异常:

class BarPolicy < ApplicationPolicy
  def authorize_test?(foo)
    raise Pundit::NotAuthorizedError, "not authorized to test" unless record.foo_id == foo
  end
end

class BarsController < ApplicationController
  def test
    skip_authorization && BarPolicy.new(current_user, @record).authorize_test?(@foo)
    ...
  end
end

skip_authorization &&如果不使用,则不需要该部分after_action :verify_authorized,我只是想展示一个可以在这种情况下使用的单行代码,以摆脱未经授权的异常,同时仍然需要授权操作。

于 2020-05-13T03:59:13.223 回答
0

我不明白这个想法是什么,将额外的参数传递给 Pundit 是不好的编码。我的意思是,当然,这就像一个大案例陈述。如果您可以通过更好的设计来避免它,那么就这样做,但您通常会面临选择将授权逻辑飞溅到其他文件或将额外信息传递给 Pundit 的选择。

这是我编写的代码,让我可以使用我的 Pundit 类来检查是否允许用户对给定的列进行排序(resource_class 是我编写的另一种方法,它返回关联控制器中关联的 activerecord 类):

    def authorize_sort(column, record = resource_class)
        Pundit.policy!(user, record)
        unless policy.allow_sort?(column)
            raise NotAuthorizedError, "Not authorized to sort on column #{column} on record #{record}"
        end
    end

如果您不希望您的授权逻辑分布在更多类上并希望允许用户对其他用户看不到的字段进行排序,这确实是不可避免的。如果没有创建特殊的活动记录排序对象,这是不可避免的,因为它不是您要返回的任何单个对象的属性,而是它们排序所在的列。

于 2021-10-20T15:38:54.057 回答