Changed ACL documentation

This commit is contained in:
George Vinogradov 2011-10-25 02:07:59 +04:00
parent 2437f72f08
commit 517a0e6df1
1 changed files with 160 additions and 24 deletions

View File

@ -5,7 +5,14 @@
-------------- --------------
ACL предназначена для контроля прав пользователя на выполнение действий в ACL предназначена для контроля прав пользователя на выполнение действий в
системе доступа к моделям по областям видимости. системе и доступа к моделям по областям видимости.
Решаемые задачи
---------------
* Проверка наличия у пользователя прав для выполнения метода контроллера;
* Прозрачная фильтрация моделей для исключения невидимых для пользователя
записей.
Возможности Возможности
----------- -----------
@ -20,15 +27,55 @@ ACL предназначена для контроля прав пользова
* Объединение прав `acter`-ов на глубину одной модели (см. далее); * Объединение прав `acter`-ов на глубину одной модели (см. далее);
* Разграничение назначения ролей по классам (не завершено, на данный * Разграничение назначения ролей по классам (не завершено, на данный
момент не критично); момент не критично);
* Разграничение ролей на глобальные и локальные (см. далее); * Разграничение ролей на глобальные и локальные (см. далее).
Типы моделей Типы моделей, с которыми взаимодействует ACL
------------ --------------------------------------------
* __ActerModel__ -- модель, которая может выполнять действия, разрешенные
ролями, над другими моделями;
* __TargetTarget__ -- модель, над которой могут выполняться действия,
разрешенные ролями.
__ActerModel__ может иметь глобальную роль, которая определяет возможность
выполнения действий без привязки к конкретному экземпляру __TargetModel__ и
неограниченное количество прав по отношению к конкретному экземпляру
__TargetModel__.
__TODO__: *Реализовать дополнение необходимым функционалом моделей, выбранных
в качестве __ActerModel__ или __TargetModel__ при декларировании их роли в
системе*
Схема взаимодействия объектов ACL
---------------------------------
Функционал ACL реализуется путем взаимодействия моделей `Right, Role, Relation`,
реализующих основной функционал и особых моделей проекта, обозначенных на схеме
как `ActerModel` и `TargetModel`.
Экземпляры __ActerModel__ и __TargetModel__ связываются посредством модели
`Relation`, через которую экземпляр __ActerModel__ получает неограниченное
количество ролей по отношению к экземпляру __TargetModel__.
### Схема связей моделей:
--------------
| ActerModel |
/ --------------
--------- -------- |
| Right | | Role | V
--------- -------- ------------
... <= ... <= | Relation |
--------- -------- ------------
| Right | | Role | |
--------- -------- V
---------------
| TargetModel |
---------------
* Обозначения: <= -- Связь с несколькими моделями
<-,/,| -- Связь с одной моделью
* __Acter__ - модель, которая может выполнять действия, разрешенные ролями,
над другими моделями;
* __Target__ - модель, над которой могут выполняться действия, разрешенные
ролями;
Генератор прав Генератор прав
-------------- --------------
@ -50,12 +97,12 @@ ACL предназначена для контроля прав пользова
* Добавить к таблице моделей поле `visibility:text`; * Добавить к таблице моделей поле `visibility:text`;
* Добавить `attr_accessible :visibility` в модель; * Добавить `attr_accessible :visibility` в модель;
* Создать `scope :by_visibility`, принимающий аргументом массив областей * Создать `scope :by_visibility`, принимающий аргументом массив областей
видимости; видимости.
После выполнения этих действий на странице редактирования роли появится поле После выполнения этих действий на странице редактирования роли появится поле
выбора областей видимости для этой модели. выбора областей видимости для этой модели.
Пример: ### Пример:
model VisibilitiesExample < ActiveRecord::Base model VisibilitiesExample < ActiveRecord::Base
VISIBILITIES = ['open', 'hidden', 'open_for_admins'] VISIBILITIES = ['open', 'hidden', 'open_for_admins']
@ -64,6 +111,8 @@ ACL предназначена для контроля прав пользова
scope :by_visibility, lambda {|v| {:conditions => ['visibility in (?)', v]}} scope :by_visibility, lambda {|v| {:conditions => ['visibility in (?)', v]}}
end end
*Назначение методов описано в API*
Задание типа модели Задание типа модели
------------------- -------------------
*Этот функционал скорее всего будет изменяться* *Этот функционал скорее всего будет изменяться*
@ -82,7 +131,7 @@ ACL предназначена для контроля прав пользова
которой аргументом присвоить имя/имена связей с моделями, из которых должны которой аргументом присвоить имя/имена связей с моделями, из которых должны
браться роли. браться роли.
Примеры: ### Примеры:
* Модель, являющаяся __acter__: * Модель, являющаяся __acter__:
@ -121,6 +170,78 @@ ACL предназначена для контроля прав пользова
has_many :objects, :as => :target, :class_name => 'Relation' has_many :objects, :as => :target, :class_name => 'Relation'
end end
*Назначение методов описано в API*
Использование ACL в контроллере
-------------------------------
Если необходимо ограничить доступ ко всем методам контроллера по глобальной
роли пользователя вне зависимости от текущей модели, необходимо установить
`before_filter :check_global_rights`.
В случае, если у пользователя нет прав для выполнения текущего действия, он
будет переотправлен на предыдущую страницу.
Если необходимо проверить, может ли пользователь выполнить конкретное действие,
необходимо в начале этого метода вызвать метод `can_perform?`. Если методу
передан параметр, являющийся экземпляром класса __TargetModel__, метод возвратит
`true`, если одна или несколько ролей пользователя над этой моделью позволяет
ему выполнить может выполнить действие и `false` в противном случае. Если
необязательный параметр опущен, или в качестве параметра передано `:system`,
учитываются только глобальные роли.
### Примеры
* Контроллер, некоторые методы которого доступны для всех:
class StuffController < ApplicationController
def index # доступ у всех
...
end
def show # 'Что-то полезное' выполнится только у тех, чьи роли над
# @data позволяют выполнить конкретное действие.
@data = Stuff.find(params[:id])
if can_perform? @data
#что-то полезное
else
# сообщаем пользователю, что он не может выполнить действие
end
end
def create # 'Что-то полезное' выполнится только у тех, чьи
# глобальные роли позволяют выполнить метод
if can_perform?
# что-то полезное
else
# сообщаем пользователю, что он не может выполнить действие
end
end
end
* Контроллер, доступ к методам которого возможен только при наличии необходимых
прав в глобальных ролях:
class StuffController < ApplicationController
before_filter :check_global_rights # разрешаем доступ только тем,
# чьи роли это позволяют.
def index # доступ только у тех, кому это позволяет глобальная роль
...
end
def show # 'Что-то полезное' выполнится только у тех, чьи роли
# над @data это позволяют
@data = Stuff.find(params[:id])
if can_perform? @data
#что-то полезное
else
# сообщаем пользователю, что он не может выполнить действие
end
end
end
API для работы с ACL API для работы с ACL
-------------------- --------------------
*Этот функционал скорее всего будет изменяться* *Этот функционал скорее всего будет изменяться*
@ -130,23 +251,38 @@ API для работы с ACL
*  Методы классов: *  Методы классов:
- `relationable` -- устанавливает, кем является модель (acter/target) - `relationable` -- устанавливает, кем является модель (acter/target)
- `relationable?` -- может ли иметь связь с ролью/ролями с другими - `relationable?` -- может ли иметь связь с ролью/ролями с другими
- `relation_acters` -- список моделей, которые могут иметь роли по отношению к другим (след. метод) - `relation_acters` -- список моделей, которые могут иметь роли
- `relation_targets` -- список моделей, над которыми могут совершаться действия по отношению к другим (след. метод)
- `relation_acter? (model)`, `relation_target? (model)` -- является ли тем или другим - `relation_targets` -- список моделей, над которыми могут совершаться
  - `inherit_rights_from (:relation_name | [:relation_names])` -- права из каких связанных моделей наследовать действия
  - `visible_to (model)` -- все видимые для модели записи, может включаться в цепочку (например, для paginate) - `relation_acter? (model)`, `relation_target? (model)` -- является ли
тем или другим
  - `inherit_rights_from (:relation_name | [:relation_names])` -- права из
каких связанных моделей наследовать
  - `visible_to (model)` -- все видимые для модели записи, может
включаться в цепочку (например, для paginate)
* Методы инстансов: * Методы инстансов:
- `add_role_to(acter, role)` -- привязать acter-а с ролью к текущей записи - `add_role_to(acter, role)` -- привязать acter-а с ролью к текущей записи
- `add_role_on(target, role)` -- привязать текущую модель с ролью - `add_role_on(target, role)` -- привязать текущую модель с ролью
- `roles_to(object)` -- если object == :system, возвращает глобальные роли текущей записи, если передана запись -- то роли текущей модели над записью - `roles_to(object)` -- если object == :system, возвращает глобальные роли
- `rights_to(object)` -- аргументы те же, но возвращается список прав, собранный из всех ролей текущей записи, если передана запись -- то роли текущей модели над записью
- `right_to(controller_name, action)` -- возвращает запись с правом на выполнение действия action в контроллере c именем controller_name - `rights_to(object)` -- аргументы те же, но возвращается список прав,
- `can_perform? (controller_name, action, target = :system)` -- показывает, может ли текущая модель выполнить действие контроллера над целью собранный из всех ролей
- `right_to(controller_name, action)` -- возвращает запись с правом на
выполнение действия action в контроллере c именем `controller_name`
- `can_perform? (controller_name, action, target = :system)` -- показывает,
может ли текущая модель выполнить действие контроллера над целью
### Методы потомков `ActiveController::Base` ### Методы потомков `ActiveController::Base`
- `can_perform? (target = :system)` -- может ли current_user выполнить текущее действие *Возможно, будут вынесены в хелпер для универсализации системы*
- `check_global_rights` -- делает редирект назад, если пользователь вообще не может совершить текущее действие
- `roles_to(object)` -- возвращает список ролей current_user-а по отношению к объекту - `can_perform? (target = :system)` -- может ли `current_user` выполнить
- `rights_to(object)` -- возвращает список прав current_user-а по отношению к объекту текущее действие
- `check_global_rights` -- делает редирект назад, если пользователь вообще
не может совершить текущее действие
- `roles_to(object)` -- возвращает список ролей `current_user`-а по отношению
к объекту
- `rights_to(object)` -- возвращает список прав `current_user`-а по отношению
к объекту