26

Best practice is to assign access rights to roles rather than users. So I would like to block changes that apply access rights for users. Sitecore does not seem to trigger the saveUI pipeline on access right changes, so I think I should use an event handler. One of my concerns is that SheerUI might not always be available. This seems to work, though I haven't tried it from an API call with no SheerUI context.

One issue is that if a UI user has made significant security changes, they will lose their work because I do not think I can confirm, only alert, and then in the case of Security Editor, the UI does not refresh.

Please comment on this approach, especially anyone who has experience with SheerUI from an event handler. Is this just a bad idea, or is there some better way?

namespace Whatever.Tasks
{
    using System;
    using Sitecore.Diagnostics;
    using Sitecore.Data.Items;
    using Sitecore.Events;
    using Sitecore.Globalization;
    using Sitecore.Security.AccessControl;
    using Sitecore.Security.Accounts;
    using Sitecore.SecurityModel;
    using Sitecore.Web.UI.Sheer;

    public class PreventUserAccessRights
    {
        protected void OnItemSaving(object sender, EventArgs args)
        {
            // data being saved
            Item itemInMemory = Event.ExtractParameter(args, 0) as Item;
            Error.AssertNotNull(itemInMemory, "itemInMemory");

            // probably not needed
            using (new SecurityDisabler())
            {
                // ignore event if no changes to security field
                Item itemInDatabase = itemInMemory.Database.GetItem(itemInMemory.ID);

                if (itemInDatabase == null || itemInMemory[Sitecore.FieldIDs.Security]
                    != itemInDatabase[Sitecore.FieldIDs.Security])
                {
                    foreach (AccessRule accessRule
                        in AccessRuleCollection.FromString(itemInMemory[Sitecore.FieldIDs.Security]))
                    {
                        if (accessRule.Account.AccountType == AccountType.User)
                        {
                            // block the save
                            SitecoreEventArgs scEventArgs = args as SitecoreEventArgs;

                            if (scEventArgs != null)
                            {
                                scEventArgs.Result.Cancel = true;
                            }

                            string msg = Translate.Text(
                                "Hey bro, you cannot assign access rights for users, only roles: ") + accessRule.Account.Name;

                            // try to alert the user
                            try
                            {
                                SheerResponse.Alert(msg);
                            }
                            catch (Exception ex)
                            {
                                // maybe thrown if SheerUI missing?
                                throw (new ApplicationException(msg));
                            }

                            if (scEventArgs == null)
                            {
                                // unlikley/impossible case, 
                                // but would still want to prevent the save
                                throw (new ApplicationException(msg));
                            }

                            return;
                        }
                    }
                }
            }
        }
    }    
}
  • 5
    An alternative approach may be to to simply not allow the selection of users in the Account Selector dialog. – jammykam Sep 21 '16 at 8:29
  • I also question whether the event would even fire, say if someone is putting security permissions on an item through security editor. I have not tried. – Pete Navarra Oct 7 '16 at 3:53
  • FYI - there have been some defects in 8.x where role-based permissions are not respected and only per-user permissions work correctly. – Chris Berg Oct 9 '16 at 12:54
  • item.Security.GetAccessRules() may be neater than AccessRuleCollection.FromString(itemInMemory[Sitecore.FieldIDs.Security] – Paul George Oct 26 '16 at 7:38
7

Because Sitecore does not provide you the hooks to validate the transaction you're after, your best bet is to hide the security features and manage them in code. Here's a few suggestions that aren't too onerous to implement.

Prerequisite: Lock Sitecore Users out of Security Features

Make sure no one has access to Sitecore Client Securing Make sure no one has the Administer right on any Items.

Create Security Privileges as part of Item Creation

There are probably some basic conventions to your security scheme. Assuming something Helix/Habitat like, you probably have roles to manage Tenants, Site Groups and Sites.

When a new scope object is created (Tenant, Site, etc) consider creating the security roles for it as part of the Item Created process, then assigning the new roles the appropriate rights. This could either be done with an Item Created/Saved rule or a Branch Template. All that's left is to assign users to roles.

Consider some sort of Security Facade

You could create some sort of settings Items that represent actual Security roles and using a system of multilist fields on Items that need securing, allow content authors to perform security themselves through the facade. On Item:Saved, you then read these fields and make the necessary changes through the actual Security API.

2

The approach to sheerUi seems fine. As an alternative to blocking the save outright and as you say possibly loosing other changes made, you could strip the user-account specific permissions from the inMemoryItem and let the rest go through.

var accessRules = itemInMemory.Security.GetAccessRules();
foreach (var accessRule in accessRules)
{
    if (accessRule.Account.AccountType == AccountType.User)
    {
        accessRules.Helper.RemoveWildcardMatches(accessRule.Account);
    }
}

// alert sheerUi

// allow save

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.