Custom Access Rights and Workflow Commands

 

So one of my clients had a specific need to allow a specific subset of users to be able to publish stuff directly to the web, bypassing the workflow.  Sounds easy?  Here’s the specifics of their needs:

  • They only have 1 workflow in place for all site(s).
  • Content templates are varied and do not necessarily inherit from a specific template
  • They need to have only some users bypass the workflow only on some items while other items they should only have their regular permissions.
  • The workflow in place is a simple “Editing –  Approval  – Published” 3 step workflow.
  • There is a very large amount of existing content all over a very large site which any major change could potentially have an impact on.
  • The developers for the site are in China and the client is a site admin out of New York with no access at all to the file system or server.

So… here’s my thought process:

This was actually a lot trickier than I had first expected and in digging in to things, I found that there were hidden levels of complexity with the particulars of the solution that I didn’t expect.  Basically I tried to find a way to do this strictly on the front end without the need to add any custom code.  There was just no way that I could think of to do this on the front end only without a risk to the current solution.   I actually tried multiple approaches to find a way to implement this that wouldn’t require access to the backend.

Second Workflow?

This is complex.  There is existing content already published using their main workflow.  New versions of this content would need to use the new workflow.  New versions of the content would ONLY need to use this workflow for some users and not others.  The content template was not the same across the board for their needs. Not only would we need to get the existing content moved to the new workflow, but we’d need to work out some logic to assure that a subset of all newly created items would use the new workflow and override standard values for only a specific group.  This would work, but it’s a potentially complex solution to implement, would require a lot of custom coding and would potentially be difficult to maintain.

Create New Templates?

This assumes that the content in question lives in a single folder.  Another option would be to create a template that inherits from the current template(s) and set the workflow on standard values.  This could mean multiple new templates that need to be created (the folder would have to be inventoried to make sure which ones), but more importantly, it would require changing the template on existing content, potentially breaking it in the process.  This approach, I think is very clunky and would also be difficult to maintain.

Custom Access Right!! 

What I came up with instead is a way to alter the existing workflow to simply add another command that in addition to the “Submit” the appropriate users would also see a “Direct Publish” command along with the “Submit” command.  The new command sets the next state to be “Approved” instead of “Waiting Approval” and proceeds through the workflow as usual to the normal “approved” state.  Since the Approved state has an autopublish action on it, they simply need to get it to the approved state and the workflow does it’s thing.

To control access to this command, we would create a role(s) and then grant only that role the Workflow Command Execute right.  The tricky part of that, however, is to limit when that command is available since that should only be an option on certain items.  The easiest way to do that is to create a new access right, configure which items would have the option to set the right on it (such as by setting a “root” item and then it inherits down to its descendants allowing that right in the security editor for the specific role.  This result is that the only the items specified can have the right set and any other items that it’s not set on or not allowed, will not give access to this additional command.  This approach is completely flexible, it’s extendable to add other subsets of items to have this same permission, and its controlled via standard Sitecore security.

Code now please?

First.. you need to have the access right.  It must inherit from AccessRight

public class DirectPublishAccessRight : AccessRight
 {
public DirectPublishAccessRight(string name) : base(name) { }
public static AccessRight DirectPublish { get { return FromName("direct:publish"); } }
 }

Next, I need to hijack the authorization helper for items so that Sitecore knows to check my access right.  Here’s how I did that:

public class DirectPublishAuthorizationHelper : ItemAuthorizationHelper
    {
        protected override AccessResult GetItemAccess(Item item, Account account, AccessRight accessRight, PropagationType propagationType)
        {
            //This method applies the specified AccessRight.           
            var result = base.GetItemAccess(item, account, accessRight, propagationType);

            // First, lets check to see if the result returns back anything or if it's denied, return since we don't need to do anything
            if (result == null || result.Permission != AccessPermission.Allow)
            {
                return result;
            } 

           //  If the access right isn't our new access right, pass it on to be handled by the base object methods.
           //  From here on out, only checks against the direct publish access will get through.
            if (accessRight.Name != "direct:publish")
            {
                return result;
            }

            //  Now, if the access right is not even applicable to the item for this user, return it as not set.  
            if (!AccessRightManager.IsApplicable(accessRight,item))
            {
                return new AccessResult(AccessPermission.NotSet, new AccessExplanation("Access right not applicable", null));
            }

            //  if the access right gets this far, the permission is going to be allowed. 
            var ex = new AccessExplanation("This item can apply the Direct Publish command");
            return new AccessResult(AccessPermission.Allow, ex); 

        }
    }

Now that we have that done, we have to work out exactly how we’re going to get Sitecore to use the helper class we just created. Here’s how we did that:

public class DirectPublishAuthorizationProvider : SqlServerAuthorizationProvider
    {
        public DirectPublishAuthorizationProvider()
        {
            _itemHelper = new DirectPublishAuthorizationHelper();
        }        
        private ItemAuthorizationHelper _itemHelper;
        protected override ItemAuthorizationHelper ItemHelper
        {
            get { return _itemHelper; }
            set { _itemHelper = value; }
        }
    }

Here’s the access right.  Next I’ll add in the Workflow code that I used to be able to take control of the commands that were visible.  Look for the next installment on that soon!

Please let me know if you have any pointers.  This was a real challenge for me and the lack of documentation on this made it a challenge to implement.

 

One thought on “Custom Access Rights and Workflow Commands

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s