Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What datatype to use to store user permissions

Tags:

c#

We've developed code that basically returns data for a user's permissions on an entity. For instance, an entity could be one of the following:

-Company
-Contact
-Project
-Issue etc...

We then can assign policies (and a person can get multiple policies) that allow a user to perform an action:

-Create
-Edit
-Delete
-Export

So basically one policy could say that user A has the right to create a company, but another policy which this same user has says that he does not have the right to create a company. In this case we take the rights that allow before the rights that dont allow. In this example, he/she would be allowed to create a company.

So basically you end up with data like so:

Policy1 Company Create Yes
Policy1 Company Edit Yes
Policy1 Company Delete No
Policy2 Company Create No
Policy2 Company Edit   Yes
Policy2 Company Delete No

I have a query which we use to return what is this user's permission based on the rules we discussed.

In this case running the query the result would be:

Company create yes
Company edit yes
Company delete no

Our app isn't just a bit yes / no for whether they can perform the action or not. We have yes / no / owner only (for records that should only be edited / deleted by the owner only. Our query is great and is returning the correct data.

My question is what data type should I use in C# to basically say:

Given an entity (company) given an action (create) what is the value. Basically at the end of the day I want to build a matrix that looks like this:

           Create     Edit        Delete
Company      Yes     Owner Only    Yes
Contact      No      No            No
Project      Yes     Yes          Owner Only

The rows on the first column represent the entity, the columns after that represent the actions (create, edit, delete). The combination of the 2 for instance index: [Company][Create] = Yes would give you the right of the action based on the entity.

So what datatype fits this model where I can perform some index like: [Contact][Edit]=No. We also have to session this object / come up with a way (maybe dynamically) to get the result based on an entity and action.

I thought session would be good so that we can check the rights once and only once until the user logs out.

like image 595
JonH Avatar asked Jul 09 '14 21:07

JonH


People also ask

How do you store access rights to a database?

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.

What are user permissions?

User permissions, part of the overall user management process, are access granted to users to specific resources such as files, applications, networks, or devices.


1 Answers

This is not a final answer, but I thought about this and maybe I can get some feedback. Here is what I came up with:

I was thinking about how to store the permissions and I believe I have come up with something that just might work.

I kept thinking throughout all of this is – all I need is a 2d matrix…then the obvious hit me, why simply do we not use a simple 2d int matrix? It works, at least on paper it does.
As you know we have some enums:

Modules          Answer                 Action 
Contact = 1      Yes = 1                Create = 1
Corp = 2         No = 2                 Edit = 2
Company = 3      Originator Only = 3    Delete = 3
Program = 4                             View = 4
Project = 5                             List =5
SubProject  = 6                         Export = 6
Issue = 7       
LL = 8      
User = 9        

In this case we have 9 modules with 6 action types, therefore we need a matrix of the size [9x6] to generate 54 possible entries based on the matrix[i,j]. This would work even if we added more modules and more actions.

The type is simply: int[,] permissions = new int[Enum.GetNames(typeof(Modules)).Length, Enum.GetNames(typeof(Action)).Length];

Translates simply to: int[,] permissions = new int[9,6]

So far this gives us the matrix as an empty matrix. We have to remember that arrays / matrices in C# are zero based…which is fine. We already have a stored procedure that returns the data like so:

Module       Action          Answer
1 (Contact)   1 (Create)     1 (Yes)
1 (Contact)   2 (Edit)       1 (Yes)
1 (Contact)   3 (Delete)     2 (No)
…..     
2 (Corp)      1 (Create)     1 (Yes)
2 (Corp)      2 (Edit)       1 (Yes)
Etc…etc…

So now to fill the array we have the following, this is just C# pseudo code:

for(int i=0; i<Enum.GetNames(typeof(Modules)).Length; i++) {
  Reader.read();  //read the first row from the database
   For(int j=0; j<Enum.GetNames(typeof(Action)).Length; j++) {
         Permissions[i,j] = reader[“Answer”];  //assign the answer from the returned row to the array
        If( j<Enum.GetNames(typeof(Action)).Length-1) {
            Reader.read(); //read next row in database
        } //end if condition
  } //end for j
} //end for i

This loop will simply produce the result of this:

             1 Create    2 Edit 3 Delete    4 View  5 List  6 Export
1(Contact)     1           1      2            1    1         1
2(Corp)        1           3      2            1    1         1
3(Company)     1           1      1            1    1         1
4(Program)     1           1      1            1    1         1
5(Project)     1           1      2            1    1         1
6(SubProject)  1           1      2            1    1         1
7(Issues)      1           1      1            2    1         1
8(LL)          1           1      1            1    1         1
9(User)        2           2      2            1    2         2

This would be per user…And this is exactly what I want because I want to write code similiar to this (remember this is just pseduo):

If(MySession.Current.Permission[(int)Module.Contact – 1, (int)Action.Create] == (int)Answer.Yes)
 {
  //this allows contact create
}

This is very flexible as we could potentially add any new modules without affecting anything. I can reference things simply by Permission[Module.ModuleIWant – 1, Action.ActionIWant – 1].

We simply ensure we take 1 away from it since the array is zero based…We don’t need anything else. It's probably not the best solution but I think it can work...

like image 188
JonH Avatar answered Sep 20 '22 04:09

JonH