Add / Remove collection items authorization rule.

Add / Remove collection items authorization rule.

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


rxelizondo posted on Monday, June 27, 2011

Hello,

I am trying to limit the ability to add / remove collection items to certain users. Ideally, I was looking for something quick and simple like:

BusinessRules.AddRule(new IsInRole(AuthorizationActions.AddChild, SomeCollectionProperty, “Supervisor”));

Such feature does not appear to exist however and something tells me there is a good reason for it so I am curious.

As of right now, I am thinking of creating my own authorization rule, subscribe to the CollectionChanged event of the collection and call the rule every time the CollectionChanged event fires.

I am sure there is better ways of doing this so I appreciate your feedback.

Thanks.

JonnyBee replied on Monday, June 27, 2011

In terms of encapsulation - I'd rather implement these checks in the ChildObject to check that the user has permission to create/delete object and a corresponding static authorization rule. (this would also work nicely with the Csla.Xaml.ViewModel).

For child objects you need to enforce the rule in your own code (authz rules is only enforced by the "root" DataPortal).

Another possibility is to use the RegisterMethod (similar to RegisterProperty but for a method) for a "custom" CreateChild method and add authorization+checks to that method.

rxelizondo replied on Tuesday, June 28, 2011

 

Thanks for you feedback guys, I really appreciate it.

JonnyBee

In terms of encapsulation - I'd rather implement these checks in the ChildObject to check that the user has permission to create/delete object and a corresponding static authorization rule. (this would also work nicely with the Csla.Xaml.ViewModel).

 

I understand your point about encapsulation but I see things differently. Needless to say, 99.9% of the population (including Rocky) probably won’t agree with my way of thinking but…Surprise

For the most part (not talking about corner cases here), in my world, broken rules and authorization rules should be enforced on the object that is ultimately responsible for enforcing such rule. In the case of children on a collection, it is the collection the one that has the ultimate say on whether a child is allowed to be added or deleted to it.

I realize that the child could impose rules on itself to prevent itself from being created, edited or deleted and that is fine. But no matter what kind of fight the child puts on, if the collection says that the child will not be added or deleted to it, then it won’t be and that is final. I know all this is philosophical garbage but that is just my opinion Smile

So in a way, I kind of like Tiago approach better except that collection object are somewhat treated as a second class citizens in the CSLA (such as they don’t have a broken rule collection etc), So I end up enforcing the rule on the parent object of the collection, not because I want to do that but because I have no other choice, at least not without adding significant work to me.

I am curious however about the “this would also work nicely with the Csla.Xaml.ViewModel”, I am not familiar with that (too much corporate Unix, Java, Flex, Mainframe in my life not much experience with MVVM). Do you think that if I was to go my way this will create havoc with the Csla.Xaml.ViewModel if I end up using it?

Thanks.

 

JonnyBee replied on Tuesday, June 28, 2011

Csla.Xaml.ViewModel has "meta" data based properties for the item type of a List, such as:

CanAddNew
CanRemove

And for the actual model object as well:

CanSave
CanCancel
CanDelete
CanFetch
 

if (Csla.Rules.BusinessRules.HasPermission(Rules.AuthorizationActions.DeleteObject, itemType) && list.Count > 0 && !isObjectBusy)
   CanRemove = true;
else
   CanRemove = false;
 
if (Csla.Rules.BusinessRules.HasPermission(Rules.AuthorizationActions.CreateObject, itemType) && !isObjectBusy)
   CanAddNew = true;
else
   CanAddNew = false

So as you can see - for a list the ViewModel knows the item type and has properties (with PropertyChanged events) so that you can use them for databinding on f.ex Enabled property of buttons.

rxelizondo replied on Wednesday, June 29, 2011

 

I see, thank for the help Jonny.

By the way, I was not being clear on my original question. I don't have a root collection object, I have business base root object instead (parent -> collection -> child).

What I want to do is to prevent add / delete on the collection object (a child of the root object in my case). I realize that you suggestion still apply, just wanted to clarify my original question.

Thanks for your time.


tiago replied on Monday, June 27, 2011

One solution is do it like Jonny says. The other is check at the collection level the add / remove authorization.

/// <summary>
/// Adds a new <see cref="DocFolder"/> object to the DocFolderColl collection.
/// </summary>
/// <param name="item">The item to add.</param>
/// <exception cref="System.Security.SecurityException">if the user isn't authorized to add items to the collection.</exception>
public new void Add(DocFolder item)
{
    if (!CanAddObject())
        throw new System.Security.SecurityException("User not authorized to create a DocFolder.");
 
    base.Add(item);
}
 
/// <summary>
/// Removes a <see cref="DocFolder"/> object from the DocFolderColl collection.
/// </summary>
/// <param name="item">The item to remove.</param>
/// <returns><c>true</c> if the item was removed from the collection, otherwise <c>false</c>.</returns>
/// <exception cref="System.Security.SecurityException">if the user isn't authorized to remove items from the collection.</exception>
public new bool Remove(DocFolder item)
{
    if (!CanDeleteObject())
        throw new System.Security.SecurityException("User not authorized to remove a DocFolder.");
 
    return base.Remove(item);
}

 ...

/// <summary>
/// Adds the object authorization rules.
/// </summary>
protected static void AddObjectAuthorizationRules()
{
    BusinessRules.AddRule(typeof(DocFolderColl), new IsInRole(AuthorizationActions.CreateObject"Archivist"));
    BusinessRules.AddRule(typeof(DocFolderColl), new IsInRole(AuthorizationActions.DeleteObject"Admin""Manager"));
}
 
/// <summary>
/// Checks if the current user can create a new DocFolderColl object.
/// </summary>
/// <returns><c>true</c> if the user can create a new object; otherwise, <c>false</c>.</returns>
public static bool CanAddObject()
{
    return Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.CreateObjecttypeof(DocFolderColl));
}
 
/// <summary>
/// Checks if the current user can delete a DocFolderColl object.
/// </summary>
/// <returns><c>true</c> if the user can delete the object; otherwise, <c>false</c>.</returns>
public static bool CanDeleteObject()
{
    return Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.DeleteObjecttypeof(DocFolderColl));
}  

Anyway keep in mind authorization is checked by Csla only on DataPortal calls.

JonnyBee replied on Tuesday, June 28, 2011

Hi Tiago,

I am not quite comfortable with your sample code in that it mixes the

Example: If the collection is a "root" object the DataPortal will NOT allow Create or Delete of the list object.

I'd still prefer to have the Authz rules on the Child type and you could just as easily have the list object check permissions on the child type.

/// <summary>
/// Checks if the current user can create a new DocFolder item object.
/// </summary>
/// <returns><c>true</c> if the user can create a new object; otherwise, <c>false</c>.</returns>
public static bool CanAddObject()
{
    return Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.CreateObject
typeof(DocFolder)); } /// <summary> /// Checks if the current user can delete a DocFolder item object. /// </summary> /// <returns><c>true</c> if the user can delete the object; otherwise, <c>false</c>.</returns> public static bool CanDeleteObject() {     return Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.DeleteObject
typeof(DocFolder)); }

tiago replied on Friday, July 01, 2011

JonnyBee

Hi Tiago,

I am not quite comfortable with your sample code in that it mixes the

Hi Jonny,

While re-doing that part for CslaGenFork templates I was faced with the decision of how to control the Add/Remove authorization.

There are a lot of possibilities here and there is also this edge situation here role AAA can do whatever he wants to the collection but can do nothing at all to the collection items.

Let's discuss a bit the exact meaning of AuthrizationActions, first at the collection level

CreateObject - create a collection 
GetObject - read the collection (meaning get the collection items)
EditObject - edit a collection looks like adding or removing collection items, since there is nothing more to do to a Csla collection object
DeleteObject - delete the collection, anf thus removing/deleting all items of the collection, 

Now let's take a look at the collection items level

CreateObject - I can create an item, but what's that good for if I can't add it to the collection? It looks I also need EditObject at the collection level
GetObject - I can read a collection item. But can I read the collection? If not, how come I am allowed to read a page of a book I'm not aloowed to read
EditObject - I can edit (change) an item properties, this is fine even if I can't read collection items (GetObject at the collection level)
DeleteObject - delete a collection item (idem) 

So... this isn't an easy issue. I'm not re-evaluating the solution I adopted in CslaGenFork, but may be it needs to be re-evaluated.

The fact is certain combinations don't make sense.

1) The GetObject AuthorizationAction should always be the same at the collection and item levels or else there is a potential for weirdness (read bugs you loose hours to try to explain to your users).

2) The DeleteObject AuthorizationAction for collections should imply DeleteObject for items but noit vice versa.

3) The CreateObject and DeleteObject for items should imply EditObject for collection but noit vice versa.

And that's about all that should be enforced.

Please comments.

Copyright (c) Marimer LLC