CSLA.net 4 Authorization rules delete instance problem

CSLA.net 4 Authorization rules delete instance problem

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


JJLoubser posted on Wednesday, August 18, 2010

Per-type authorization (which is a little different now) where you can ask:

Can the user create an instance of this type? <we can do this one>
Can the user get/fetch an instance of this type? <we can do this one>
Can the user edit/save an instance of this type? <we can do this one>
Can the user delete an instance of this type?
And the new per-instance authorization where you can ask:

Can the user create the instance you already have? (silly, but possible)
Can the user get/fetch the instance you already have? (silly, but possible)
Can the user edit/save this instance?
Can the user delete this instance?  <we want to do this one, but error> <what are we missing?>
 

Our projects Authorization rules work with WriteProperty where we want to disable and enable xaml objects 100%, we just had to play with the rulesets: example 1 see below

now we are trying to use the "per-instance authorization where you can ask. Can the user delete this instance?" my problem is my execute method's context object is null, why? what am I missing? see example 2 see below

example 1:

BusinessRules.AddRule(new AuthorisationPropertyRule(AuthorizationActions.WriteProperty, PresentStatusIDProperty, new List<string> { "IsClosed", "FutureDate" }));

  private class AuthorisationPropertyRule : AuthorizationRule
        {
            private List<string> _ruleSets;

            //Creates an instance of the rule.           
            public AuthorisationPropertyRule(AuthorizationActions action, List<string> ruleSets)
                : base(action)
            {
                _ruleSets = ruleSets;
            }

            /// Creates an instance of the rule.
            public AuthorisationPropertyRule(AuthorizationActions action, Csla.Core.IMemberInfo element, List<string> ruleSets)
                : base(action, element)
            {
                _ruleSets = ruleSets;
            }

            /// Rule implementation.
            protected override void Execute(AuthorizationContext context)
            {
                bool hasPermission = true;
                var target = (RowCallDetailsEC)context.Target;
                //Check all conditions

                if (_ruleSets.Count > 0)
                {
                    foreach (var ruleSet in _ruleSets)
                    {
                        switch (ruleSet)
                        {
                            case "IsClosed":
                                //if (target.IsClosed == true)
                                if (IsClosedConditionBroken(target))
                                    hasPermission = false;
                                break;
                            case "FutureDate":
                                if (IsFutureDateConditionBroken(target))
                                    hasPermission = false;
                                break;
                            case "PresentStatusComment":
                                if (IsCommentConditionBroken(target))
                                    hasPermission = false;
                                break;
                            case "LeaveTypeSet":
                                if (IsLeaveTypeSetConditionBroken(target))
                                    hasPermission = false;
                                break;
                        }


                        if (hasPermission == false)
                            break;
                    }
                }
               
                context.HasPermission = hasPermission;

            }
        }

 

 

example 2:

protected override void AddBusinessRules()
        {

            base.AddBusinessRules();

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

   

        }

 

 public class AuthorisationCanRemoveObjectRule : AuthorizationRule
        {
            private List<string> _ruleSets;
            private CompanyGroupEC _instance;

            //Creates an instance of the rule.           
            public AuthorisationCanRemoveObjectRule(AuthorizationActions action, List<string> ruleSets)
                : base(action)
            {
                _ruleSets = ruleSets;
                _instance = null;
            }

            /// Creates an instance of the rule.
            public AuthorisationCanRemoveObjectRule(AuthorizationActions action, CompanyGroupEC instance, List<string> ruleSets)
                : base(action)
            {
                _ruleSets = ruleSets;
                _instance = instance;
            }

            /// Rule implementation.
            protected override void Execute(AuthorizationContext context)
            {
                bool hasPermission = true;
                var target = (CompanyGroupEC)context.Target; //is null
                //var ptarget = _instance; is null
                //var ptarget = this.Element; is null

                try
                {
                    if (target.haveChildren)
                        hasPermission = false;
                }
                catch (Exception eeee) { }
                

                context.HasPermission = hasPermission;

            }
        }

 

// BusinessRules.CheckRules(); is in the other partial class

 

 

Question 2: When will the CSLA.net 4 videos be online and examples?

RockfordLhotka replied on Wednesday, August 18, 2010

You are saying that context is null? Or that context.Target is null?

The Target property isn't always available, because there isn't aways an object instance.

For create, fetch and immediate delete operations there is no business object - so there's no way to provide a Target value.

For execute, insert, update and deferred delete operations there is a business object, so there should be a Target value. If you are doing one of these operations and you aren't seeing a Target value, that may be a bug in CSLA.

jjloubser@symbioses.co.za replied on Tuesday, September 21, 2010

"For execute, insert, update and deferred delete operations there is a business object, so there should be a Target value. If you are doing one of these operations and you aren't seeing a Target value, that may be a bug in CSLA."

I have a list of objects: TestERL<BusinessListBase> with TestER<BusinessBase>'s

in ViewModel

public void RemoveInstance(Object sender, EventArgs e) //testing method binded to a trigger action binded to a button in the xaml
        {

                Csla.Xaml.TriggerAction TriggerAction_ = (Csla.Xaml.TriggerAction)sender;
                StackPanel stack_ = (StackPanel)TriggerAction_.Tag;


                TestER TestER_ = (TestER)stack_.DataContext;
                TestERL TestERL_ = (TestERL)Model;
                TestERL_.Remove(TestER_);

       }

When  TestERL_.Remove(TestER_); it executes:

protected override void Execute(AuthorizationContext context)
            {
                bool hasPermission = true;
                try
                {
                    TestER target = (TestER)context.Target;
                                      if (target != null)
                    {
                        if (target.ValueA == 1)
                            hasPermission = false;
                    }

                }
                catch (Exception eeee) { }


                context.HasPermission = hasPermission;

            }

target is always null ; why? is it a bug?

Ive tried these posts not working or do not give me enough information on delete instance or maybe I read something missing: :-)

http://forums.lhotka.net/forums/p/9373/44440.aspx //feedback: I do not use system role sets, but we use the role sets like he use it. 

 http://forums.lhotka.net/forums/p/9019/42914.aspx //feedback: my xaml do not display the data if i use this:

//protected static void AddObjectAuthorizationRules() //xaml not displaying
        //{
        //    //// per-type/per-instance rules go here

        //    //BusinessRules.AddRule(typeof(TestER),new AuthorisationCanRemoveObjectRule(AuthorizationActions.DeleteObject, new List<string> { "All" }));

        //}

this works better for delete instance, but the context is always null:

protected override void AddBusinessRules()
        {
            //// per-property and per-method rules go here

            base.AddBusinessRules();

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


        }

 

//public class AuthorisationCanRemoveObjectRule : Csla.Rules.BusinessRule // not working
        public class AuthorisationCanRemoveObjectRule : AuthorizationRule
        {
            private List<string> _ruleSets; //Roles
            //private List<string> _SysRuleSets; //SysRoles
            //private TestER _instance;

           

            //Creates an instance of the rule.           
            public AuthorisationCanRemoveObjectRule(AuthorizationActions action, List<string> ruleSets)
                : base(action)
            {
                _ruleSets = ruleSets;
                //_instance = new TestER();
            }

            ///// Creates an instance of the rule.
            //public AuthorisationCanRemoveObjectRule(Type type_ ,AuthorizationActions action, TestER instance, List<string> ruleSets)
            //    : base(action)
            //{
                
            //    _ruleSets = ruleSets;
            //    _instance = instance;
            //}

            /// Rule implementation.
            protected override void Execute(AuthorizationContext context)
            {
               

                bool hasPermission = true;
                try
                {
                    TestER target = (TestER)context.Target;
                    //var ptarget = _instance;
                    //var ptarget = this.Element;

                    if (target != null)
                    {
                        if (target.ValueA == 1)
                            hasPermission = false;
                    }

                }
                catch (Exception eeee) { }


                context.HasPermission = hasPermission;

            }
        }

 

 

 

RockfordLhotka replied on Tuesday, September 21, 2010

I don't think that BusinessListBase checks any authorization rules when Remove() is called to remove a child object.

You are saying that you have an authorization rule that is running when you call Remove()? What runs that rule?

JJLoubser replied on Wednesday, September 22, 2010

its running by itself after I call parent.remove(child); the Authorization Rules is set on the child not on the parent.

JJLoubser replied on Monday, September 27, 2010

its running by itself after I call parent.remove(child); the Authorization Rules is set on the child not on the parent.

JJLoubser replied on Monday, September 27, 2010

Don't i miss a dataAnnotation or a Using or a IF_SILVERLIGHT code?

RockfordLhotka replied on Thursday, September 30, 2010

I am trying to replicate what you are seeing. I really don't see anywhere in CSLA that an authorization rule is called on a child object when that object is removed from a BusinessListBase. To confirm this, I added a unit test:

    [TestMethod]
    public void AuthorizeRemoveFromList()
    {
      var root = new RootList();
      root.RemoveAt(0);
    }
 

  [Serializable]
  public class RootList : BusinessListBase<RootListChildItem>
  {
    public RootList()
    {
      RaiseListChangedEvents = false;
      Add(Csla.DataPortal.CreateChild<ChildItem>());
      RaiseListChangedEvents = true;
    }
  }

  [Serializable]
  public class ChildItem : BusinessBase<ChildItem>
  {
    protected override void AddBusinessRules()
    {
      base.AddBusinessRules();
      BusinessRules.AddRule(new NoAuth(AuthorizationActions.DeleteObject));
    }

    private class NoAuth : Csla.Rules.AuthorizationRule
    {
      public NoAuth(AuthorizationActions action)
        : base(action)
      {}

      protected override void Execute(AuthorizationContext context)
      {
        context.HasPermission = false;
      }
    }
  }

The NoAuth rule is never invoked. At no point does its Execute() method get called. Which is exactly what I expected to happen, because no authz rules are run when a child object is removed from a BusinessListBase.

JJLoubser replied on Friday, November 05, 2010

how can I send my project code to you? Will you compile it to see it happen?

The xaml "remove button" trigger the viewmodel function: "void RemoveInstance" it run this code in the function:

                TestER TestER_ = (TestER)stack_.DataContext;       //TestER BusinessBase class
                TestERL TestERL_ = (TestERL)Model;                         //TestERL BusinessListBase class
                TestERL_.Remove(TestER_);

 the TestERL_.Remove(TestER_) run the execute function of the Auth Rule:

 public AuthorisationCanRemoveObjectRule...

the target is null, big problem?

you need to create a businessbase and its parent businessListbase class, you need to create its xaml and viewmodel with bxf navigation and the button and function I specify above.

JJLoubser replied on Friday, April 15, 2011

I read your book Using CSLA 4: Creating Business Objects: answer:

implement own Auth rule and use Csla.Rules.BusinessRules.HasPermission method and add instance of object in there for context not to be null when it do the execute of the method...

BI object:

public bool CanCreate
        {
            get
            {
               
                if (AppUser.IsRoleDeveloper)
                    return true;
                else if (IsSystemRole == true)
                    return false;
                else
                    return true;


            }
        }

        public bool CanDelete
        {
            get
            {
               
                if (AppUser.IsRoleDeveloper)
                    return true;
                else if (IsSystemRole == true)
                    return false;
                else
                    return true;

             
            }
        }


        public class MyAuthorizationRuleDelete : Csla.Rules.AuthorizationRule
        {
            private List<string> _roles;

            public MyAuthorizationRuleDelete(Csla.Rules.AuthorizationActions action, Csla.Core.IMemberInfo element, List<string> pRoles)
                : base(action, element)
            {
                _roles = pRoles;
            }


            protected override void Execute(Csla.Rules.AuthorizationContext context)
            {
                UserSecurityEC userSecurity = (UserSecurityEC)context.Target;
                bool hasPermission = true;
                if (userSecurity != null)
                    hasPermission = userSecurity.CanDelete;


                if (hasPermission)
                {
                    foreach (var item in _roles)
                        if (Csla.ApplicationContext.User.IsInRole(item.ToString()))
                        {
                            context.HasPermission = true;
                            break;
                        }
                }
                else
                    context.HasPermission = hasPermission;

            }
        }

        public class MyAuthorizationRuleCreate : Csla.Rules.AuthorizationRule
        {
            private List<string> _roles;

            public MyAuthorizationRuleCreate(Csla.Rules.AuthorizationActions action, Csla.Core.IMemberInfo element, List<string> pRoles)
                : base(action, element)
            {
                _roles = pRoles;
            }

            protected override void Execute(Csla.Rules.AuthorizationContext context)
            {
                UserSecurityEC userSecurity = (UserSecurityEC)context.Target;
                bool hasPermission = true;
                if (userSecurity != null)
                    hasPermission = userSecurity.CanCreate;

                if (hasPermission)
                {
                    foreach (var item in _roles)
                        if (Csla.ApplicationContext.User.IsInRole(item.ToString()))
                        {
                            context.HasPermission = true;
                            break;
                        }
                }
                else
                    context.HasPermission = hasPermission;


            }
        }

#if SILVERLIGHT
        public static void AddObjectAuthorizationRules()
        {
            Csla.Rules.BusinessRules.AddRule(typeof(UserSecurityEC), new MyAuthorizationRuleCreate(Csla.Rules.AuthorizationActions.EditObject, null, new List<string> { "Developer", "Company Administrator" }));
            Csla.Rules.BusinessRules.AddRule(typeof(UserSecurityEC), new MyAuthorizationRuleDelete(Csla.Rules.AuthorizationActions.DeleteObject, null, new List<string> { "Developer", "Company Administrator" }));
        }

#else



#endif


viewModel or code-behind:

UserSecurityEC pop = (UserSecurityEC)ListItem.SelectedItem;
                if (pop != null)
                {

                    Type sourceType = typeof(UserSecurityEC);
                    bool returnValue = (Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.DeleteObject, pop));

                    if (returnValue)
                        menuItems.Add(new ContextMenuItem("RemoveSecurityRoleUsed", "Remove Security Role - " + pop.SecurityRole, true));
                    else
                        menuItems.Add(new ContextMenuItem("RemoveSecurityRoleUsed", "Remove Security Role - " + pop.SecurityRole, false)); //cannot remove it yes ha ha
...

 

Copyright (c) Marimer LLC