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 Page
var 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 defined
var allRoles = roleManager.GetRoles();
//Get all page permissions
var 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 role
List<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 role
List<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;