Recently I was working on the EPiServer site that contains dozens of subsections. Every of them is managed by different editor. I was asked to display in page tree view in edit mode only those pages, that editor has editing access. It is reasonable as having dozens of pages (all marked with padlock) makes editing harder or at least less comfortable. Lets do not talk more about the background and take a look at implementation...
In general I think that EPiServer code is a little bit too sealed. I hate all those classes where you can not reimplement part of the code on your own or where you can not overwrite methods. However, this time I was nicely surprised. It was enough to create custom implementation of the
EPiServer.PlugIn.PlugInAttribute and use
DataFactory.Instance.FinishedLoadingChildren event.
Actually, on the beginning I wanted to use
DataFactory.Instance.LoadingChildren and set
RequiredAccess to
AccessLevel.Edit (see below), but it didn't work for me. If you know why, please comment so I can learn something :)
private static void Instance_LoadingChildren(object sender, ChildrenEventArgs e)
{
e.RequiredAccess = AccessLevel.Edit;
}
First I created my class inheriting from
EPiServer.PlugIn.PlugInAttribute and implemented Start method so it adds new
ChildrenEventHandler to the
DataFactory.Instance.FinishedLoadingChildren event:
using System.Web;
using EPiServer;
using EPiServer.Configuration;
using EPiServer.Core;
using EPiServer.PlugIn;
using EPiServer.Security;
namespace Maras.TreeAdapter
{
public class TreeAdapter : PlugInAttribute
{
public static void Start()
{
DataFactory.Instance.FinishedLoadingChildren += Instance_FinishedLoadingChildren;
}
private static void Instance_FinishedLoadingChildren(object sender, ChildrenEventArgs e)
{
if (IsAccessCheckNecessary(e))
{
int index = 0;
while (index < e.Children.Count)
{
if (e.Children[index].ACL.HasAccess(PrincipalInfo.Current.Principal, AccessLevel.Edit))
{
index++;
}
else
{
e.Children.RemoveAt(index);
}
}
}
}
}
}
As you can see, I check whether the access control is necessary and then I remove all the children that current user is not allowed to edit. Pretty important is the
IsAccessCheckNecessary method. My implementation assumes that I want to filter pages in edit mode and for the children of the start page only, so it looks like this:
private static readonly string UI_URL = Settings.Instance.UIUrl.ToString().ToLower();
private static bool IsAccessCheckNecessary(ChildrenEventArgs e)
{
return e.PageLink == PageReference.StartPage &&
HttpContext.Current.Request.Url.ToString().ToLower().StartsWith(UI_URL);
}
If you know any easier way of doing what I needed, feel free to comment below.
Source code can be downloaded from here: source code
