Use API to get Roles with Page Edit Permission
We have implemented a custom guard activity in our workflow that now has the need to send an email to all the people in a ROLE if that role has permission to edit the page.
I know I can get all of the roles by looking at the RoleManager.GetManager().GetRoles() method -- but we need to see if those roles have permission to edit the current page.
Something like the following:
//Get Current Pagevar item = context.DataContext.GetProperties()["workflowItem"];var page = item.GetValue(context.DataContext) as ISecuredObject;var pageManager = PageManager.GetManager();var node = pageManager.GetPageNode(page.Id);//Get all roles definedvar allRoles = roleManager.GetRoles();//Get all page permissionsvar pagePerms = node.Permissions();string roleName = "";foreach(var role in allRoles) //NEED TO FIGURE OUT IF ROLE HAS EDIT ACCESS TO THE PAGE if (pagePerms.Contains(role) && role.Name.Contains("Editor")) roleName = role.Name; break; //Get all users in the roleList<User> usersInRoles = new List<User>();if (roleManager.RoleExists(roleName)) usersInRoles = roleManager.GetUsersInRole(sRoleName).ToList();Hi Brandon,
Can you please elaborate a bit on the exact use case scenario, as we are not sure we're understanding the request correctly?
By default when you're configuring your Sitefinity Workflow you can specify which roles/users to approve/publish the content. It is by design that hese roles/users should have modify permissions over the content, otherwise they won't be able to fulfill their specific tasks int he workflow, namely approving/rejecting/publishing the content.
If the above condition is met why would there be a necessity for another check if the user has these permissions, since they are a prerequisite for the user to be a participant in the workflow anyways?
On the other hand, if what you're looking for is achieving further granularity in the pages approval workflow (e.g. certain users can approve only pages under certain Group page) I believe you might find our blog post on the topic useful.
Regards,
Boyan Barnev
the Telerik team
Your post on Page Groups (which I was unaware of) was actually very interesting -- and we might talk about how that could play a role in our sitemap -- but it does not fix my problem.
In our CustomGuardActivity -- We have a need to send an email to all the editors in a specific role. The problem is -- the roles vary per page. For our homepage the role is HomepageEditors but for our Parts + Service page it is PartsAndServiceEditors. This continues down the line for all of our page groups. I would say we have about 17 unique roles.
I wanted to see if there was a way I could pull the unique role from the current page in my CustomGuardActivity --- then loop through and grab all of the users within it.
Currently here is my workaround -- where all of my groups are hard-coded based upon the top page's name (one under the Pages group page) -- the logic could be replaced by checking for a group page if we inserted in our sitemap -- but the logic would not change a whole lot. This is not an ideal solution, but it does indeed work.
var sRoleName = "AllEditors";
var groupName = "";var groupPageNode = currentPage;while (groupPageNode.Parent != null) var parent = groupPageNode.Parent; //Check if page is one of our exceptions if (IsLockdownPage(groupPageNode)) groupName = groupPageNode.Title.ToLower(); switch (groupName) case "newsroom": groupName = "publications"; break; if (parent.Title == "Pages") //Check if we are to the top of the list groupName = groupPageNode.Title.ToLower(); switch (groupName) case "home": groupName += "page"; break; case "transmissions": groupName = "transmission"; break; case "suppliers": groupName = "supplier"; break; case "my allison": groupName = "myallison"; break; case "parts + service": groupName = "partsandservice"; break; if (groupName.ToLower() == "home") groupName += "page"; break; groupPageNode = groupPageNode.Parent;if (!string.IsNullOrEmpty(groupName)) var tempRoleName = string.Concat(groupName, "Editor"); if (roleManager.RoleExists(tempRoleName)) sRoleName = tempRoleName; //Get all users in the roleList<User> usersInRoles = new List<User>();if (roleManager.RoleExists(sRoleName)) usersInRoles = roleManager.GetUsersInRole(sRoleName).ToList();Hi Brandon,
I apologize if I'm failing to understand completely the desired scenario, however by design all users who receive workflow notifications when a content has been sent for approval should have Modify action granted by default, otherwise they won't be able to fulfill their task in the workflow.
In any case, if what you're aiming at involves getting a list of the users who have certain action granted on a page I believe the below sample would help you achieve it:
using System;using System.Activities;using System.Collections.Generic;using System.Linq;using System.Text;using Telerik.Sitefinity.Fluent.AnyContent.Implementation;using Telerik.Sitefinity.Modules.Pages;using Telerik.Sitefinity.Security;using Telerik.Sitefinity.Security.Model;using Telerik.Sitefinity.Services;using Telerik.Sitefinity.Services.Notifications;using Telerik.Sitefinity.SitefinityExceptions;using Telerik.Sitefinity.Workflow.Activities;using Telerik.Sitefinity.Workflow.Model;namespace Telerik.Sitefinity.Custom.Workflow.Activities public class CustomNotifyGroup : NotifyGroup protected override void Execute(CodeActivityContext context) var siteUrl = "http://localhost:1129"; StringBuilder sb = new StringBuilder(); OnExcecuting(context); var dataContext = context.DataContext; var workflowDefinition = (WorkflowDefinition)dataContext.GetProperties()["workflowDefinition"].GetValue(dataContext); if (workflowDefinition != null) if (workflowDefinition.WorkflowType == WorkflowType.StandardOneStep && !workflowDefinition.SendFirstLevelEmailNotification) return; if (workflowDefinition.WorkflowType == WorkflowType.StandardTwoStep) var approvalState = (((AnyDraftFacade)(dataContext.GetProperties()["masterFluent"].GetValue(dataContext))).Get() as IApprovalWorkflowItem).ApprovalWorkflowState; if (approvalState == "AwaitingPublishing" && !workflowDefinition.SendSecondLevelEmailNotification) return; if (approvalState == "AwaitingApproval" && !workflowDefinition.SendFirstLevelEmailNotification) return; string itemName = dataContext.GetProperties()["workflowItem"].GetValue(dataContext).GetType().Name; sb.Append("Workflow Item type: " + dataContext.GetProperties()["workflowItem"].GetValue(dataContext).GetType().Name + " "); Guid contentId = (Guid)dataContext.GetProperties()["itemId"].GetValue(dataContext); switch (dataContext.GetProperties()["workflowItem"].GetValue(dataContext).GetType().Name) case "PageNode": Pages.Model.PageNode node = App.WorkWith().Page(contentId).Get(); if (node != null) #region Find all users that have been granted certain action for this pageNode principalsToGrantPermissions = new List<Guid>(); //list all actions for whihc you want to check string[] operationalPageActions = SecurityConstants.Sets.Pages.Create, SecurityConstants.Sets.Pages.CreateChildControls, SecurityConstants.Sets.Pages.Delete, SecurityConstants.Sets.Pages.EditContent, SecurityConstants.Sets.Pages.Modify ; //find all the IDs of actual user/roles who are allowed to take operational actions on pages (except "Owner"role). foreach (Permission perm in node.GetActivePermissions().Where(p => p.PrincipalId != SecurityManager.OwnerRole.Id)) if ((operationalPageActions.Any(action => perm.IsGranted(action))) && (!principalsToGrantPermissions.Contains(perm.PrincipalId))) principalsToGrantPermissions.Add(perm.PrincipalId); #endregion if (itemName.IndexOf("Node") > 0) itemName = itemName.Substring(0, itemName.IndexOf("Node")); sb.Append("<table><tr><td>Link to the item: <a href='" + siteUrl + node.GetFullUrl().Substring(1) + "/Action/Edit' >" + node.Title + "<td></tr><tr><td>Last Modified Date: " + node.LastModified.ToSitefinityUITime().ToString() + "<td></tr><tr><td>Item Pending: " + itemName + "<td><tr><table>"); else sb.Append("Unable to get the Page."); break; default: sb.Append("Unhandled notification for the following item : "); sb.Append("Workflow Item type: " + dataContext.GetProperties()["workflowItem"].GetValue(dataContext).GetType().Name + " "); break; sb.Append("<br>EmailText " + EmailText); var html = sb.ToString(); this.SendMessage(context, html); private void SendMessage(CodeActivityContext context, string messageHtml) string serviceEmail = "boyan.barnev@telerik.com"; var ns = SystemManager.GetNotificationService(); this.Group = "Approve"; //var emailList = GetEmails(context); //this is what we call by default!!! //you can use this one for the custom scenario: var emailList = GetEmailsCustom(principalsToGrantPermissions); if (emailList == null || emailList.Count == 0 || !emailList.Contains(serviceEmail)) emailList.Add(serviceEmail); var subscribers = emailList.Select<string, ISubscriberRequest>(e => new SubscriberRequestProxy() Email = e ); var message = new MessageTemplateRequestProxy() Subject = "Content is waiting for your action in Sitefinity", BodyHtml = EmailText + messageHtml ; var messageJob = new MessageJobRequestProxy() MessageTemplate = message, Subscribers = subscribers, ; var serviceContext = new ServiceContext(null, "Workflow"); ns.SendMessage(serviceContext, messageJob, null); /// <summary> /// Returns a list of the emails for all users resolved from the principalsToGrantPermissions Ids /// </summary> /// <param name="roleOruserIds"></param> /// <returns></returns> private List<string> GetEmailsCustom(List<Guid> roleOruserIds) var emails = new System.Collections.Generic.HashSet<string>(); foreach (var id in roleOruserIds) //id can be either User ID or Role ID, that's why the below check if (UserManager.FindUser(id) != null) #region User usr = null; usr = UserManager.FindUser(id); if (usr == null || String.IsNullOrEmpty(usr.Email)) continue; if (!emails.Contains(usr.Email)) emails.Add(usr.Email); #endregion; else #region var providers = RoleManager.GetManager().Providers; foreach (var provider in providers) try var manager = RoleManager.GetManager(provider.Name); Role role = manager.GetRole(id); if (role != null) var users = manager.GetUsersInRole(role.Id); foreach (var usr in users) if (usr == null || String.IsNullOrEmpty(usr.Email)) continue; if (!emails.Contains(usr.Email)) emails.Add(usr.Email); catch (ItemNotFoundException) //we test all role providers - since we don't keep principal provider name , but just the id #endregion return emails.ToList(); private List<Guid> principalsToGrantPermissions;