Changing "AuthorizationRuleManager" behaviour.

Changing "AuthorizationRuleManager" behaviour.

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


sash_kr posted on Sunday, August 11, 2013

Base class:

public class MyBusinessBase<T> : BusinessBase<T> where T:  MyBusinessBase<T>

{

    protected static void AddObjectAuthorizationRules()
    {
        var tp = typeof(T);
        var roleName = "role_" + tp;
        BusinessRules.AddRule(tp, new IsInRole(AuthorizationActions.CreateObject, roleName));
        BusinessRules.AddRule(tp, new IsInRole(AuthorizationActions.GetObject, roleName));
    }

}

 

If we will change "AuthorizationRuleManager" behaviour like this:

    private static void InitializePerTypeRules(AuthorizationRuleManager mgr, Type type)
    {

        ...

        var type2 = type;
        var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic |  BindingFlags.DeclaredOnly;
        while (type2 != typeof(object))
        {
            // invoke method to add auth roles
            var method = type2.GetMethod("AddObjectAuthorizationRules", flags);
            if (method != null)
            {
                method.Invoke(null, null);
                break;
            }
            type2 = type2.BaseType;
        }

        ...

    }

 

We will achive next:

- all inherited objects will inherit  "AddObjectAuthorizationRules" method. And I can even override this method.

 

So, is this good or bad idea?

JonnyBee replied on Sunday, August 11, 2013

I believe you have missed one very important point.

There can only be one-1 authorization rule for each Type - MethodInfo and AuthorizationAction. 

For object authorization rules the MethodInfo is null - so there can only be one authorization rule per AuthorizationAction.

This limitation - in my opinion - makes it non-practical to call into a base class or make this an override method.. 

sash_kr replied on Monday, August 12, 2013

"There can only be one-1 authorization rule for each Type - MethodInfo and AuthorizationAction."

 

 "AddObjectAuthorizationRules()" method is static. So it's OK. If I need to override base "AddObjectAuthorizationRules" method I can just declare new method:

static void  AddObjectAuthorizationRules()

{

 BusinessRules.AddRule(typeof(NewType), new IsInRole(AuthorizationActions.CreateObject, "role_NewType_Create"));

}

 

So,  "AuthorizationRuleManager" will call only this one method. Base method will stay untouched.

"For object authorization rules the MethodInfo is null - so there can only be one authorization rule per AuthorizationAction." 

 As you can see, new behaviour doesn't break this limitation.

sash_kr replied on Tuesday, August 13, 2013

I see as usually you didn't understand me.

I think we are like from different planets. Maybe the problem is in my english or we have different kind of thinking?

Let's look at little example:

 

    public class MyBusinessBase<T> : BusinessBase<T> where T : MyBusinessBase<T>
    {
        protected static void AddObjectAuthorizationRules()
        {
            var tp = typeof(T);
            var roleName = "role_" + tp.Name;
            BusinessRules.AddRule(tp, new IsInRole(AuthorizationActions.CreateObject, roleName));
            BusinessRules.AddRule(tp, new IsInRole(AuthorizationActions.GetObject, roleName));
        }
    }

    public class Invoice : MyBusinessBase<Invoice>
    {
    }

    public class Order : MyBusinessBase<Order>
    {
        // override base method
        new static void AddObjectAuthorizationRules()
        {
            BusinessRules.AddRule(typeof(Order), new IsInRole(AuthorizationActions.CreateObject, "role_admin"));
            BusinessRules.AddRule(typeof(Order), new IsInRole(AuthorizationActions.GetObject, "role_admin"));
        }
    }

 

So, as you can see "Invoice" will use "base"  "AddObjectAuthorizationRules" method. And "Order" "overrides" "AddObjectAuthorizationRules" method.

For now, CSLA doesn't allow me to do that and "Invoice" class should look like this:

    public class Invoice : BusinessBase <Invoice>
    {
        static void AddObjectAuthorizationRules()
        {
            var tp = typeof(Invoice);
            var roleName =  "role_Invoice";  //"role_" + tp.Name;
            BusinessRules.AddRule(tp, new IsInRole(AuthorizationActions.CreateObject, roleName));
            BusinessRules.AddRule(tp, new IsInRole(AuthorizationActions.GetObject, roleName));
        }
    }

 

Is it clear now?

JonnyBee replied on Tuesday, August 13, 2013

So what you propose is to add a new BindingFlags.FlattenHierarchy like this:

// invoke method to add auth roles
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic 
BindingFlags.DeclaredOnly | BindingFlags.FlattenHierarchy; System.Reflection.MethodInfo method = type.GetMethod("AddObjectAuthorizationRules", flags); if (method != null) method.Invoke(nullnull);

I need Rocky to chime in to this - for now I will add an Issue for this.

See: https://github.com/MarimerLLC/csla/issues/192

sash_kr replied on Tuesday, August 13, 2013

"So what you propose is to add a new BindingFlags.FlattenHierarchy like this:"

Yes. I forgot about  FlattenHierarchy.

But flags should look like this (without DeclaredOnly):

var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;

 

P.S.

By the way. How do you insert colored text? "Paste from Word" never works for me.

JonnyBee replied on Tuesday, August 13, 2013

I use the CopyAsHtml extension for VS2010 - or HtmlCopy in Productivity Power Tools for VS2012 and paste the code into Firefox or IE browser.

Paste unfortunately doesn't work that nicely in Chrome. 

Cymro replied on Friday, March 28, 2014

Which versions are we looking at here?  The BindingFlags.FlattenHierarchy flag appeared to disappear somewhere between version 4.1.x and 4.3.14.  

We have a task / role based security system and we implemented a standard implementation (in our MyBusinessBase<T> class).  This checks for an attribute on the sub-class and if it exists adds the rules using the Attribute Value.

Code Snippet
  1.         Protected Shared Sub AddObjectAuthorizationRules()
  2.             Dim subClass As Type = GetType(T)
  3.             Dim attr As SecuritySubTaskAttribute = CType(subClass.GetCustomAttributes(GetType(SecuritySubTaskAttribute), False).FirstOrDefault, SecuritySubTaskAttribute)
  4.             If attr IsNot Nothing Then
  5.                 Csla.Rules.BusinessRules.AddRule(GetType(T), New UserHasAmsRoleSubTask(AuthorizationActions.CreateObject, attr.SubTaskID))
  6.                 Csla.Rules.BusinessRules.AddRule(GetType(T), New UserHasAmsRoleSubTask(AuthorizationActions.GetObject, attr.SubTaskID))
  7.                 Csla.Rules.BusinessRules.AddRule(GetType(T), New UserHasAmsRoleSubTask(AuthorizationActions.EditObject, attr.SubTaskID))
  8.                 Csla.Rules.BusinessRules.AddRule(GetType(T), New UserHasAmsRoleSubTask(AuthorizationActions.DeleteObject, attr.SubTaskID))
  9.             End If
  10.         End Sub

This allows for a sub-class to be simply decorated with the "Security SubTaskID", or it can implement it's own rules if need be.  Unfortunately we have recently upgraded to 4.3.14 and lost this behaviour.

Copyright (c) Marimer LLC