I'm updating an extremely ancient CSLA (1.x era) project to 4.10 and our original authorization is permission based. Users can set each users rights to 84 types of objects (RootObjectTypes in the code below) within our app at 4 different levels (No access, read only, read/write, delete).
Rights are set for security groups and users are set to a security group within the app.
To support this we can't use the roles based authorization in the examples so I have built something that appears to work in 4.10 and just want to confirm if it makes sense / serve as a possible example to others doing this type of authorization.
When the user logs in their rights for their security group are retrieved and stored within our custom Identity object in a property like this:
public static readonly PropertyInfo<Dictionary<RootObjectTypes, int>> RightsProperty = RegisterProperty<Dictionary<RootObjectTypes, int>>(x => x.Rights);
public Dictionary<RootObjectTypes, int> Rights
{
get { return ReadProperty(RightsProperty); }
private set { LoadProperty(RightsProperty, value); }
}
This is my custom authorization:
class IsAllowed : Csla.Rules.AuthorizationRule
{
private RootObjectTypes _rootObjectType;
/// <summary>
/// Creates an instance of the rule.
/// </summary>
/// <param name="action">Action this rule will enforce.</param>
/// <param name="objectType">Object type</param>
public IsAllowed(AuthorizationActions action, RootObjectTypes objectType)
: base(action)
{
_rootObjectType = objectType;
}
/// <summary>
/// Rule implementation.
/// </summary>
/// <param name="context">Rule context.</param>
protected override void Execute(AuthorizationContext context)
{
context.HasPermission = false;
Dictionary<RootObjectTypes,int> nRights = ((AYIdentity)Csla.ApplicationContext.User.Identity).Rights;
if (nRights.ContainsKey(_rootObjectType))
{
int nRight=nRights[_rootObjectType];
//1=No Access, 2=ReadOnly, 3=ReadWrite, 4=ReadWriteDelete
//full rights short circuit
if (nRight > 3)//read/write/delete
{
context.HasPermission = false;
return;
}
//no rights short circuit
if (nRight < 2) //no access allowed at all
return;
//can read?
if (this.Action == AuthorizationActions.GetObject)
{
//We've already established it's not NOAccess so by default read is allowed
context.HasPermission = true;
return;
}
if (this.Action == AuthorizationActions.CreateObject || this.Action == AuthorizationActions.EditObject)
{
//We make no distinction between creation and edit
if(nRight > 2)
context.HasPermission = true;
return;
}
if (this.Action == AuthorizationActions.DeleteObject)
{
if (nRight > 3)
context.HasPermission = true;
return;
}
}
}
}//eoc
This is how I call it in a test "UserInfo" read only object I made only for this test (it's not related to the authorization):
public static void AddObjectAuthorizationRules()
{
Csla.Rules.BusinessRules.AddRule(typeof(UserInfo), new IsAllowed(Csla.Rules.AuthorizationActions.GetObject, RootObjectTypes.User));
}
It appears to work properly. Anything glaringly wrong or does this seem ok?
Instead of ContainsKey and then an index lookup, you might be able to use a Try method on the dictionary (I don't remember the name right now) to try and get the value. You'll get the contains result and actual value all in one shot that way, which would provide better perf (often much better perf).
Cool thanks Rocky.
Like this:
int nRight = 0;
if (nRights.TryGetValue(_rootObjectType, out nRight))
{
Copyright (c) Marimer LLC