Send Sitecore workflows notifications to users based on Sitecore roles

In many Sitecore solutions, there are different areas, where different editors and publishers maintains content in their respective areas. Sometimes these areas overlap.

In this blog post I will give an example of how to send workflow notifications to the different publishers and editors without being restricted to where in the structure the item is created/edited.

Creating a connection to roles and the Sitecore item

I created a droplink field on the Sitecore items which use workflows so we can connect this item to the corresponding roles.
The droplink is populated based on a data folder with items that has the Roles specified.

In this example, I have a Publisher Role and an Editor Role, where access rights to workflow commands and other Sitecore roles has been added.
The owner roles (owner publisher and owner editor) will inherit from these roles. the owner roles are primarily used to control which users should get notifications in this example, I also use, the owner set on the item to control access rights programmatically but I won't cover this in this blog post.

Since the publishers and editors will be given different roles we can on item creation set this droplink field programmatically based on their role:
public void OnItemCreated(object sender, EventArgs args)
{
User currentUser = Sitecore.Context.User;
if (currentUser.IsInRole("sitecore\\Mysite Publisher") ||
currentUser.IsInRole("sitecore\\Mysite Editor"))//if the users are ourside of these roles we cannot set the owner programatically
{
var createdArgs = Event.ExtractParameter(args, 0) as ItemCreatedEventArgs;
Item owner = null;
string userRole = "";
Assert.IsNotNull(createdArgs, "args");
if (createdArgs != null)
{
Assert.IsNotNull(createdArgs.Item, "item");
if (createdArgs.Item != null)
{
Item currentItem = createdArgs.Item;
currentItem.Editing.BeginEdit();
try
{
Item ownersRoot = SiteConfiguration.GetOwnersRootItem();//Helper class to get the root datafolder for Owners
foreach (Item ownerItem in ownersRoot.Children)
{
foreach (Role role in currentUser.Roles)
{
if (role.LocalName == ownerItem["Publisher Role"])//Since some publishers also could create items
{
owner = ownerItem;
}
if (role.LocalName == ownerItem["Editor Role"])
{
owner = ownerItem;
}
}
}
if (owner != null)
{
if (currentItem.Fields != null && currentItem.Fields["Owner"] != null)
{
currentItem.Fields["Owner"].Value = owner.ID.ToString();//sets the field to the correct Item ID
}
}
}
finally
{
currentItem.Editing.EndEdit();
}
}
}
}
}

Creating worflow notification on Submit

On the submit command I created an action NotifyOnSubmit, here I send an email to all the publishers who has the corresponding role as the owner of the item. I could have used the current role of the logged in user, but this was not always the correct action when I created this logic. for another solution that would probably be a better approach
public class NotifySubmit
{
public void Process(WorkflowPipelineArgs args)
{
var contentItem = args.DataItem;
var currentUser = Sitecore.Context.User;
Item ownersRoot = SiteConfiguration.GetOwnerssRootItem();//gets the root item of owners so we can traverse it later
var comment = args.CommentFields.Values.ElementAt(0);//gets the comment add this to the email
//############## Build you Email content #######################333
// to use the send mail code below you should add emailbody, fromemail and subject
//I would recommend to add direct links to content editor/experience editor
// /sitecore/shell/Applications/Content Editor.aspx?fo= + contentItem.ID
// /?sc_mode=edit&sc_itemid=" + contentItem.ID
Log.Info("NotifySubmit - User request from: " + currentUser.Name, this);
foreach (Item owner in ownersRoot.Children)
{
Role editorRole = Role.FromName(owner["Editor Role"]);
if (currentUser.IsInRole(editorRole))
{
var users = System.Web.Security.Roles.GetUsersInRole(owner["Publisher Role"]);
foreach (var user in users)//we travers all the users who has the correct role and send them an notification email
{
var membershipUser = System.Web.Security.Membership.GetUser(user);
var email = membershipUser.Email;
if (email != null)
{
var emailMessage = new MailMessage(fromEmail, email, subject, emailBody);
emailMessage.IsBodyHtml = true;
MainUtil.SendMail(emailMessage);
Log.Info("NotifySubmit - mail sendt to: " + email, this);
}
}
}
}
}
}
view raw NotifySubmit.cs hosted with ❤ by GitHub

Creating worflow notification on approve

On the awaiting approval command I created an action NotifyOnApprove action. Here we send an email to all the publishers and super administrators in the solution
public void Process(WorkflowPipelineArgs args)
{
var contentItem = args.DataItem;
var currentUser = Sitecore.Context.User;
Item ownersRoot = SiteConfiguration.GetOwnersRootItem();//gets the owner root item
var comment = args.CommentFields.Values.ElementAt(0);
// build the email, you need to add fromadress, emailbody and subject
foreach (Item owner in ownersRoot.Children)
{
var users = System.Web.Security.Roles.GetUsersInRole(owner["Publisher Role"]);//get all users with this role so we can send them notification
foreach (var user in users)
{
var membershipUser = System.Web.Security.Membership.GetUser(user);
var email = membershipUser.Email;
if (email != null)
{
var emailMessage = new MailMessage(fromEmail, email, subject, emailBody);
emailMessage.IsBodyHtml = true;
MainUtil.SendMail(emailMessage);
}
}
}
//We also send notification to all the super administrators
var administratorUsers = System.Web.Security.Roles.GetUsersInRole("sitecore\\MySite SuperAdministrator");
foreach (var user in administratorUsers)
{
var membershipUser = System.Web.Security.Membership.GetUser(user);
var email = membershipUser.Email;
if (email != null)
{
var emailMessage = new MailMessage(fromEmail, email, subject, emailBody);
emailMessage.IsBodyHtml = true;
MainUtil.SendMail(emailMessage);
}
}
}

Creating workflow notification on Reject

On the awaiting approval command I created an action NotifyReject action, Here we collect the last workflow history to get the correct email we should send the reject notification to

public class NotifyReject
{
public void Process(WorkflowPipelineArgs args)
{
var contentItem = args.DataItem;
var currentUser = Sitecore.Context.User;
// build the email, you need to add fromadress, emailbody and subject
var comment = args.CommentFields.Values.ElementAt(0);// gets the last comment
Log.Info("NotifyReject - User rejected change from: " + currentUser.Name, this);
var contentWorkflow = contentItem.Database.WorkflowProvider.GetWorkflow(contentItem);
var contentHistory = contentWorkflow.GetHistory(contentItem);
if (contentHistory.Length > 0)
{
var lastUser = contentHistory.Last().User;
var submittingUser = User.FromName(lastUser, false);
var email = submittingUser.Profile.Email;
var emailMessage = new MailMessage(fromEmail, email, subject, emailBody);
emailMessage.IsBodyHtml = true;
MainUtil.SendMail(emailMessage);
Log.Info("NotifyReject - mail sendt to: " + email, contentItem);
}
}
}
view raw NotifyReject.cs hosted with ❤ by GitHub
Setting the owner field as required

For all templates which have the workflow added, it is required to have the owner set on the Sitecore item for workflow notifications to be sent to the correct users. this is partially covered by setting the owner on item creation, however super admins and developers could be creating content items without these roles. I have set the owner droplink to be required so we do not end up with items with missing owners.

Recommended links to send to the publishers

 /sitecore/shell/Applications/Content Editor.aspx?fo= + contentItem.ID
 /?sc_mode=edit&sc_itemid=" + contentItem.ID

Comments

Popular posts from this blog

Step by step guide to add Glass Mapper to Helix solution

Using interfaces with Glass Mapper

Adding dynamic image source for multi-site solutions with $site$ token and setting dynamic datasource location for components