Basic deal is, we have a custom built "kickstart" for our projects. For this we are looking at redoing the user control. I know there are a lot of questions out there about general rbac, but I cannot find any on hierarchical rbac?
Our requirements are:
So, with those requirements out of the way, here's how I am thinking of doing it.
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
Well, actually that's half of it, that part I am sure about, the part I am getting stuck on is the hierarchical roles.
So, how do I design this? My idea is that to save on the database queries I am just going to build the permission matrix on login and save it to session so the queries don't have to be too simple as they are only run once for each login.
The issue I see is that, I am going to need to know the hierarchy of the roles so I can resolve the inherited roles permissions before I resolve the inheriting.
The user permissions is the easy part, the per-user permissions are essentially the finally resolved group.
5 Steps to Implement Role-Based Access ControlCreate a mapping of roles to resources from step 1 such that each function can access resources needed to complete their job. Create security groups that represent each role. Assign users to defined roles by adding them to the relevant role-based groups.
Hierarchical RBAC, as the name suggests, implements a hierarchy within the role structure. This hierarchy establishes the relationships between roles. Users with senior roles acquire permissions of all junior roles, which are assigned to their subordinates.
Technical – assigned to users that perform technical tasks. Administrative – access for users that perform administrative tasks.
According to the figure, these relationships exist between parts of the RBAC model: Privileges can be assigned to multiple Roles. A User can have multiple Roles. A Group can have multiple Roles.
There is a way to implement role inheritance by using recursive relation on table Roles
, by making role reference to another record:
This relation will add 1 : n
inheritance within Roles
record. You might obtain whole hierarchy tree with this stored function:
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
Then, you might obtain all granted permissions with something like this:
SELECT `permission_id` FROM `Permission_Role` WHERE FIND_IN_SET(`role_id`, `getHierarchy`({$role})) AND grant;
If it's not enough, then you might do another table for inheritance:
But, in this case, needed another hierarchy obtainment algorithm.
To resolve overriding issue you will have to get role permissions and user permissions. Then, write user
permissions over roles
permissions to session
.
Also, I suggest to remove grant
columns in Permission_Role
and Permission_User
. There is no need to map every permission for each of them. Just enough to use EXISTS
queries: if there is a record, then permission granted, else - it's not. If you need to retrieve all permissions and statuses, you might use LEFT JOIN
s.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With