В классе Permission даны методы для переопределения "на лету" разрешений, которые имеет текущий пользователь, в отношении различных объектов сайта. Объектами могут выступать блоки, записи, страницы сайта, другие пользователи сайта, сам сайт и т.д.
Каждый тип объекта имеет собственный набор возможных разрешений. Например, в отношении записей пользователи могут иметь следующие разрешения: создание новых записей, редактирование и удаление записей.
Вы, в принципе, можете придумывать собственные типы объектов, и задавать им собственные разрешения — главное, чтобы названия этих типов не совпадали с зарезервированными. При этом, естесвенно, нужно иметь в виду, что ваши разрешения не будут влиять на работу служебных скриптов.
Ключи — это массив идентификаторов или один идентификатор. В качестве идентификаторов можно использовать строковые данные или целые числа (для штатных типов объектов используются только целые числа). Например, для объекта типа "page", ключом является номер страницы. А чтобы изменить разрешения на запись, нужны два ключа: кроме номера записи, нужно знать и номер блока, в котором находится эта запись.
Если ключ объекта является составным, то его нужно записывать в виде простого (не ассоциативного) массива. Идентификатор более высокого уровня по иерархии системы в массиве должен стоять левее. Например, для объекта типа "record", можно добавить разрешение на редактирование таким образом:
Permission::add('record', [$srcBlockId, $recId], 'edit');
Метод, добавляющий разрешения текущему пользователю.
Обратите внимание на то, что метод Permission:add является чисто виртуальным — он работает только во время вызова страницы. Для сохранения же прав на постоянной основе и получении информации обо всех правах пользуйтесь классом Proposition, методом Blox::info() и др.
Пример:
# Разрешить текущему пользователю редактировать запись 333 в блоке 22
Permission::add('record', [22, 333], ['edit'=>true]);
Это ассоциативный массив в формате: ['имяРазрешения'=>true, ...]
.
Каждый тип объекта имеет собственный набор возможных разрешений.
Полный список объектов разрешений приведен в таблице в конце.
Обычно в качестве значений элементов массива $permits используется true. Однако, если необходимо отменить разрешение, нужно явно задавать значение false .
Для массива $permits допустимы более компактные форматы:
['имяРазрешения', ...]
.
'имяРазрешения'
(если добавляется одно разрешение).
Можно установить одно и то же разрешение $permits для всех объектов. Для этого вместо указания конкретного ключа, нужно поставить пустой ключ/ключи. В качестве значений пустых ключей нужно брать пустую строку. Пустыми могут быть только младшие ключи или все ключи сразу. Ситуация, когда старший ключ пустой, а младший задан, недопустима.
Примеры:
# Текущий пользователь имеет право создавать новые записи в блоке 22.
Permission::add('record', [22, ''], 'create');
# Кстати, для разрешения create второй ключ вообще всегда должен быть пустым.
Всегда нужно указывать полный набор ключей (даже пустых) для данного типа объекта. Неполные наборы ключей в методе Permission::add() запрещены
В момент вызова метода Permission::add() не всегда бывают известны объекты (ключи объектов), которым нужно установить те или иные разрешения. Для этого нужны дополнительные данные, которые становятся известными только в момент вызова метода Permission::get().
В таких случаях вместо массива $permits нужно поставить определение разрешительной функции (callback).
Разрешительная функция должна быть определена как анонимная функция, и она должна возвращать массив разрешений. Формат возвращаемого массива, должен быть ассоциативный: ['имяРазрешения'=>true, ...], такой же как и у массива $permits в полной форме.
У разрешительной функции могут быть два параметра: $keys и $data. Они совпадают с одноименными параметрами метода Permission::get(). Задавать эти параметры в разрешительной функции необязательно — делайте это, если они нужны.
# Разрешить текущему пользователю редактировать записи
# блока 22, в которых значение поля 1 равно его ID.
$permits = function($keys, $data) {
if ($data['dat'][1] == Blox::info('user','id'))
return ['edit'=>true];
};
Permission::add('record', [22, ''], $permits);
При использовании разрешительной функции, младшие ключи часто бывают пустыми. Это ясно из назначения разрешительной функции — уточнять, каким объектам давать разрешения, а каким нет. Однако разрешительную функцию можно применять и для конкретного объекта с конкретными ключами.
Если не хватает входных данных для вычислений, например, было указано меньше ключей, чем надо, то желательно сделать так чтобы, функция возвращала строку 'undefined', а не null (то есть, ничего), как в предыдущем примере. Это будет означать, что какие-то разрешения все-таки могут быть, и система это учтет, когда данных окажется достаточно.
Permission::add(
'record',
[22, ''],
function($keys, $data) {
if (!isset($keys) && !isset($data['dat']))
return 'undefined';
. . .
};
);
Для отмены какого-либо разрешения необходимо задать разрешению значение false.
# Запретить редактировать все блоки сайта
Permission::add('record', ['', ''], ['edit'=>false]);
Если перед назначением разрешения вам важно знать о том, что разрешение не просто отсутствовало, а было отменено, то предварительно нужно производить проверку:
if (Permission::get('record', [11,''])['edit'] !== false) {
Permission::add('record', [11, ''], function(){...});
}
Вызывать метод Permission::get() внутри разрешительной функции для проверки разрешений запрещено — это приведет к бесконечному циклу.
Метод для извлечения разрешений.
['имяРазрешения1'=>true, 'имяРазрешения2'=>false, ...]
. Формат такой же, как у параметра $permits в полном формате.
В случае ошибки вместо массива возвращается false.
Чтобы узнать какое-либо разрешение на конкретный объект, все ключи должны быть заданы, например:
if (Permission::get('record', [22, 333])['edit'])
echo'Вам разрешено редактировать запись 333 в блоке 22';
Применять пустые ключи в методе Permission::get(), в отличие от метода Permission::add(), запрещено! Однако, ключи можно просто опустить, то есть, применять неполные наборы ключей. Если опустить младшие ключи, то будет выведен массив всех опущенных младших ключей и их разрешений :
if (Permission::get('record', [22]))
echo'Вы имеете какие-то разрешения, касающиеся записей в блоке 22';
Если разрешение не просто отсутствовало, а было отмено, то оно будет иметь значение false. Если вас не интересует факт явного удаления разрешения, то все разрешения со значением false можно разом удалить с помощью метода Arr::remove(). Заодно будут удалены и все пустые элементы: '', 0, '0', null.
$permissions = Arr::remove(
Permission::get('record', [22])
);
Если вас не интересуют разрешения, которые определить не удалось, то их можно удалить так:
$permissions = Arr::remove(
Permission::get('record', [22]),
'undefined'
);
Если вы хотите убрать из массива разрешений все отмены, неопределенные разрешения, и заодно все пустые элементы, которые могли появится по ошибке, делайте так:
$permissions = Arr::remove(
Permission::get('record', [22]),
['undefined', false, '', 0, '0', null]
);
Собственно прибегать к методу Permission::get() обычно не приходится — он вызывается в служебных скриптах для управления доступом к штатным типам объектов (record, block, page). Другое дело, если вы создаете собственные типы объектов — там оба метода: Permission::add() и Permission::get(), нужно использовать в связке.
Метод Permission::get() возвращает массив всех разрешений, как есть, без всякой интерпретации. Более строгим аналогом этого метода является метод Permission::ask().
Метод Permission::ask() — это более строгий аналог метода Permission::get(). Узнавать окончательные разрешения, как с конкретными ключами, так и с неполными набороми ключей, лучше с помощью именно данного метода.
[
'' => ['' => ['edit' => false]],
22 => ['' => ['edit' => true]]
]
Этот массив говорит о том, что был запрет редактировать все блоки сайта. Также где-то было дано разрешение редактировать все записи блока 22.
Придавать значение порядку следования элементов массива нельзя, так как сначала вычисляются разрешения, заданные с помощью разрешительных функций.
Если мы применим метод Permission::get() к блоку 22, то есть, Permission::get('record', 22), то получим массив:
['' => ['edit' => true]]
которое, казалось бы должно означать, что все записи блока 22 разрешено редактировать.
Однако в этом же случае метод Permission::ask('record', 22) вернет пустой массив.
На практике метод Permission::get используется для получения полной картины обо всех разрешениях и запретах, и для этой цели ключи вообще лучше не применять.
$type Тип объекта | $keys Ключи | $permits Разрешения | $data |
record (запись) | $srcBlockId, # Номер исходного блока
При назначении разрешения 'create' второй ключ ($recId) должен быть пустым. | 'edit', # Редактировать записи
| 'dat'=>$dat, # Данные записи
|
block (блок) | В работе ...$srcBlockId # Номер исходного блока
| ||
page (страница) | $pageId # Номер страницы
| 'see', # Видеть скрытую страницу даже если она скрыта
|