2

我正在使用声明性授权 gem 来获取 rails 项目中的权限,并且我正在尝试根据用户权限限制模型的输出。

我的缩写授权文件如下所示:

roles do
  role :supervisor
    has_permission_on :people, :to => :manage_all
  end

  role :basic_user
    has_permission_on :people, :to => :manage_subordinates
  end
end

privileges do
  privilege :manage_subordinates do
    includes :subordinate_records
  end

  privilege :manage_all do
    includes :all_records
  end
end

在我的人员模型中,我有一个静态方法,我希望看起来像这样

def self.supervised_by(user)
  if user.permitted_to? :all_records
    #return all of the records
  elsif user.permitted_to? :subordinate_records
    #return some of the records
  else
    #return none of the records
  end
end

使用 with_permissions_to 或 allowed_to 的文档中的 AuthorizationInModel 对象似乎对此提供了支持。我无法根据文档弄清楚如何使用这些功能,或者如何返回当前用户对当前模型的权限列表。

有任何想法吗?

4

2 回答 2

1

我找到了使用内置 if-attribute 方法的替代解决方案。我最初远离它是因为我使用的是非命名空间模型和命名空间控制器和视图。这个结构是我正在处理的项目的原始版本的一个工件。我的大部分工作都获得了处理这种结构的声明性授权。

我不清楚的主要信息是如何在部分命名空间的环境中命名权限。模型需要模型名称 (:people),控制器需要命名空间和模型 (:staff_people),只要您选择一个,视图就不会在意。我选择的解决方案是使用模型名称并在每个控制器中显式设置上下文。如果控制器中未设置上下文,则使用 filter_access_to 不起作用,因为它会寻找 staff_people 权限而不是正确的权限 people。

在声明性授权配置文件中,我将完全权限授予管理员,部分权限授予主管。person.supervised 返回其自身和所有其他受监督人员的数组。

roles do
  role :administrator
    has_permission_on :people, :to => [:create, :read, :update, :delete]
  end

  role :supervisor
    has_permission_on :people do
      to => [:create, :read, :update, :delete]
      if_attribute :id => is_in { Person.find_by_user_id(user.id).supervised }
    end
  end
end

为了在命名空间控制器中访问这些信息,我使用了 filer_resource_access。

module Staff
  class PeopleController < ApplicationController
    filter_resource_access :context => :people

    def index
      @people = People.with_permissions_to(:read)
    end

我发现使用

filter_access_to :all, :with_attribute => true

不适用于需要使用 with_permissions_to 和 if_attribute 权限的方法。我不知道为什么这是一个问题

对于不包含获取单个记录的 id 作为参数的一部分的非标准控制器操作,仍然需要使用 filter_access_to。例如,如果一个名为 part_timers 的操作返回一个人员列表,那么这个解决方案似乎应该可以工作:

filter_resource_access :context => :people, :additional_member => { :part_timers => :read }

正确的解决方案是保持 filter_resource_access 原样并为该操作添加 filter_access_to

filter_resource_access :context => :people
fitler_access_to :part_timers, :required => :read, :context => people
于 2011-05-05T21:24:11.103 回答
0

可能有更好的方法来做到这一点,但supervised_by如果其他一切设置正确,这应该适用于您的方法。

def self.supervised_by(user)
  if Person.new.permitted_to? :all_records, :user=>user
    #return all of the records
  elsif Person.new.permitted_to? :subordinate_records, :user=>user
    #return some of the records
  else
    #return none of the records
  end
end
于 2011-05-04T03:53:52.863 回答