5
votes

Current project I am working on is a web application, that has to be delivered to multiple customers on their own servers. The website needs a permission control system, that will manage areas and features users can or can not use.
As for know, I'm designing a database-driven permissions system, with permissions stored in database. Every user has a role. The role defines the list permissions available. The schema looks like this:

users table
1. user_id
2. name
3. role_id

roles table
1. role_id
2. name

permissions table
1. permission_id
2. name

roles_permissions table:
1. role_id
2. permission_id

In the code I would fetch logged users role and permissions, and check if the user is able to perform action or see area like so:

if($user->hasPermission('Edit HR')) {
  // let user see the editing HR section
}

The hasPermission would check if user has a permission with a name 'Edit HR' and will return the needed result. The problem I see is the database table has to have the permission record with a name being exactly 'Edit HR', not 'Edit_hr' or 'HR Editing'. So I have to make sure the data for the permissions system is the same for every database the applications are using. Which kind of makes me think this is a flawed design and needs to be re-designed. Creating new sections and features would also require to update all the databases, which also makes me a sad panda.

So, basically, the question is: what is the best way to design the database driven permission system and keep the database integrity on multiple databases?

2
To clarify the design, I would call the tables role, resource, and permission. The permissions table would include the foreign keys to role_id and resource_id and if any entry exists then you know that role is connected to that resource. Also, I would call each PK id since you already have FK's named [table]_id.Xeoncross
Users can only have one role? How about someone who is editor for one category and reviewer for another? :)Ja͢ck
this is good the problem is when you have a mixing of role, proccess and you need explain if the user need add more permissions to one user or user group or exclude a permison from one user only, would you like get this scheme intead: stackoverflow.com/questions/37466333/…user6079755

2 Answers

3
votes

The scheme you've come up with looks fine. The only thing I would add to that is on the permissions table I would add a field called tag or similar.

The permission tag would be something like EDIT_HR, and you would use this as the reference in your code instead of its name. Use the name just for display purposes for example HR Editing. This way the name can vary as required, and it won't affect your code.

0
votes

The solution I'm using is to have a global $current_user object that reads the permissions table on creation and stores all permission actions that are valid for it. This array is then searched whenever you need to check an action. It saves on DB queries, although if there are security implications for storing this kind of data in a global object, I haven't found it.

There's only 1 db table required (sample):

user_id | user_role | user_action
---------------------------------
0       |   10      |   view_dashboard
0       |   1       |   view_users

User role corresponds to the minimum user type (Admin, editor, visitor, etc.) so all actions with a user_role >= $current_user role are available. The user_id column allows you to override certain levels for a specific user.

With this kind of setup, it's also easy to have a page that lists all permissions and allows a user to modify the value with a simple dropdown (but make sure not every user can do that).