Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enums to define permission sets in c#

Instead of splitting each permission into individual columns or sql server table we are rethinking of using Flag attribute to Enum for use with bit wise operations. Our application defines end points ( not the one from rest services) for accessing resources( read, modify, update) and each user is entitled with permissions for example Bob has permissions to Read, Modify resource X so when bob comes and accesses this resource we check if bob has permission x.Now that where we are going to apply this is clear here are my doubts

  • Suppose Bob has Read, Write, Delete permission on resource using Flagged enumerations i would do Permission.Read | Permission.Write | Permission.Delete Is the end result of bit wise AND a integer or another Enum ?

  • For Storing this permission in database table should the column be a integer?

  • If answer to question 1 is Enum then should i define another property on the Permissions enum that represents the integer value of Bit wise and operation?

disclaimer: the Bob referred to in the example does not represent any user in the Stack overflow network of sites or any person. It is just another character

like image 254
Deeptechtons Avatar asked Apr 23 '12 04:04

Deeptechtons


2 Answers

To answer your questions in order:

  • Assuming you have set the [Flags] attribute on the enum, and use the correct operator (& and | for bitwise operations) it is essentially both. If you cast the result to an integer, you will get the bitwise and of the relevant values, ie. 7 for your example. If you use .ToString(), then you will get a string back indicating that the value has all three values. I believe that there is a HasFlags() method somewhere, but most code I have seen uses the tried and true bitwise code for comparisons, ie:

    var x = Permissions.Read | Permissions.Write;
    if ((x & Permissions.Read) == Permissions.Read) { print "Success!"; }
    

    From a technical standpoint, C#'s type safety helps keep things sane and the result of |ing or &ing two enums of the same type is another enum of the same type but all enums are simply integers, and can be treated as such in most cases, though some things need explicit casts to/from int.

  • It should be an integral type, yes. I believe the default type for an enum is Int32, however you can set that explicitly if you want to match up the database and code exactly.

  • Given all the above, it can still make a lot of sense to have predefined values for commonly used sets of permissions, for example ReadWrite. In particular, a None element is recommended for all enums by Microsoft, especially if you are going to be casting values. This allows for a fallback and a valid value for freshly initialized variables as well as a sane value for default(Permissions). You can set values in your enum based on other ones like so:

    [Flags]
    enum Permissions {
      None =    0,
      Read =    0x001,
      Write =   0x010,
      Execute = 0x100,
      ReadWrite = Read | Write,
      // [snip]
    }
    
like image 198
Matthew Scharley Avatar answered Oct 22 '22 13:10

Matthew Scharley


  1. Bitwise OR/AND for values of enum marked with [Flags] are values of the same enum.
  2. Integer is reasonable filed to store enum values in database.
  3. No, you don't need to add additional enum values, but may do so for conviniece.

Normaly you define such enums with FlagsAttribute i.e.

[Flags] enum My {
  None = 0, Read =1, Write =2, Delete = 4
};

When defined this way you can combine different values with | (or) operation:

My readAndWrite = My.Read | My.Write;

Bitwise AND will give you 0 for enum values that represent unique flags, but commonly used to mask other bits:

bool doIHaveWrite = (readAndWrite & My.Write) == My.Write;

Note that logical AND (&&) can't be applied to enum values.

like image 31
Alexei Levenkov Avatar answered Oct 22 '22 11:10

Alexei Levenkov