Я нашел альтернативное решение, используя встроенный метод 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. Я не уверен, почему это было проблемой
По-прежнему необходимо использовать 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