Основная задача заключается в том, что у нас есть собственный «кикстарт» для наших проектов. Для этого мы пересматриваем пользовательский элемент управления. Я знаю, что есть много вопросов об общем rbac, но я не могу найти ни одного иерархического rbac?
Наши требования:
Итак, с учетом этих требований, вот как я думаю об этом.
id | int | unique id
id | int | unique id --------------|--------------------------------------------- title | varchar | human readable name
id | int | unique id --------------|--------------------------------------------- module | varchar | module name --------------|--------------------------------------------- title | varchar | human readable name --------------|--------------------------------------------- key | varchar | key name used in functions
role_id | int | id from roles table --------------|--------------------------------------------- user_id | int | id from users table
id | int | unique id --------------|--------------------------------------------- permission_id | int | id from permissions table --------------|--------------------------------------------- role_id | int | id from roles table --------------|--------------------------------------------- grant | tinyint | 0 = deny, 1 = grant
id | int | unique id --------------|--------------------------------------------- permission_id | int | id from permissions table --------------|--------------------------------------------- user_id | int | id from users table --------------|--------------------------------------------- grant | tinyint | 0 = deny, 1 = grant
Ну, на самом деле это половина этого, эта часть, о которой я уверен, часть, которую я застрял, – это иерархические роли.
Итак, как мне это создать? Моя идея состоит в том, что для сохранения запросов к базе данных я просто собираюсь создать матрицу разрешений при входе в систему и сохранить ее на сеансе, чтобы запросы не были слишком простыми, поскольку они выполняются только один раз для каждого входа.
Проблема, которую я вижу, заключается в том, что мне нужно будет знать иерархию ролей, чтобы разрешить разрешения унаследованных ролей до того, как я разрешу наследование.
Разрешения пользователя – это легкая часть, разрешения для каждого пользователя – это, по сути, окончательно разрешенная группа.
Существует способ реализовать наследование роли с помощью рекурсивного отношения к Roles
таблицы, сделав ссылку на другую запись:
Это отношение добавит наследование 1 : n
в записи Roles
. Вы можете получить общее дерево иерархии с помощью этой хранимой функции:
CREATE FUNCTION `getHierarchy`(`aRole` BIGINT UNSIGNED) RETURNS VARCHAR(1024) NOT DETERMINISTIC READS SQL DATA BEGIN DECLARE `aResult` VARCHAR(1024) DEFAULT NULL; DECLARE `aParent` BIGINT UNSIGNED; SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aRole`); WHILE NOT `aParent` IS NULL DO SET `aResult` = CONCAT_WS(',', `aResult`, `aParent`); SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aParent`); END WHILE; RETURN IFNULL(`aResult`, ''); END
Затем вы можете получить все предоставленные разрешения с чем-то вроде этого:
SELECT `permission_id` FROM `Permission_Role` WHERE FIND_IN_SET(`role_id`, `getHierarchy`({$role})) AND grant;
Если этого недостаточно, тогда вы можете сделать другую таблицу для наследования:
Но в этом случае нужен еще один алгоритм получения иерархии.
Чтобы устранить проблему с переопределением, вам нужно будет получить разрешения на роль и разрешения пользователей. Затем укажите права доступа user
разрешениям на roles
в session
.
Кроме того, я предлагаю удалить столбцы grant
в Permission_Role
и Permission_User
. Нет необходимости отображать каждое разрешение для каждого из них. Достаточно просто использовать EXISTS
запросы: если есть запись, то разрешение предоставляется, иначе – это не так. Если вам нужно получить все разрешения и статусы, вы можете использовать LEFT JOIN
s.