I'm trying to implementing a new permission based access approach for my MVC application; We have several Permission Group and each group contains a list of Permission. for example we have Invoices
permission group which contains CreateInvoice,RemoveInvoice,etc
permission keys.
In this approach each mvc Action
should requires a specific permission for execution. I'm trying to do this through CustomAttributes, something like this :
public class InvoiceController : Controller
{
[RequirePermission(Permissions.Invoices.CreateInvoice)]
public ActionResult Create()
{
return View();
}
}
To make it easier for developers to remember different Permission Groups and Permission Keys I'm trying to create a pre-defined list of permissions that should be a combination of permission group and permission key. but due to restrictions applied to using attributes arguments in C# I couldn't make it work yet. (I don't want to make an extra large enumurator and put all permission keys in there)
my last try was creating an enumerator for each permission group and then define permission keys as enum constants in there :
public class PermissionEnums
{
[PermissionGroup(PermissionGroupCode.Invoice)]
public enum Invoices
{
CreateInvoice = 1,
UpdateInvoice = 2,
RemoveInvoice = 3,
ManageAttachments = 4
}
[PermissionGroup(PermissionGroupCode.UserAccounts)]
public enum UserAccounts
{
Create = 1,
ChangePassword = 2
}
}
As you can see we have a combination of codes here, the permission group key specified using a PermissionGroup
attribute and permission key's code specified as numeral code on each enum constant.
the RequirePermission attribute defined as below :
public class RequirePermissionAttribute : Attribute
{
private Enum _Permission;
public RequirePermissionAttribute(Enum Permission)
: base()
{
_Permission = Permission;
}
}
but the problem is that objects of type Enum
could not be used as Attribute Arguments.
Any suggestion/idea is appreciated
I've found the solution, the only thing needs to be changed is type of constructure parameter. instead of using Enum
you have to use object
:
public class RequirePermissionAttribute : AuthorizeAttribute
{
private object _Permission;
public RequirePermissionAttribute(object Permission)
: base()
{
_Permission = Permission;
}
}
Here is the complete code :
/***************** Permission Groups And Keys *****************/
public static class Permissions
{
[PermissionGroup(PermissionGroupCode.Invoice)]
public enum Invoices
{
CreateInvoice = 1,
UpdateInvoice = 2,
RemoveInvoice = 3,
ManageAttachments = 4
}
[PermissionGroup(PermissionGroupCode.UserAccounts)]
public enum UserAccounts
{
Create = 1,
ChangePassword = 2
}
}
public enum PermissionGroupCode
{
Invoice = 1,
UserAccounts = 2,
Members = 3
}
/***************** Attributes & ActionFilters *****************/
[AttributeUsage(AttributeTargets.Enum)]
public class PermissionGroupAttribute : Attribute
{
private PermissionGroupCode _GroupCode;
public PermissionGroupCode GroupCode
{
get
{
return _GroupCode;
}
}
public PermissionGroupAttribute(PermissionGroupCode GroupCode)
{
_GroupCode = GroupCode;
}
}
public class RequirePermissionAttribute : AuthorizeAttribute
{
private object _RequiredPermission;
public RequirePermissionAttribute(object RequiredPermission)
: base()
{
_RequiredPermission = RequiredPermission;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var permissionGroupMetadata = (PermissionGroupAttribute)_RequiredPermission.GetType().GetCustomAttributes(typeof(PermissionGroupAttribute), false)[0];
var groupCode = permissionGroupMetadata.GroupCode;
var permissionCode = Convert.ToInt32(_RequiredPermission);
return HasPermission(currentUserId, groupCode, permissionCode);
}
}
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