Use API to get Roles with Page Edit Permission

Posted by Community Admin on 04-Aug-2018 14:40

Use API to get Roles with Page Edit Permission

All Replies

Posted by Community Admin on 29-Mar-2013 00:00

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();

Posted by Community Admin on 03-Apr-2013 00:00

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

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 03-Apr-2013 00:00

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();

Posted by Community Admin on 08-Apr-2013 00:00

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;
 
    


Greetings,
Boyan Barnev
the Telerik team
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

This thread is closed