+1-888-365-2779
Try Now
More in this section
Categories
Bloggers
Blogs RSS feed

Working with Sitefinity Permissions API - Managing Permissions

by Boyan Barnev
Every now and then we receive questions from our clients regarding managing permissions in Sitefinity CMS through code. With this blog post we aim at addressing the most common scenario of granting and denying specific actions on Sitefinity secured objects. Let's take Pages for example.

Prior to proceeding, please note that the purpose of this post is to describe one of the multiple applications our Permissions API has, and to get you started in your projects when similar implementation is required. To learn more about the full power of our permissions API, we strongly recommend checking out our Permissions API section from the Developers Guide of our Sitefinity online documentation.

For the sake of the post I've created a very simple UI on an ASP.NET WebForm, which you can find attached at the end of the article.  The UI allows you to type in a Page title, a user name, and select among the supported security actions for Pages which ones you want to grant and deny for your user.

When working with our Permissions API you can easily see the available security actions for each supported type by using the SecurityConstants.Sets class. Each type is represented as a separate Set and each set contains the supported actions as string constants. For example, with Pages we have:
SecurityConstants.Sets.Pages.ChangeOwner,
                                            SecurityConstants.Sets.Pages.ChangePermissions,
                                            SecurityConstants.Sets.Pages.Create,
                                            SecurityConstants.Sets.Pages.CreateChildControls,
                                            SecurityConstants.Sets.Pages.Delete,
                                            SecurityConstants.Sets.Pages.EditContent,
                                            SecurityConstants.Sets.Pages.Modify,
                                            SecurityConstants.Sets.Pages.View

To assign permissions to an item you'll need to retrieve the secured object (the item itself) and the principal (user or role) and configure the granted (what the user can do) and denied (what the user can not do) actions from the specific set in SecurityConstants. In other words we'll simply retrieve the page and user through the corresponding managers:
#region initialize managers and get items to work with
 
            string transactionName = "transact" + Guid.NewGuid().ToString();
            var pgManager = PageManager.GetManager(null, transactionName);
            var page = pgManager.GetPageNodes().Where(pn => pn.RootNodeId == SiteInitializer.FrontendRootNodeId && pn.Title == pageTitle).SingleOrDefault();
            if (page == null)
            {
                this.statusLabel.Text = "Unable to find page with the specified title ";
                return;
            }
            var uManager = UserManager.GetManager();
            var user = uManager.GetUser(userName);
            if (user == null)
            {
                this.statusLabel.Text = "Unable to find user with the specified user name ";
                return;
            }
            #endregion

We use the GetManager() overload with transaction name, so we can easily commit the transaction later on in our code.

NOTE: Please note that if you are working with content items (e.g. News, Blogs, etc.) you should retrieve the master item by using the LifecycleDecorator.GetMaster() call, for example:

var newsLive = nManager.GetNewsItems().Where(n => n.Title == "TestPerm" && n.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Master).SingleOrDefault();
 

or

var newsLive = nManager.GetNewsItems().Where(n => n.Title == "TestPerm" && n.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live).SingleOrDefault();
NewsItem news = nManager.Lifecycle.GetMaster(newsLive) as NewsItem;

Now we're on to the actual part, namely implementing our permissions business logic. Each permission supports multiple grant and deny actions, which we can easily represent with a string[] that is populated with actions from the specific set in SecurityConstants class:

//set the allowed actions for that permission set
            var actionsAllowedForUser = new string[] { grantAction };
            //set the denied actions for the permission set
            var actionsDeniedForUser = new string[] { denyAction };

Once we've sorted that out, we need to check if the item inherits permissions form its parent. If so, just like in the Sitefinity backend UI we need to break the permissions inheritance so we can apply our new desired permissions:
//break inheritance
               if (page.InheritsPermissions)
                   pgManager.BreakPermiossionsInheritance(page);
               TransactionManager.CommitTransaction(transactionName);

Please note that we need to commit the changes introduced by our call to BreakPermiossionsInheritance before moving on!

Our item does not inherit its permissions from the parent anymore, so we are ready to define the new permission to be assigned. Please note that you always have to check if a permissions does not already exist in the database, prior to creating it, in order to avoid duplicate permissions entries. Each permissions is a unique combination of a SecurityConstants SetName, SecuredObject Id, and Principal Id, so you can easily check if it exists in the Permissions collection of the secured item like this:
//Check whether such permission already exists, and if not create a new one
                var perm = secItem.Permissions
                                .Where(p =>
                                       p.SetName == permSet &&
                                       p.PrincipalId == user.Id &&
                                       p.ObjectId == page.Id)
                                .SingleOrDefault();
If it doesn't then we can check if it's not available as a permission for the secured object type, and if it's not available there either we can proceed by creating it:
if (perm == null)
                {
                    perm = pgManager.GetPermission(permSet, page.Id, user.Id);
                    if (perm == null)
                    {
                        perm = pgManager.CreatePermission(
                                              permSet,
                                              page.Id,
                                              user.Id);
                    }
                }
 
Once you have the permission ready to be assigned to your item, our Permissions API gives you the option of assigning it only to the current item you're working with, or have it propagate to its child items as well. By default we always inherit the assigned permissions to the item's children, if any, so if you want to duplicate the Sitefinity backend UI behavior you have to use the AddPermissionToObject() method of the corresponding item's manager:
pgManager.AddPermissionToObject(page, pgManager, perm, transactionName);
If your desired scenario requires that this permission gets assigned only to the item you're currently working with, you can just add it to the item's Permissions collection instead:
secItem.Permissions.Add(perm);

Now that we're sure the permission is assigned to the desired item(s) we can easily set the Allowed and Denied actions for it, and commit everything:
//Get the permission agan as we're calling FlushTransaction internally
                perm = pgManager.GetPermission(permSet, page.Id, user.Id);
 
                //Grant the actions to the permission
                perm.GrantActions(true, actionsAllowedForUser);
                //Deny the actions to the permission
                perm.DenyActions(true, actionsDeniedForUser);
 
 
                TransactionManager.CommitTransaction(transactionName);

That's about everything you need to get you started in exploring and utilizing the Sitefinity Permissions API. As promised in the article's introduction, you can find the WebForm sample here: SetPagePermissionsSample

We hope you found this article useful.

Leave a comment