...

Have you come across any complex scenarios where you need to use multiple roles for users and your code complexity increase as the business rules changes? As the application development continues more roles get added and your code gets unmaintainable? Have you had scenarios when only one single role can only be given to user despite them having multiple roles type as a business scenario?

One effective way to manage complex roles is by Flags attributes for the enum. Flags allow an enum value to contain many values. An enum type with the flags attribute can have multiple values assigned. Flags enumerations are used for masking bit fields and doing bitwise comparisons. They are the correct design to use when multiple enumeration values can be specified at the same time.

It is defined as below. The values are set as power of 2.
[Flags]
EnumRoles
{
None =0
SiteAdmin =1
PageAdmin=2
User=4
ReadOnly=8
Region=16
SitePageAdmin = SiteAdmin | PageAdmin
UserReadOnly = User | ReadOnly
}
As you can see the combination of roles is represented by the bitwise operator |. Combination roles will have a value of individual roles.

e.g SitePageAdmin will have a value of SiteAdmin + PageAdmin = s3. Bitwise operation of 01 |10 = 11

Database Storage

Only the individual roles need to be stored in the master table of roles

The Authorized roles for a user stores separate record corresponding to each role. Roles thus stored can be combined to single value
EnumRoles.userRole = EnumRoles.None;
UserRoles.ForEach(ld =>
{
if(userRole>0)
{
userRole = userRolelist | ld.Role
}
else
{
userRole = ld.Role
}

});
The above code will translate multiple records to a single value of userRole.

C# code

To check if the user has a particular role:

EnumRoles.SiteAdmin.HasFlag(userRole)
Or
If( (EnumRoles.SitePageAdmin & userRole) > 0)
The HasFlag method can check for simple types but to check for complex type we can use the bitwise operator.
Javascript Code
Define an object with the same values
var RoleType =
{
None: 0,
SiteAdmin: 1,
PageAdmin: 2,
User: 4,
ReadOnly: 8,
Region :16

}
RoleType .SitePageAdmin = RoleType .SiteAdmin | RoleType .PageAdmin
RoleType .UserReadOnly = RoleType .User | RoleType .ReadOnly

//Check for a particular Role
If( (RoleType.SitePageAdmin & usserRole) > 0){
}

Use it in a lambda expression

var userRoles = response.Where(x =>((EnumRoles.PageAdmin.HasRole(x.Role) != 0))
HasRole method does not work when both the Enum and value are of the complex type. Using the bitwise operator works in all scenarios.
var userRoles = response.Where(x => ((x.Role & EnumRoles.SitePageAdmin) != 0))

Using a single variable to specify all the roles of a particular user simplifies the roles. Using a bitwise operation on the single variable we can find out, if the user in question has access to a particular functionality on the server side, client side or even the database side. Adding a new role or changing the role type can be done at on place and it does not lead to code changes in all parts of the application.

Conclusion

Flags attribute indicates that an enumeration can be treated as a bit field. Flag Attribute in enumeration or designing the enumeration correctly can help us represent more complex constants and combinations. This works very well for roles in the applications when the combination of roles or group of roles can be defined permissions to a feature. We saw how we can use it in C# .NET, within a lambda expression and Javascript.