Custom Workflow for content silos
Wondering if anyone has done anything like this:
1) I'd like to able to restrict a workflow to a section within the website:
Let's say i have 3 sections within my site, each with child sections. I have 3 groups of 6 groups of users: a group of content AUTHORS and content APPROVERS for each section. Each section has specific permissions on it to only allow editing by authors and approvers of that section.
I'd like this separation to also carry over to the workflow. Currently, when an author from any section sends an page for approval, the approvers from every section are notified.
2) I'd like to customize the NotifyGroup message to something more useful then "You have new items waiting approval."
I've been able integrate "PagesApprovalWorkflow.xamlx" into my project, modify it by following this post:
http://www.sitefinity.com/documentation/documentationarticles/developers-guide/sitefinity-essentials/modules/workflow-for-content-modules/custom-workflow as a test.
but I'm wondering if anyone has accomplished the goals i have described above?
1) Basically to be able to do this you should use customized workflows and most probably replace our GuardActivity with your custom GuardActivity. Our guard workflow activity is generally blocking access to actions based on whether a user is in a role associated with the approves or publishers workflow groups.
You can make your own logic there and throw WorkflowSecurityException if the conditions are not met. The downside of this approach is that our workflow menu rendering will not recognize your activity, so each user will see all the action buttons (DecisionActivities) that are possible for the current workflow status.
Once they click them they will receive the warning message that they are not allowed to say Approve this page etc.
Let's take pages for example:
My opinion is that the easiest way to do this is to use a Role naming convention.
For example create some roles named “WorkFlow-Courts”, “Workflow-TakingAction”, “Workflow-CurrentBusiness”.
Assign the respective users to these roles.
In your custom guard activity first check what the current page parent group is. If you have nested hierarchy you have to traverse the ancestors of the page node to find the group if not directly get PageNode.Parent.
Once you have the name of the group try to get the user roles for the user and check if the user has a role for this page group.
Please find below a sample guard activity that can be used. Replace our GuardActivity in your customized PagesApprovalWorkflow.xamlx your custom activity.
If your are going to have one level of approval – you can use just the StandardOneLevel approval flowchart and remove the Switch and the other flowcharts.Please be aware that if you assign a role to a user the user first has to sign out and sign in – in order to receive this role
Were you able to get this functionality working? If so, do you have any code samples that you could share? I'm having the same type of issue. I need to have authors and approvers for departments. Let's say HR, Sales and IT. For example, HR authors can create pages in the HR section that can only be approved by HR approvers.
Another question I have is whether I can avoid creating a custom workflow by using the sync tool. If I create hr.mydomain.com and only allow hr users to author/approve content there, sales.mydomain.com and allow sales users to author/approve content there to be pushed to a production site that includes all sections, is this a realistic approach to handling this issue?
We also have this exact same requirement. We will have various blogs on our site, each maintained by a different division within our company. For each blog, we may have different sets of approvers/publishers. Since workflows only apply to Blogs overall (you can't tell it to apply only to one particular blog, for example), we are stuck with adding all possible approvers to our workflow, and then using blog-level permissions to only allow the particular set of approvers to actually be able to approve/publish blog posts for their division. This works for the most part, but all of the approvers get the notification email, regardless of whether or not they actually have permission to approve that particular blog post.
In addition, we may have the need for additional levels of approval (beyond the 2 that come out of the box). There has even been talk within our company of allowing one approver to decide "hey, this needs to also be routed to groups A, B, and C, for further approval", and therefore essentially dynamically choosing which other approvers might also need to see the content before publishing it.
It seems as if customizing workflows for Sitefinity is quite difficult. Are there future plans to make workflows within Sitefinity more robust out-of-the-box for more enterprise-level content authoring/approving needs?
We had also thought of the possibility of setting up multiple Sitefinity instances, one for each division, and then bringing together the content via the SiteSync tool, or via RSS feeds. Although that seems to be a bit cumbersome, especially when it comes to the need to upgrade all of those individual instances and keep them in sync.
Any guidance for us enterprise-level customers looking for more advanced workflow scenarios would be very much appreciated!
At the current moments there are no plans to extend the workflows, I suppose you mean having a workflow editing tool that will allow workflow customizations to be made directly from sitefintiy backend applying changes instantly. The development team is aware of the benefits from having such feature, but for the time beeing this is not available and yet no plans are made towards this functionality.
Editing sitefintiy workflow and substituting it with custom workflow utilizing activitiy classes developed for specific purposes requires approach one described below, following windows workflow like development fixing the moving parts in the workflow designers with custom activity classes and sitefinity professional editions (custom workflow is available for sitefinity proessional and enterprise editions).
Sitefintiy have its own activity classes to handle the workflow in sitefintiy context and work with its data types and I think after a while in dealing with the activities and the worklfow designer one can deal with ease in implementing customizations to workflows.
Concerning having more than 2 level approavl workflow, the 2 level appraoval workflow when the item is passed trough second level workflow returns the item passed trough workflow with status Published, if the second level approval worklow is modified to return the item as awaiting further approval it will pass trough workflow again The implications come from the fast this is not available out of the box as in Administration->Worklfow there is no option to have third level approver.
the Telerik team
Thanks for the suggestions. I have spent some time really digging into how the workflows work out of the box, and I'm getting more comfortable with them. One thing we'd really like to do is set up the workflow so that different blogs have different groups of people set up as approvers/publishers. The approach I was thinking of going with was creating a couple new custom permissions (under Advanced Settings -> Blogs -> Permissions -> BlogPost -> Actions), which would then allow us to assign roles to these new permissions on each blog. Then, I was planning on modifying the GuardActivity to look for these new permissions at the blog/content level, instead of or in addition to checking the permissions at the workflow level. When digging into this, I discovered that there is already a ContentPermissions property of the GuardActivity. I tried adding my new permission to this property (in the format "BlogPost.ApproveBlogPost"), but it doesn't seem to be working correctly. When I used Reflector to look at the GuardActivity code, it looks like it calls off to a securedContent.IsGranted method, but it doesn't actually use the results of that method to stop the user from going forward with that operation. And, even if it did, it looks like the code that inspects the workflow to build up the UI of allowed operations wouldn't honor this ContentPermissions property either, as it looks specifically only at the WorkflowPermissions property (this is inside the FlowchartWorkflowInspector.CanPassGuard method).
I plan on inheriting from the GuardActivity class, and in my version, actually check the ContentPermissions and stop the user from doing something they don't have permission to do, but I can't see a way to create my own implementation of a CanPassGuard method to also check this (there isn't an interface or anything that would allow me to plug in an alternative implementation). Is there a way this can be done? Or could Telerik implement this as a fix in a future version?
Finally, I'm also planning on inheriting from the NotifyGroup activity so that we only send the "You have content to approve" emails to the people who actually have the permission to do so (based on my new BlogPost.ApproveBlogPost permission). I believe that should be pretty straight forward.
Does this approach sound reasonable?
Oh, one more item: I noticed that sf_workflow_scope table has a column named content_filter_expression, which sounds like it might be able to be used to filter the workflow scope down to, say, a particular blog or via some other criteria. Is that actually implemented, and if so, what sort of syntax could we use in there?
I must say this conversion is really interesting... We have been working with Workflows for the first time and I'd love to know more about what can be done with the customization of the Sitefinity workflows. Did you get any response or did you have any success with this Andy?
We haven't heard much on this back from Telerik. However, we've had some success going our own way with a few customizations to the workflow logic. This is what we wanted to accomplish:
1. Each blog or list should have its own set of people who act as authors, approvers, and publishers (we are using the 2-step workflow).
2. Only the approvers or publishers configured for a given blog/list should get a notification email if some content is requiring their review.
3. If someone outside the configured set of authors, approvers, or publishers for a given blog or list attempts to author, approve, or publish content in that blog/list, they should be prevented from doing so.
Unfortunately, the built-in workflow functionality in Sitefinity only gives you a broad way to configure a set of approvers and publishers for blogs or lists overall... with no way to have separate sets of people for each individual blog or list. (It does allow you to have different sets of authors, however, through the use of permissions on each blog or list).
So, we realized that if authors could be set independently on each blog/list by using permissions, then perhaps we could create some custom permissions to do the same for approvers and publishers. So this is what we did:
1. We created custom "ApproveListItem", "PublishListItem", "ApproveBlogPost", and "PublishBlogPost" permissions. This can be done via the advanced settings UI, or simply by adding some stuff to the ListsConfig.config and BlogsConfig.config files. Here's what's inside our BlogsConfig.config file, for example:
<add title="Approve Blog Post As Editor (Workflow Step 1)" type="None" name="ApproveBlogPost" />
<add title="Publish Blog Post (Workflow Step 2)" type="None" name="PublishBlogPost" />
2. Once these custom permissions are created, it's an easy matter of using the backend UI to set up what groups and/or users have each permission, per blog or list. We also needed to ensure that the users/groups who had the new Approve and Publish permissions also had the "Update this blog and manage its blog posts" permission.
3. Of course, we now needed a way to get the system to actually use these permissions somehow... this is where things got a little tricky. What we ended up doing is creating some custom Activities to plug into the Windows Workflow Foundation (xamlx) files. We created two classes:
a. CustomEmailNotifyGroup, which inherits Telerik.Sitefinity.Workflows.Activities.NotifyGroup, and overrides the GetEmails function so that it only gets emails for people who have the Approve or Publish permission. I put the code for this class at the bottom of this post.
b. CustomWorkflowGuard, which inherits System.Activities.CodeActivity. This activity is responsible for ensuring that the user has permission to do whatever the activity is that they are trying to do (approve or publish). We tried inheriting from Telerik.Sitefinity.Workflow.Activities.GuardActivity, thinking that we could just change the logic inside the existing acitivity that was already being used by the workflows. However, we ran into problems because unfortunately, that type is specifically being checked for inside Telerik.Sitefinity.Workflow.FlowchartWorkflowInspector.GetVisualDecisions, via this line of code: if (activity.GetType() == typeof(GuardActivity)) (this is a bad, bad practice, in my opinion, in regards to customizability of the software). So, instead, we decided to create a separate activity to do the additional checking that we required. We inserted this activity immediately after the DecisionActivity for the various paths through the workflow. You can find the code for this class at the bottom of this post.
4. We enabled the 2-level workflow for the Blog and List content types. Within the configuration of this workflow, we added the entire set of all users/groups that could act as Approvers or Publishers.
Now, the one issue we still have with this approach is that, since we weren't able to inherit from the existing GuardActivity, the backend will give the user options to do things that they might not actually have permission to do. However, once they try to do it, they'll get caught by our CustomWorkflowGuard and be prevented from actually accomplishing it. Not ideal, but good enough for us.
We really do hope that a future version of Sitefinity would introduce some more robust Workflow customization options. It's the one major area of Sitefinity that we feel is lacking, especially for trying to use it in an enterprise environment.
Thank you very much for taking the time to explain and include the code that you used for this. I have a similar challenge, and the information you provided is really helpful.