Roman Kolpak
Roman Kolpak

Reputation: 2012

Best practices for website permissions system

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?

Upvotes: 5

Views: 4198

Answers (2)

MechEngineer
MechEngineer

Reputation: 1429

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).

Upvotes: 0

MrCode
MrCode

Reputation: 64526

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.

Upvotes: 3

Related Questions