开发者

Using declarative_authorization to limit results in the model

开发者 https://www.devze.com 2023-03-02 19:34 出处:网络
I am using the declarative authorization gem for permissions in a rails project and I am trying to limit output from the model based on user permissions.

I am using the declarative authorization gem for permissions in a rails project and I am trying to limit output from the model based on user permissions.

My abbreviated authorization file looks like this:

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

In my people model, I have a static method that I want to look like this

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

It looks like there is support for this using the AuthorizationInModel object in the documentation using with_permissions_to or permitted_to. I haven't been able to figure out how to use those functions based on the documentation or how to return a list of the current user's privileges on the current model.

Any ideas?


I found an alternative solution using the built in if-attribute method. I originally moved away from it because I was using non-namespaced models and namespaced controllers and views. This structure is an artifact form the original version of the project I am working on. Most of my work has been getting declarative authorization to deal with this structure.

The major piece of information that was not clear to me was how to name the permissions in a partially namespaced environment. The model expected the model name (:people), the controller expected the namespace and the model (:staff_people), and the views didn't care as long as you picked one. The solution I picked was to use the model name and explicitly set the context in every controller. If the context is not set in the controller, using filter_access_to does not work because it would be looking for the staff_people permission rather than the correct permission, people.

In the declarative authorization config file, I am giving full permissions to administration and partial permissions to supervisor. person.supervised returns an array of itself and all other supervised people.

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

To access this information in a Namespaced controller, I am using filer_resource_access.

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

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

I found that using

filter_access_to :all, :with_attribute => true

did not work for methods that need to use with_permissions_to and an if_attribute permission. I am not sure why this was a problem

It is still necessary to use filter_access_to for nonstandard controller actions that do not include an id fetching a single record as part of the arguments. For example, if an action called part_timers returns a list of people, this solution seems like it should work:

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

The correct solution is to keep the filter_resource_access as is and add a filter_access_to for that action

filter_resource_access :context => :people
fitler_access_to :part_timers, :required => :read, :context => people


There may be a better way to do this but this should work for your supervised_by method if everything else is setup right.

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
0

精彩评论

暂无评论...
验证码 换一张
取 消