Pull to refresh

Comments 20

Если бы я вдохновлялся вот этой реализацией, я бы получил:
— «непоследовательную» ACL в которой «система вернет вам последний измененный параметр»
— наследование ролей
Или я что-то не понял, или там роли и группы — это одно и то же
По сути одно и то же. Но я использовал два термина, чтобы подчеркнуть разницу в подходах.
Следующая тонкость — в моем описании есть небольшая подмена понятий. Группа (которая отражает принадлежность к иерархической структуре в реальном мире) и группа (роль) в системе разделения прав не всегда одно и тоже. Специально оставил, так как сам наступал на эти грабли (думаю, не я один). Нужно разделить понятия группа и роль. Тогда можно будет сделать соотношение между ролями и пользователями многие ко многим.
Да я про фреймворк для вдохновения. Для меня логично разделять роли и группы — функциональное и административное деление.
Лучше бы вы это здесь не оставляли. Идеи которые предлагает Zend_Acl:
— множественное наследование ролей. Это вообще «сказка» для хранения в базе (если нужно будет перейти от хранения в коде к хранению в базе.
— отсутствие принципов решения конфликтов
Вы правы, это идеи. Но ничего не мешает сделать свою реализацию под интерфейс Zend_Acl.
Мое решение «на бумаге». Если найдется желающий, то он может реализовать его под интерфейс Zend_Acl
Например в Yii
Основным понятием в RBAC Yii является элемент авторизации. Элемент авторизации — это права на выполнение какого-либо действия (создать новую запись в блоге, управление пользователями). В зависимости от структуры и цели, элементы авторизации могут быть разделены на операции, задачи и роли. Роль состоит из задач. Задача состоит из операций. Операция — разрешение на какое-либо действие (дальше не делится). К примеру, в системе может быть роль администратор, состоящая из задач управление записями и управление пользователями. Задача управление пользователями может состоять из операций создать пользователя, редактировать пользователя и удалить пользователя. Для достижения большей гибкости, роль в Yii может состоять из других ролей и операций. Задача может состоять из других задач. Операция — из других операций.

На деле является очень гибким решением, без лишних сложностей.
У меня нет опыта использования Yii (поправляйте, если что-то неправильно понял). Вот, что я понял из документации:
— нельзя назначить много ролей юзеру (вместо этого предлагают использовать наследование ролей)
— нет готового решения для задачи с атрибутами ресурсов
UFO just landed and posted this here
> на практике полезут вопросы производительности
Все вопросы производительности рассмотрены. Для этого как раз и не делается наследование групп и не даются права напрямую пользователям. Структура получилась «плоская», так что запросы будут простые и красивые и кеширование сделать тоже будет просто.
> и муторность конфигурирования
Не вижу такой проблемы. В коде ничего конфигурировать не надо, потому что CoC. Сбор данных автоматизирован максимально. Можно задавать изначальные значения с помощью DSL (эти файлы будут хранится в системе контроля версий и накатываться автоматически так же как фикстуры на базу).
> Есть еще вопрос аудита — например, хочется знать, юзер редактировал пост потому что ему прав хватило, или потому что он модератор.
Не очень понял проблему. Смотрим на пост и видим кто автор поста.
> А правило например «может редактировать свои посты в течение 30 минут».
can_edit_30(user, resource) return user.id == resource.user_id && (resource.created_at - now()) < 30; end
> Если не различать — логи забьются шлаком.
Поподробней пожалуйста.
> IMHO, оптимальнее всего отталкиваться от реальной задачи, максимально упрощая для нее логику ACL. На «классические» реализации вас ссылки уже дали, тут добавить нечего.
Я как раз все упрощал. А эти реализации все усложняют. Не очень понял почему это «классические», реализации. Я бы назвал классической реализацией, например, права в файловой системе *nix. Именно из этой системы была взята идея о том, что у юзера может быть много ролей (больше ничего подсмотреть не удалось).
UFO just landed and posted this here
Гостям вообще разрешить только смотреть

allow('guest', 'read', 'posts[not_only_for_moderators]')

Админам можно все
allow('admin', 'all', 'all')

Надо в некоторые разделы запретить постинг на первый месяц, некоторые сделать доступными только модераторам.

allow('members', 'read', 'posts[not_only_for_moderators,not_fitst_month]') allow('members', [read, 'post'], 'posts[not_only_for_moderators,fitst_month]')

Еще хочется на отдельные темы (!) назначать персональных модераторов.

allow('moderators', 'all', 'posts[where_moderator]') allow('moderators', ['read', 'post'], 'posts[only_for_moderators]')

Все просто если отделить бизнес логику от ACL. Назначение модератора в раздел это бизнес логика. Объясню на примере:
Пользователь является автором поста не потому, что он может редактировать пост, а потому что он написал этот пост и при создании поста система записала в базу текст поста и текущего пользователя как автора.
Эта информация может использоваться для разделения прав, а может и не использоваться. Может использоваться для получения списка всех постов данного пользователя.
Если на ситуацию смотреть под таким ракурсом, то любая задача решается. Была бы соответствующая бизнес логика, а навернуть сверху разделение прав всегда можно.

Вот если модератор — надо в лог записать, что модератор совершил действие.

Тут надо различать два действия: редактирование автором и редактирование модератором.
За ними стоит разная бизнес логика:
— при редактировании автором запись происходит только в таблицу с постами
— при редактировании модератором запись происходит в таблицу с постами и в таблицу с логами (в таблицу, если их потом надо просматривать конечному пользователю)

потому что универсальные, позволяют решить задачу в общем виде

Базовый интерфейс (а именно функция can) тоже может решить задачу в общем виде.
IMHO велоустройство через чур complexed. Btw, почему мы именуем DSL`ом то, что им не является? :)
IMHO велоустройство через чур complexed.

Да простое же как грабли. Разбито на модули. Даже может работать с флагом admin в таблице user (куда уж проще). Но если изначально использовать заложенные принципы и программные интерфейсы, то легко расширить до решения с редактированием.
Btw, почему мы именуем DSL`ом то, что им не является? :)

Термин DSL я использовал так же как его используют в ruby. Любое множество специфических функций там называют DSL. Например, функции для написания Gemfile.
И в результате получился Interbase/firebird с его системой ролей и прав. :)
С точки зрения концепции рекомендую посмотреть реализацию ACL баз данных в IBM Lotus/Domino. Эта модель работает уже не первый десяток лет и, насколько я знаю, не претерпела значительных изменений.
Если очень кратко, то есть сущности: User, Group, Role. User может входить (а может и не входить) в одну или несколько(!) Group.
Также, группа может содержать другие группы, даже вперемешку с User'ами.
Роль — это предопределенная совокупность разрешений/ограничений (прав). Одну или несколько ролей можно назначать User'у и/или группе.
При этом, назначив роль(и) пользователю или группе, мы можем дополнительно переопределить нужные нам права, которые будут иметь приоритет над правами, выдаваемые назначенной ролью.

Это кажется сложным, но когда вникаешь, понимаешь, что это очень гибкая и прозрачная схема.

Смысл в том, что вы проектируете приложение именно под _Роли_, а не группы. Например, роли «Админ», «Юзер RO», «Юзер RW», «Редактор», и тп. Это логика приложения, на нее не влияют внешние факторы, типа набора подразделений в организации. Т.е., например, появление «Бухгалтерии» в компании приведет к появлению группы «Бухгалтерия», но на приложении никак не отразится!
А в приложении вы связываете (в ACL) пользователей и группы с их ролями. Группе «Админов» будет назначены все роли или только роль «админ», если она покрывает все остальные.
У вас появился новый админ или ушел старый — вы всего-лишь меняете состав группы «Админы».
Появилось новое структурное подразделение — добавили группу «Новое подразделение» и назначили ему необходимые роли.
Удобно создать группу «уволенные сотрудники», которая будет во всех ваших ACL и у которой сняты все права.
Сотрудник уволен — легким движением руки у него отбираются все права.

Итого: приложение проектируется под роли (наборы прав). Роли статичны. Группам и пользователям назначаются роли. Группы динамичны — их состав меняется со временем.
Как-то так.

Спасибо за комментарий.
Часть предложенных принципов я поддерживаю:
— соотношение пользователей и ролей многие ко многим
— роли и организационные группы это не одно и тоже
От части идей я предпочёл отказаться, потому что, как мне кажется, это ненужное усложнение
— наследование ролей
— назначение прав напрямую пользователям. Это с точки зрения базы. А с точки зрения пользовательского интерфейса можно назначать права пользователю, а записывать их в его «персональную» группу. Но этот подход выходит за пределы моего базового решения. Просто предлагаю варианты.
Sign up to leave a comment.

Articles