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.
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.
User permissions, part of the overall user management process, are access granted to users to specific resources such as files, applications, networks, or devices.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With