4.10 Permission based authorization example - am I doing it right?

4.10 Permission based authorization example - am I doing it right?

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


JCardina posted on Wednesday, February 16, 2011

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?

RockfordLhotka replied on Wednesday, February 16, 2011

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).

JCardina replied on Wednesday, February 16, 2011

Cool thanks Rocky.

Like this:

int nRight = 0;
           if (nRights.TryGetValue(_rootObjectType, out nRight))
           {

Copyright (c) Marimer LLC