Authorization 4 (aka new authz)

Authorization 4 (aka new authz)

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


tiago posted on Wednesday, June 02, 2010

Hi Rocky,

I've read your blog post about the new authorization system in CSLA.NET 4

We can have:

- per-type rules
- per-property rules
- per-instance rules

I have a few question:

1)
protected override void AddBusinessRules() {} is the method where we add per-type and per-property rules (authorization and plain business rules)?

2)
protected static void AddObjectAuthorizationRules() {} is the method where we add per-instance authorization rules?

3) The difference between type and property rules seems to be just the Authorization Action specified. Is this correct?

4) We can add property rules in both 1) and 2) methods. It looks like we can also have per per-instance property rules. Is this supposed to be like this? Will this work?

RockfordLhotka replied on Wednesday, June 02, 2010

It is important to get the terms/definitions right:

AddBusinessRules() is where you add per-property and per-method rules. This is the same as 3.8.

The static AddObjectBusinessRules() is where you add per-type (and "per-instance") rules (since they are really the same thing). This is the same as 3.8.

You must add the per-type rules in the static method, because that's the only way they can be available before the first instance of the type has been created. Suppose your app is just starting up, and you want to enable/disable the "Create Customer" button. And suppose you add your per-type rules in AddBusinessRules(), which is run the first time a customer is created. So the UI thinks the user can create a customer, even though your actual rule might block that action...

If you set up the per-type rules in AddObjectAuthorizationRules(), then the rules are set up earlier - on the first access to the type, not an instance of the type. So as your app starts up the "Create Customer" button is disabled as expected.

Russ replied on Wednesday, June 02, 2010

Hi Rocky, I'm struggling with the same problem. I had placed my per-type rules in my AddBusinessRules method but the first time the system called HasPermission it ALWAYS returned true even if the user wasn't in the Admin role. Here is the code:

protected override void AddBusinessRules()

{

  base.AddBusinessRules();

  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(CodeProperty));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxLength(CodeProperty, 10));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(DescriptionProperty));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxLength(DescriptionProperty, 100));

 

  BusinessRules.AddRule(new IsInRole(AuthorizationActions.CreateObject, new List<string> { "Admin" }));

  BusinessRules.AddRule(new IsInRole(AuthorizationActions.EditObject, new List<string> { "Admin" }));

  BusinessRules.AddRule(new IsInRole(AuthorizationActions.DeleteObject, new List<string> { "Admin" }));

}

 

I just read your response and I have now move the rules around like this:

protected override void AddBusinessRules()

{

  base.AddBusinessRules();

  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(CodeProperty));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxLength(CodeProperty, 10));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(DescriptionProperty));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxLength(DescriptionProperty, 100));

}

 

protected static void AddObjectBusinessRules()

{

  BusinessRules.AddRule(new IsInRole(AuthorizationActions.CreateObject, new List<string> { "Admin" }));

  BusinessRules.AddRule(new IsInRole(AuthorizationActions.EditObject, new List<string> { "Admin" }));

  BusinessRules.AddRule(new IsInRole(AuthorizationActions.DeleteObject, new List<string> { "Admin" }));

}

 

The problem is the three AddRule lines in the static AddObjectBusinessRules give the following error:

An object reference is required for the non-static field, method, or property 'Csla.Rules.BusinessRules.AddRule(Csla.Rules.IAuthorizationRule)'

Can you tell me what I'm doing wrong?

Thanks

Russ.

 

P.S. There appears to be a contradiction in your last post. You initially say that per-type rules go in the static AddObjectBusinessRules() and later you say they go in the AddObjectAuthorizationRules() method.  I have tried both with the same results.

RockfordLhotka replied on Wednesday, June 02, 2010

The static method is named AddObjectAuthorizationRules(). There is no AddObjectBusinessRules() - though maybe that should be changed to be consistent?

In any case, the problem you are hitting is that you need to disambiguate "BusinessRules" since it is a protected property of the base class, but you want to use the actual type from Csla.Rules:

Csla.Rules.BusinessRules.AddRule(...);

 

Russ replied on Wednesday, June 02, 2010

Thanks Rocky!

 

Here is the working code for anyone who is following this thread:

 

protected override void AddBusinessRules()

{

  // per-property and per-method rules go here

  base.AddBusinessRules();

  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(CodeProperty));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxLength(CodeProperty, 10));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(DescriptionProperty));

  BusinessRules.AddRule(new Csla.Rules.CommonRules.MaxLength(DescriptionProperty, 100));

}

 

protected static void AddObjectAuthorizationRules()

{

  // per-type rules go here

  BusinessRules.AddRule(typeof(AddressCode), new IsInRole(AuthorizationActions.CreateObject, new List<string> { "Admin" }));

  BusinessRules.AddRule(typeof(AddressCode), new IsInRole(AuthorizationActions.EditObject, new List<string> { "Admin" }));

  BusinessRules.AddRule(typeof(AddressCode), new IsInRole(AuthorizationActions.DeleteObject, new List<string> { "Admin" }));

}

 

Russ

 

BruderKotlett replied on Tuesday, July 05, 2011

Hi,

I also have this problem. Here is my code:

        protected static void AddObjectAuthorizationRules()
        {
            // CRUD --> Create, Read, Update, Delete (Reading all user groups fomr the database)
            BenutzerGruppeList gruppen = BenutzerGruppeList.GetBenutzerGruppeList();

            List<string> create = new List<string>();
            List<string> read = new List<string>();
            List<string> update = new List<string>();
            List<string> delete = new List<string>();

            // Put the groupd into my list objects, regarding CRUD permissions
            foreach (BenutzerGruppe g in gruppen)
            {
                if (g.BenutzerAnlegen)
                {
                    create.Add(g.Bezeichnung);
                }

                if (g.BenutzerLesen)
                {
                    read.Add(g.Bezeichnung);
                }

                if (g.BenutzerBearbeiten)
                {
                    update.Add(g.Bezeichnung);
                }

                if (g.BenutzerLoeschen)
                {
                    delete.Add(g.Bezeichnung);
                }
            }

            // Adding the rules to my "Benutzer" object
            Csla.Rules.BusinessRules.AddRule(typeof(Benutzer), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.CreateObject, create));

            Csla.Rules.BusinessRules.AddRule(typeof(Benutzer), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.GetObject, read));

            Csla.Rules.BusinessRules.AddRule(typeof(Benutzer), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.EditObject, update));

            Csla.Rules.BusinessRules.AddRule(typeof(Benutzer), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.DeleteObject, delete));
        }

Here I'm checking if the the user has permission...

if (Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.CreateObject, typeof(Business.Benutzer)))

This returns always true. If I use for example "Admin" instead auf my "create-List" object, it will work. Do you have any suggestions for me?

Kind regards

Kevin

BruderKotlett replied on Tuesday, July 05, 2011

Ok. I got it :-)

My List<string> object count was 0, so the permission was always set to true.

Now I'm checking the list count and if it's 0 I'm adding a empty string.

Copyright (c) Marimer LLC