L'accord de base est que nous avons un "kickstart" personnalisé pour nos projets. Pour cela, nous envisageons de refaire le contrôle utilisateur. Je sais qu'il y a beaucoup de questions sur le rbac général, mais je n'en trouve pas sur le rbac hiérarchique?
Nos exigences sont:
Donc, avec ces exigences à l'écart, voici comment je pense le faire.
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
Eh bien, en fait, c'est la moitié, la partie dont je suis sûr, la partie sur laquelle je suis coincé est les rôles hiérarchiques.
Alors, comment puis-je concevoir cela? Mon idée est que pour économiser sur les requêtes de base de données, je vais simplement créer la matrice des autorisations lors de la connexion et l'enregistrer dans la session afin que les requêtes ne soient pas trop simples car elles ne sont exécutées qu'une seule fois pour chaque connexion.
Le problème que je vois est que, je vais avoir besoin de connaître la hiérarchie des rôles afin de pouvoir résoudre les autorisations de rôles héritées avant de résoudre l'héritage.
Les autorisations utilisateur sont la partie facile, les autorisations par utilisateur sont essentiellement le groupe finalement résolu.
Il existe un moyen d'implémenter l'héritage de rôle en utilisant une relation récursive sur la table Roles
, en faisant référence au rôle à un autre enregistrement:
Cette relation ajoutera 1 : n
héritage dans Roles
enregistrement. Vous pouvez obtenir toute l'arborescence de la hiérarchie avec cette fonction stockée:
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
Ensuite, vous pouvez obtenir toutes les autorisations accordées avec quelque chose comme ceci:
SELECT
`permission_id`
FROM
`Permission_Role`
WHERE
FIND_IN_SET(`role_id`, `getHierarchy`({$role}))
AND
grant;
Si cela ne suffit pas, vous pouvez faire une autre table pour l'héritage:
Mais, dans ce cas, il fallait un autre algorithme d'obtention de hiérarchie.
Pour résoudre ( remplacement , vous devrez obtenir des autorisations de rôle et des autorisations d'utilisateur. Ensuite, écrivez user
autorisations sur roles
autorisations dans session
.
Je suggère également de supprimer les colonnes grant
dans Permission_Role
et Permission_User
. Il n'est pas nécessaire de mapper toutes les autorisations pour chacun d'eux. Juste assez pour utiliser les requêtes EXISTS
: s'il y a un enregistrement, alors l'autorisation est accordée, sinon - ce n'est pas le cas. Si vous devez récupérer toutes les autorisations et tous les statuts, vous pouvez utiliser LEFT JOIN
s.