What datatype to use to store user permissions

c#

Solution

We ended up with:

 public class EntityPermission
    {
        private readonly List<GetUserPermissionsResult> _userPermissionDataSet;
        private readonly Dictionary<int, Dictionary<int, int>> _permissions;
        /// <summary>
        /// Constructor to generate permissions for a user
        /// </summary>
        /// <param name="ds">
        /// Dataset of type List GetUserPermissionsResult
        /// based on a stored procedure which brings back the 
        /// valid permissions of a user.
        /// The result is a matrix of size [Enitities] * [Actions]
        /// Where each entity action [index] is the value (right).
        /// In general terms, the entity e with action a has right r.
        /// </param>
        public EntityPermission(List<GetUserPermissionsResult> ds)
        {
            _userPermissionDataSet = ds;
            _permissions = new Dictionary<int, Dictionary<int, int>>();
            SetPermissions();
        }

        /// <summary>
        /// Called from the constructor of EntityPermission.
        /// This method fills our matrix of size entity * action with 
        /// the valid rights.
        /// </summary>
        public void SetPermissions()
        {
            var dt = _userPermissionDataSet;
            for (int i = 1; i<=Enum.GetNames(typeof(Module)).Length; i++)
            {
                var actionDictionary = new Dictionary<int, int>();
                for (int j = 1; j<=Enum.GetNames(typeof(ActionEnum)).Length; j++)
                {
                    var value = (from a in dt where a.EntityID == i && a.ActionID == j select a.Answer).FirstOrDefault();
                    if (value != null)
                        actionDictionary.Add(j , (int) value);
                    else actionDictionary.Add(j, (int)Answer.No);
                }
                _permissions.Add(i, actionDictionary);
            }
        }

        /// <summary>
        /// Method to get the rights provided an entity (a module)
        /// and an action on that module.
        /// </summary>
        /// <param name="entityIdKey"></param>
        /// <param name="actionIdKey"></param>
        /// <returns></returns>
        public int GetPermission(int entityIdKey, int actionIdKey)
        {
            return _permissions[entityIdKey][actionIdKey]; 
        }   
    }

The readonly `List<GetUserPermissionsResult>` was a returned type from a sproc that returned a matrix based on my question - without too many details:

SELECT 
    e.EntityID AS EntityID,
    a.ActionID AS ActionID, 
    CASE MAX(ar.[Rank]) 
        WHEN 3 THEN 1   --yes
        WHEN 2 THEN 3   --originator only
        WHEN 1 THEN 2   --no
    END AS [Answer]
FROM
 ....

This sproc had a bunch of joins but basically grouped by the following:

GROUP BY
    e.EntityID,
    a.ActionID

This ensures we get an action per a module (the entity).

We stored this object as part of the user's session:

`public EntityPermission Permission { get; set; }`

And then we simply could make a call to GetPermission to get the result:

 if (((int)Answer.Yes ==
                 MySession.Current.Permission.GetPermission((int)Module.SubProject, (int)ActionEnum.Edit))

Problem

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.

Original source