I am writing an enterprise web-forms-frontend application for in-house use. It has Direct access control (DAC) masquerading as Role-based access control (RBAC).
For anonymization purposes, let's call the main unit of information stored in my application a Document, and the roles in the company a Boss, a Grunt and a C-level executive. There are also Externals (e.g. somebody working for a business partner of ours). The general guideline is that everybody but externals should be able to read all documents, C-level execs can write everything, Bosses can write the Documents belonging to their own department, and Grunts can only write Documents personally assigned to them. Fairly standard thus far.
But what users actually want is that they can make arbitrary exceptions to the above. They want that any person in the system can be granted write access to any Document, and that Externals can be granted Read access to any document. (Actually, it is more complicated than that, with more roles and finer granularity of permissions, including management of who can propagate which permission to others, but the above description illustrates the core of the problem well enough). So what I have is basically permissions on a personal level, and the roles are only a convenient way of having default settings for the personal-level permissions when a user or a Document is added to the system, instead of having somebody fill out a whole row or column in an access control matrix by hand.
Now I have already designed a Permissions table in my database, which has a User FK, Document FK and columns for the different types of permissions. What I am not sure is what I should save in the table.
- Alternative 1: I save all permissions in this table (pure DAC) and have the logic tier mimic a RBAC. E.g. when a new Boss is added, a row for each Document in the system is added to the DB, with Read permissions for all documents and Write for the Documents of her department.
- Alternative 2: I save the deviations from the role guidelines only. So when a new Boss is added, nothing is written to the permissions table. But when an executive gives a Boss the rights to write to a Document from a different department, then a single row is added to reflect that information.
I am not sure which alternative would be better. The first one feels closer to textbook implementation, and if a principle has made it into a textbook, then there is normally good reason to use it. But in my case, it also hurts the DRY principle - after all, if the information that a C-level exec can write to Document X is derivable from his role, writing a row with this information in the DB is redundant.
What are the advantages and disadvantages of each approach in terms of a) application performance and b) complexity of implementation? What headaches can I expect from each?
Keep in mind that 1) I don't plan to implement a full logic tier. The whole application is practically a convenient CRUD frontend to a database, so I will be doing DB queries for each page view instead of keeping a collection of Document objects in memory. (I know the advantages of a MVC pattern, but it was decided that it will be overkill for this project). 2) I am programming this in ASP .NET 4.5, so the closer I stay to roles, the more I can let the framework do the heavy lifting for me. 3) I have thought of implementing groups orthogonal to the roles to manage access, but it doesn't make sense in my case.