The problem
My application has multiple features. For example:
1) View resume.
2) Sending message to resume poster.
3) Viewing contact information on a resume.
My application has multiple users. For example:
1) Anonymous
2) Fred Lurker
3) Paul Generous
I want to allow some users to have access to one set of features and other users to have access to another set of features.
For example I want:
1) Anonymous users to have ability to view resume
2) Fred Lurker to be able to view resume and to send messages to resume poster.
3) Paul Generous to be able to see resume, send messages, and be able to see contact information on the resume.
Direct Permissions Mapping
The most direct approach would be to make every feature check a user who tries to access it. For example:
If (User is “Fred Lurker” or User is “Paul Generous”)That’s very direct and simple, but does not scale at all. My application has thousands of users, new users are added to the system, old users are deleted, and existing users are getting access more or less features over time. In order to deal with all that code would have to constantly change which is not feasible.
{
Allow user to send a message.
}
If (User is “Paul Generous”)
{
Allow user to view resume contact information.
}
Role-based Permissions
Better approach would be to introduce roles. For example:
1) “Recruiters” role that has access to “Sending message to resume poster” feature.
2) “PayingUsers” role that has access to “Viewing contact information on a resume” feature.
Then:
1) Add “Fred Lurker” user to “Recruiters” role.
2) Add “Paul Generous” user to “PayingUsers” role.
With such approach software developers would define what roles have access to what features. They would define it in code (e.g. in C#, C++ or Java).
Application administrator would define roles that users have access to.
When Paul Generous pays his membership fee, administrator would simply add Paul to “PayingUsers” role. Administrator does not need to explicitly define what features Paul would have access to, because it’s already defined by developers in application code for “PayingUsers” role.
To summarize:
1) Roles introduce one intermediate step in mapping users to features.
2) Developers map roles to features
3) Administrators map users to roles.
Enterprise Permissions
What if I want my application to be more flexible and allow administrator to map groups of users to features without asking developers to modify code?
That could be setup like this:
1) My enterprise system would still have Users.
2) I’d add Groups, so administrator would be able to add users to groups.
3) Developer would add Privileges, so administrator would be able to map groups to privileges.
4) Developer would code features in such a way that one feature would be mapped to one privileges in my code:
If (user.HasPrivilege(“ViewResume”))5) Administrator would create and delete Groups and map these groups.
{
ShowResume()
}
Enterprise Permissions system gives lots of flexibility to application administrators. It’s very appealing for IT department management to be able to tweak users’ permissions without need to wait for developers releasing new version of the app. That’s why such enterprise permissions systems are so popular.
Disadvantages of Enterprise Permissions
Unfortunately in real life flexible enterprise permissions system causes nothing but pain.
Here’s why:
1) With any flexibility comes added complexity.
Having “Users-Groups-Privileges-Features” chain instead of shorter “Users-Roles-Features” chain – significantly complicates the number of possible combinations of how permissions to access features can be granted to end users.
That means permissions could be granted to a user in several different ways through multiple groups. So it’s hard to revoke user’s permissions if necessary simply because it’s hard to figure out what permissions does the user really have.
2) It’s very hard for administrators to grasp what group should map to what privileges.
Administrator focuses on the end user. Administrator knows what groups user should belong to. But administrators have only vague idea about what privilege allows user to do in the application.
End result: developer is setting up the permissions anyway.
3) Enterprise permissions are much harder for developers.
Developers know what features should be available to what role (see Role-based Permissions above). Developers can map features to roles in their code.
Can developers map features to privileges and then map privileges to groups?
Yes, they can. But it’s harder. It’s more work. It requires both coding in C#/Java and scripting in SQL. Or even worse approach – mapping groups to privileges in the UI (error-prone deployment nightmare).
Administrators can setup new groups that developers do not know about. Administrators can delete groups that developers originally created. All that can quickly bring system to its knees. That’s why in the end administrators are afraid to create and delete groups and that defeats original purpose of enterprise system to give more flexibility to application administrators.
4) It’s hard to trace changes in Enterprise Permissions.
In role based system roles-features mapping is coded in C#/Java and is stored under source control. Code changes history helps to find out when and why this role was mapped to that feature.
Not so with mapping between groups and privileges. Such mapping is stored in database and is wiped out without trace every time when administrator changes the mapping.
There are no comments on why groups-features mapping was done the way it was done. There is simply no place to put such comment (unlike roles-features mapping that can be commented in C#/Java code).
Conclusion
The most robust way of handing permissions in most of applications is with role-based permissions (Users-Roles-Features).
In spite of “flexibility” appeal of enterprise-based permissions (Users-Groups-Privileges-Features), such system has serious disadvantages and virtually no real advantages.