Поддержка групп пользователей
В системе отсутствуют возможности создания Групп пользователей для разграничения полномочий. Это очень неудобно в работе, когда есть потребность в таком разграничении. При желании изменить полномочия на группу страниц (необязательно кластер) приходится все в ручную править. То же самое при появлении нового пользователя с некоторым набором полномочий.
Эту задачку можно очень просто решить.
Достаточно ввести в ACL еще один тип пользователя (в дополнение к * и $),
это ссылка на конкретную страницу. Она означает «Взять права доступа со страницы».
Примеры:
- Чтение: @Yuri Makarov – разрешить читать пользователям читающим Yuri Makarov.
- Редакт: @ACL/Редакторы – редактируют только из списка редакторов.
- Чтение: @Yuri Makarov / My Club / Members – чтение только членам моего клуба.
- Чтение: @Project 1 / Members – чтение только учасникам проекта Project 1.
- Чтение: !@Black List – запрет на чтение пользователям внесенным на страницу Black List.
Достоинства этого метода
- Простота реализации – подправить код только в месте проверки полномочий (сделать сборку полномочий рекурсивной, это наверное несколько строчек добавить). Все остальное – заведение/редактирование списков доступа (групп пользователей), описание списков доступа, ограничения доступа к ним и их редактированию – все это делается уже имеющимися стандартными средствами.
- Возможность создания произвольных групп доступа в любое время через веб-интерфейс.
- Возможность создания групп доступа любым пользователем системы (для своих нужд к примеру).
- Возможность маскировки групп доступа. Если не дать кому-то прав на чтение страницы с описанием группы доступа, то он может даже не подозревать о ее существовании.
- Возможность изменения прав пользователя сразу на большую группу страниц, скажем добавив или убрав пользователя из My Club / Members я разрешаю/запрещаю ему доступ ко все моим закрытым страницам.
- Возможность изменения поступа ко всем страницам кластера (и не только) из одного места, с сохранением возможности индивидуальной настройки доступа к отдельным страницам кластера. Для этого достаточно в поле доступа страницы (к примеру Кластер 1 / Стр 11) поставить ссылку на главную страницу кластера (Кластер 1) или на отдельную страницу с описанием группы доступа к кластеру (Кластер 1 / Members)
Тут еще много примеров придумать можно.
Этот метод управления полномочиями исключительно гибкий.
Реализация
В главном
wakka.php нужно поправить функцию HasAccess
<?
function HasAccess($privilege, $tag = "", $user = "", $tested = array()) // (Mak) добавлен параметр $tested
{
// see whether user is registered and logged in
if ($user!="guest@wacko")
{
if ($user = $this->GetUser()) $registered = true;
// set defaults
if (!$user = $this->GetUserName());
}
if (!$tag = trim($tag)) $tag = $this->GetPageTag();
if (in_array ($tag, $tested)) return false; // (Mak) Тест на зацикливание ссылок
// load acl
$acl = $this->LoadAcl($tag, $privilege);
$acl['list'] = $this->ReplaceAliases($acl['list']);
$this->_acl = $acl;
// if current user is owner, return true. owner can do anything!
if ($user!="guest@wacko") if ($this->UserIsOwner($tag)) return true;
// fine fine... now go through acl
foreach (explode("\n", $acl["list"]) as $line)
{
$line = trim($line);
// check for inversion character "!"
if (preg_match("/^[!](.*)$/", $line, $matches))
{
$negate = 1;
$line = $matches[1];
}
else
{
$negate = 0;
}
// if there's still anything left... lines with just a "!" don't count!
if ($line)
{
switch ($line[0])
{
// comments
case "#":
break;
// everyone
case "*":
return !$negate;
// only registered users
case "$":
case "§":
return ($registered) ? !$negate : false; // <- unregistered always False (Mak)
// (Mak) Приверка группы доступа
case "@":
$tested[] = $tag;
$groupe_access = $this->HasAccess($privilege, substr($line,1), $user, $tested);
return ($groupe_access) ? !$negate : $negate;
// aha! a user entry.
default:
if ($line == $user)
{
return !$negate;
}
}
}
}
// tough luck.
return false;
}
- В функцию добавлен еще один параметр $tested = array() для контроля зацикливания ссылок.
- При рекурсивном вызове HasAccess в этот параметр добавляется tag текущей проверяемой страницы.
- В начале функции проверяется наличие tag в уже протестированных страницах и если она там есть, возвращается False.
if (in_array ($tag, $tested)) return false;
- В цикле анализа элементов списка доступа добавлена обработка варианта @Page.
Особенности списков доступа
- Варианты * $ @ и их отрицания могут быть в списке доступа только в одном экземпляре и только в конце списка. Все что находится после них игнорируется.
- Возможно было бы полезно именть несколько @Page в одном списке доступа?
- В настоящее время отрицание не работает.
Тестирование
- Работа этой фичи была проверена только для варианта @Page
- Вариант !@Page не работает из-за бага в системе
- Вариант @Page/Subpage не работает из-за некорректной отработки (где-то в системе) слэша. Найти и исправить пока не смог. Возможно разработчики подскажут/поправят.