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;
}
}
}
}
}
}
}