Sitecore has a quite advanced access right management system. However, I’ve found a few quite common requirements that, as far as I know, isn’t supported out of the box. One is to allow content authors to remove individual item versions without allowing them to remove the entire item. This is especially useful for multi language sites. Another requirement is to allow authors to delete items they have created themselves, but no other items.
I’ve seen people work around these kind of issues by playing around in the core database, modifying ribbon buttons etc. Personally I don’t like that approach. That would just hide the button and if the user could initiate the command in any other way, Sitecore will gladly perform the delete action. It’s easy to forget a command action in a context menu or something like that.
Instead I created a very small Sitecore module to solve these issues. All the source is available on Github.
Ability to remove item versions
While looking into this, I reflected parts of the Sitecore security model and found that this is already partly implemented. Looking into the
Sitecore.Security.AccessControl.AccessRight class, we’ll see that there is already a hard coded
item:removeversion access right. Looking at the common
Item class, we already have the method
item.Access.CanRemoveVersion(). Looking further into the
QueryState() method of the
DeleteVersion command, I found that it also evaluates using these access rights method.
So far so good. However, the
ItemAuthorizationHelper.GetAccess() that evaluates this, is hard coded to explicitly require item delete access when evaluating the
item:removeversion access right. So by replacing the two default AuthorizationProviders (
BucketAuthorizationProvider), with new ones that uses an overridden version of the
GetAccess() method, we can easily change the behavior of this.
To be able to configure remove version access rights without delete item access rights, we can just add a “Remove version” right to the list of existing rights, like this:
<accessRights> <rights> <add patch:after="add[@name='item:delete']" name="item:removeversion" comment="Remove version right for items." title="Remove version" modifiesData="true" /> </rights> </accessRights>
With this, the access rights will appear in all UI’s, like this:
Ability to remove own items
Allowing authors to delete their own items can be implemented in a similar way. I just added the logic for it in the same overridden
ItemAuthorizationHelper.GetAccess() method. When the method evaluates access rights, its results is “Allow”, “Deny” or “NotSet”. “NotSet” means Deny in practice, but this is very useful in this scenario. If Item Delete access is explicitly set to “Allow” or “Deny”, that setting will rule. But when it evaluates to “NotSet”, I’ll look at the item creator and see if it matches the current user.
One caveat though is that the
CreatedBy field is a versioned field, so I can’t just look at that one. The current author could be the creator of the current language version, but might not have created the item in the first place. So I load all the language versions of the items and use the very first version and compares the current author with the initial creator.
As I mentioned previously, I prefer implementing the functionality close to the core, like this. That way all existing UI’s follows as expected. In the screen shot below, I’ve created two items as the user “test” and allowed the “test” user to remove item versions. On one of the items, I’ve explicitly set the deny delete item access.
Let me know what you think about this. Do you find this to be a common requirement too? Is this a good way of solving it? Should it perhaps go into the product?