Содержание
Управление правами доступа
InstantCMS 2 позволяет автоматизировать настройку прав доступа для различных групп пользователей. В админке компонента может быть добавлен специальный экшен, позволяющий определить права. Затем во фронтенде и шаблонах эти права могут быть проверены.
Правила доступа
Правилами доступа называются условия, определяющие возможность зарегистрированного пользователя выполнить какое-либо действие.
Например, так выглядит список правил и форма их настройки в админке компонента «Комментарии»:
Все правила можно разделить на три типа:
flag | Правило, имеющее два состояния – включено и выключено. В интерфейсе отображается как чекбокс |
list | Правило, имеющее несколько предустановленных значений для выбора. В интерфейсе отображается как выпадающий список |
number | Правило, представленное в виде числа. В интерфейсе отображается как текстовое поле |
Например, вы пишете компонент «Гостевая книга» и хотите сделать настройку прав на три типа действий: добавление записей, редактирование записей и ограничение по репутации, необходимой для добавления записи. Тогда вы можете предусмотреть три правила доступа:
Правило | Название | Подходящий тип | Возможные значения |
---|---|---|---|
Добавление записи | add_message | flag | да или нет |
Редактирование записей | edit_message | list | own (только свои), all (все записи) |
Мин.репутация для добавления | karma_limit | number | Число баллов репутации пользователя, необходимое для возможности добавить запись |
Названия правил могут быть любыми, но должны состоять только из латинских букв, цифр и знаков подчеркивания. Названия возможных значений для правил типа list тоже могут быть любыми и формируется по тому же принципу.
Субъекты правил
Один компонент может работать с несколькими сущностями данных. Например, если мы пишем биржу труда, то в ней могут быть два типа сущностей – резюме и вакансии. При этом, допустим, мы хотим иметь возможность отдельно разрешать или запрещать добавление как резюме, так и вакансий.
В этом случае не нужно создавать два отдельных правила («добавление резюме», «добавлений вакансий»). Достаточно создать одно правило (просто «добавление»), а при настройке указывать о каком субъекте (резюме или вакансия) идет речь в данный момент.
То есть, одно правило для одного пользователя может иметь несколько разных значений, в зависимости от текущего субъекта. Выбор текущего субъекта производится при настройке правила и при проверке его значений (когда нужно ограничить доступ).
Ниже будут даны дополнительные подробности.
Создание правил доступа
Перед тем как приступать к созданию формы настроек правил доступа необходимо создать сами правила, добавив их в базу данных и в языковой файл компонента.
База данных
В базе данных правила хранятся в общей таблице perms_rules. Для каждого правила добавляется собственная запись, со следующими полями:
Поле | Описание | Пример |
---|---|---|
controller | Название компонента, который использует данное правило | comments |
name | Название правила | add |
type | Тип правила | flag |
options | Список возможных значений, через запятую. Только для правил с типом list | own,all,any |
Значения каждого правила для каждой группы пользователей хранятся в таблице perms_users. Добавлять вручную в эту таблицу ничего не нужно (кроме случаев, когда вы точно знаете что делаете). Вместо этого, добавлением данных записей будет заниматься специальный экшен настройки, о котором будет рассказано ниже.
Языковой файл
В языковом файле компонента необходимо добавить заголовки для каждого правила. Для правил с типом list также необходимо добавить заголовок каждой опции (кроме own и all).
Имя константы заголовка правила формируется по схеме: LANG_RULE_{КОМПОНЕНТ}_{ПРАВИЛО}. Например, для правила add компонента comments:
define('LANG_RULE_COMMENTS_ADD', 'Добавление комментариев');
Если вам нужно указать пояснение к правилу, то вы можете определить константу по схеме LANG_RULE_{КОМПОНЕНТ}_{ПРАВИЛО}_HINT, например (утрируя, т.к. в данном случае пояснение лишнее) для правила add компонента comments:
define('LANG_RULE_COMMENTS_ADD_HINT', 'Если включено, пользователи смогут добавлять комментарии');
Пояснение будет отображаться под названием правила в списке.
Для опций имена констант формируются по схеме: LANG_PERM_OPTION_{ОПЦИЯ}. Например, если у вас есть правило с типом list и среди его возможных значений есть опция any, то константа будет выглядеть так:
define('LANG_PERM_OPTION_ANY', 'Любой');
В системе есть 2 заранее заданные константы для опций own и all:
define('LANG_PERM_OPTION_OWN', 'Только свои'); define('LANG_PERM_OPTION_ALL', 'Все');
То есть для этих двух опций языковые константы добавлять не нужно.
Настройка правил доступа
После того как правила добавлены в базу, можно приступить к созданию экшена для их настройки в админке компонента.
Этот экшен заранее определен в классе cmsBackend, аналогично экшену для настройки опций. Вам нужно лишь включить его и создать шаблон.
Экшен выводит список правил доступа для данного компонента (см. скриншот в начале статьи) и обрабатывает сохранение их значений в базе.
Включение экшена
Для того, чтобы контроллер админки (backend.php) знал, что вы хотите использовать стандартный экшен для настройки правил доступа, необходимо добавить в описание класса строчку:
public $useDefaultPermissionsAction = true;
После этого экшен станет доступен по URL: /admin/controllers/edit/{компонент}/perms/{субъект}.
В качестве названия субъекта можно использовать любое сочетание латинских букв и цифр. Если компонент работает только с одним типом данных (например, компонент comments управляет только комментариями), то в качестве субъекта можно использовать название самого компонента:
/admin/controllers/edit/comments/perms/comments
Если субъектов должно быть несколько (например, для компонента «Биржа труда» это могут быть резюме и вакансии), то экшен можно разделить на два отдельных:
/admin/controllers/edit/birzha_truda/perms/vakansii /admin/controllers/edit/birzha_truda/perms/rezume
Физически оба этих URL будут обрабатываться одним экшеном, но, например, ссылок в меню (об этом ниже) может быть уже несколько.
Шаблон экшена опций
Для InstantCMS выше 2.4.0
Для версий InstantCMS выше 2.4.0 прямой необходимости в создании шаблона нет. По умолчанию будет использоваться файл /templates/default/controllers/admin/backend/controllers_perms.tpl.php.
Обратите внимание, если необходимо показать ссылку на документацию, создайте в языковом файле контроллера константу LANG_HELP_URL_COM_ИМЯ-КОНТРОЛЛЕРА, где напишите URL справочной информации. В этом случае на странице правил доступа появится ссылка на нее.
Для InstantCMS 2.4.0 и ниже
До версии 2.4.0 включительно, шаблон необходимо создавать в обязательном порядке.
Свой шаблон вывода правил доступа
Создайте файл /templates/default/controllers/{компонент}/backend/perms.tpl.php со следующим содержимым:
<?php $this->addBreadcrumb(LANG_PERMISSIONS); $submit_url = $this->href_to('perms_save', $subject ? $subject : false); echo $this->renderPermissionsGrid($rules, $groups, $values, $submit_url);
Вы можете модифицировать этот шаблон под собственные нужды.
Добавление экшена в меню
Если кроме настройки правил доступа в админке вашего компонента будут и другие разделы, то имеет смысл создать меню админки.
Для этого в контроллере админки (backend.php) добавьте метод getBackendMenu():
public function getBackendMenu(){ return array( // ссылка на экшен "Доступ" // третий параметр в href_to - название субъекта // если компонент имеет только один субъект, то передаем // название самого компонента ($this->name) array( 'title' => LANG_PERMISSIONS, 'url' => href_to($this->root_url, 'perms', $this->name) ), // ... здесь добавьте ссылки на другие разделы админки ... ); }
Переадресация на экшен
При переходе к настройкам компонента, админка по-умолчанию отправляет пользователя на экшен index вашего контроллера админки. Поэтому, если в вашей админке такой экшен не нужен, то вы можете из него делать автоматический редирект на другой экшен.
Пример переадресации из экшена index на экшен perms (в компоненте comments):
class backendComments extends cmsBackend{ public $useDefaultPermissionsAction = true; public function actionIndex(){ // переадресация на экшен perms для субъекта comments $this->redirectToAction('perms', 'comments'); } }
Проверка прав доступа
В любом месте компонента (в контроллерах, экшенах, шаблонах и модели) можно проверить значение правила доступа для текущего пользователя. Описанные ниже методы работают одинаково во всех местах.
Проверка производится с помощью статических методов класса cmsUser, отвечающего за информацию о текущем пользователе.
Проверка flag и list
Правила типов flag и list проверяются с помощью метода isAllowed($subject, $permission[, $value]), где:
$subject | Название субъекта для правила (или название самого компонента, если субъект у него один) |
$permission | Название правила доступа |
$value | Значение, с которым происходит сравнение. По-умолчанию – true |
Метод возвращает результат сравнения (true/false) значения $value со значением, заданным в админке для данного правила и группы текущего пользователя.
Например, так компонент comments проверяет что пользователь имеет право добавлять комментарии:
if ( cmsUser::isAllowed('comments', 'add') ) { ... }
А так, что пользователь может удалять любые комментарии (не только свои):
if ( cmsUser::isAllowed('comments', 'delete', 'all') ) { ... }
Во втором случае правило delete имеет тип list, и среди его возможных значений есть опция all, с которой и происходит сравнение.
Проверка number
Для проверки числовых правил есть два метода, использующих те же самые входящие параметры, что и описанный выше:
isPermittedLimitReached | Проверяет, что указанное в правиле значение достигнуто, т.е. значение $value больше или равно указанному в настройках правила |
isPermittedLimitHigher | Проверяет, что указанное в правиле значение больше, т.е. значение $value меньше указанного в настройках правила |
Первый метод удобно использовать когда речь идет об ограничениях, которые пользователь должен превзойти, например ограничение на минимальный рейтинг:
if ( cmsUser::isPermittedLimitReached('comments', 'min_rating', $user->rating) ) { ... }
Второй метод пригодится для проверки ограничений, которые вероятно еще не наступили, например максимального числа добавленных записей за день:
if ( cmsUser::isPermittedLimitHigher('blog', 'max_posts', $user_posted_today) ) { ... }