I am developing an application where the client needs and extremely flexible user rights system. For example, a user should be able to have update rights in Form A but not in Form B (which prevents me from defining broad update rights). Admin should also be able to transfer specific rights to a user.
I was thinking of using the Command Pattern
with CanExecute
method but not really sure how I can use it in such a dynamic/specific way. Any suggestions ?
I have a similar situation in my application, which can be extended via plugins and the plugins can bring in their own permission. I solved that the following way:
PermissionManager
Simplified class structure:
public class PermissionManager
{
public static Dictionary<string, IEnumerable<string>> AvailablePermissions { get; set; }
public static bool? Can(User user, string permission)
{
// check DB
return DENIED ? false : (ALLOWED ? true : null);
}
}
public class MyPlugin : IPlugin
{
public void Init()
{
PermissionManager.AvailablePermissions["MyPlugin"] =
new List<string>() { "Permission1", "Permission2" };
}
public void DoWork()
{
if (PermissionManager.Can(user, "Permission1") != true)
throw new NotAllowedException();
// do work
}
}
This is the basic patter I use. Of course you should use constants or similar for the permission names/keys. The admin UI can then iterate AvailablePermissions
in the configuration UI.
In the DB I have something like the following (EF Code-First):
public class UserProfilePermissions
{
public UserProfile User { get; set; }
public Permission Permission { get; set; }
public bool IsAllowed { get; set; }
}
public class Permission
{
public int Id { get; set; }
public string Key { get; set; }
public string Group { get; set; }
}
So for every permission there is one Permission
entry created (on the first assignment) in the DB and mapped via the mapping table using the IsAllowed
to define "ALLOWED" or "DENIED".
The null
value defines a not set permission so default values can be used (=> not set permission does not always say "DENIED").
The mapping table can also be used in the same style for e.g. roles.