I\'m developing an application for our company that eventually will have lots of ways of restricting users to particular sections/modules. While the application is still small,
What about storing permissions as a JSON object?
I think you should have fave tables:
user
user_x_profile
profile
profile_x_function
function
You set up various "generic" profiles "viewer", "employee", "manager" etc.
You set up a "function" entry for each object you want to control.
Then link the functions to the profiles in profile_x_function.
Then assign one or more profiles to each user.
This cuts the administration effort. Say you want to add another function that only "managers" can use -- you just add a new entry in the function table then add an entry in the "profile_x_function" table which links to the "manager" profile the permission to the manager profile and its available to all managers.
To query access you will need a five table join, but you are only selecting one permision attribute.
Like Ibrahim says, create a new table specifically for your permissions. Assign a numerical value to a user which represents their permission level, say 1 = read, 2= write/read, 3 = modify/write/read. Then in your code, check for proper permission level before allowing a user to perform a specific task. If they don't have the required value (3 to modify or >=2 to write) then you block that ability.
In a very famous MySQL performance book High Performance MySQL, the author specifically mentioned ACL as where data type like SET
could be used. They use following example to demonstrate such use cases:
CREATE TABLE acl (
permissions SET('CAN_READ', 'CAN_WRITE', 'CAN_DELETE') NOT NULL
);
INSERT INTO acl VALUES ('CAN_READ,CAN_WRITE');
SELECT permissions FROM acl WHERE find_in_set('CAN_READ', permissions);
The problem is that, mentioned in the book as well, you can't modify the permissions set easily (you have to use ALTER TABLE
), neither can you declare a column typed SET
as an index, which may causes performance issue.
You can also use something like TINYINT
to "wrap" the ACL list, the cons is that it's harder to read as well as to code SELECT
sentence.
I would do it this way.
table name: permission
columns: id, permission_name
and then I can assign multiple permissions to the user using a many to many relationship table
table name: user_permission
columns: permission_id, user_id
This design will allow me to add as many permission as I want, and assign it to as many user as i want.
While the above design go with your requirement, I have my own method of implementing ACL in my application. I am posting it here.
My method of implementation of ACL goes like this:
To do this I have come up with the following database design.
role
I store the role name here
+----------+
| Field |
+----------+
| id |
| roleName |
+----------+
permission:
I store the permission name and key here
Permission name is for displaying to user.
Permission key is for determining the permission.
+----------------+
| Field |
+----------------+
| id |
| permissionName |
| permissionKey |
+----------------+
role_permission
I assign permission to role here
+---------------+
| Field |
+---------------+
| id |
| role_id |
| permission_id |
+---------------+
user_role
I assign role to the user here
+---------------+
| Field |
+---------------+
| id |
| user_id |
| role_id |
+---------------+
user_permission
I store the manual permission I may allow for the user here
+---------------+
| Field |
+---------------+
| id |
| user_id |
| permission_id |
+---------------+
This gives me more control over the ACL. I can allow superadmins to assign permission by themselves, and so on. As I said this is just to give you the idea.