使用declarative_authorization来限制模型中的结果

时间:2011-05-03 18:47:04

标签: ruby-on-rails declarative-authorization

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

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

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对象看起来有支持。我无法弄清楚如何根据文档使用这些功能,或者如何返回当前用户在当前模型上的权限列表。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

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

我不清楚的主要信息是如何在部分命名空间环境中命名权限。该模型期望模型名称(:people),控制器期望命名空间和模型(:staff_people),并且只要您选择了一个视图,视图就不会关心。我选择的解决方案是使用模型名称并在每个控制器中显式设置上下文。如果未在控制器中设置上下文,则使用filter_access_to不起作用,因为它将查找staff_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

要在Namespaced控制器中访问此信息,我使用的是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权限的方法。我不确定为什么这是一个问题

仍然需要将filter_access_to用于非标准控制器操作,这些操作不包含将单个记录作为参数的一部分获取的id。例如,如果名为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

答案 1 :(得分: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