CanExecute() Authorization Design Scope Question

CanExecute() Authorization Design Scope Question

Old forum URL: forums.lhotka.net/forums/t/11033.aspx


rxelizondo posted on Thursday, January 05, 2012

Hello.

Suppose you have a class with a method called “DoIt()” and a property called “IsLocked”. Suppose also that “DoIt()” can only be called by a user belonging to a particular role and it should only be called when the object is not locked. How would you design your “DoIt()” method?

Would you do this (approach number one)?


public void DoIt()
{
    CanExecuteMethod(DoItMethod, true);

    if (IsLocked)
        throw new YouCantDoThisIfObjectIsLocked();

    // Code that does whatever DoIt() needs to do goes here.
}

In the example above, The “CanExecuteMethod()” would run an authorization rule that only checks if the user is in role, it does not care if the object is locked or not. If user is in role the function would proceed  else an authorization error would be raised.


Or would you do this (approach number two):


public void DoIt()
{
    CanExecuteMethod(DoItMethod, true);

    // Code that does whatever DoIt() needs to do goes here.
}

In the example above, The “CanExecuteMethod()” would run an authorization rule that would check if the user is in role plus if the object is locked or not. If user is in role and the object is not locked the function would proceed else an authorization error would be raised.

What approach would you take? My gut feeling tells me that the way to go is approach number one. The reason for this is because I see the “CanExecuteMethod()” strictly as something that tells me if a user has the permissions to do something or not. I kind of feel that the business requirement of not being able to run the function while the object is locked belongs somewhere else.

So what woudl you do?

Thanks for your help.

RockfordLhotka replied on Thursday, January 05, 2012

I am not convinced that there's a right or wrong answer.

However, I view authorization rules as business rules, not just as a role-based security concept.

There are many examples where authorization depends on the state of the object, the context of the application, and the identity of the user. Authorization rules should be able to take all those things into account.

JonnyBee replied on Thursday, January 05, 2012

My choice would be #2.

AuthorizationRules included in CSLA is only for role checking but is designed and supposed to be used for business rules as your description here.

You could then easily create a bool property in f.ex a ViewModel to say whether DoIt can be enabled or not based on CanExecuteMethod.

So my code would look like this:

    public MethodInfo DoItMethod = RegisterMethod(o => o.DoIt());
    public void DoIt()
    {
      CanExecuteMethod(DoItMethod, true);

      // actual code goes here.....
    }

    // here shown is a private inner AuthorizationRule.
    private class DoItAccess : Csla.Rules.CommonRules.IsInRole
    {
      public DoItAccess(AuthorizationActions action, IMemberInfo memberInfo, params string[] roles) : base(action, memberInfo, roles)
      {
      }

      protected override bool CacheResult
      {
        get { return false; }
      }

      protected void Execute(AuthorizationContext context)
      {
        // not in role then no access
        base.Execute(context);
        if (!context.HasPermission) return;

        // check if object is locked
        var locked = (bool) ReadProperty(context.Target, Root.LockedProperty);
        context.HasPermission = !locked;
      }
    }

rxelizondo replied on Friday, January 06, 2012

Thank you Rocky and Jonny for your feed back.

You know, the funny thing is that we were using "approach number two" first but we started over thinking the approach and decided to switch to "approach number one" but as we were switching we started once again over thinking the approach and we ended up running in circles and I finally decided to post for help.

I think we will stick with approach number two then.

Thank you very much.

 

Copyright (c) Marimer LLC