Just from the top of my head, you can check all the roles if they have read
access to chosen item:
foreach (Role role in RolesInRolesManager.GetAllRoles())
{
bool roleCanRead = item.Security.CanRead(role);
}
EDIT after code sample provided:
You need to try to resolve the item in the same way as ItemResolver
does but wrapped it with SecurityDisabler
and without setting it to Sitecore Context
afterwards. This will allow you to find the requested item despite the fact the user doesn't have access to it:
public class NotFoundProcessor : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
if (args.PermissionDenied)
{
Item item = GetItemUsingSecurityDisabler(args);
//determine what role would give the user access
foreach(Role role in RolesInRolesManager.GetAllRoles())
{
bool roleCanRead = item.Security.CanRead(role);
//... do stuff here
}
}
}
}
private Item GetItemUsingSecurityDisabler(HttpRequestArgs args)
{
using (new SecurityDisabler())
{
string path = MainUtil.DecodeName(args.Url.ItemPath);
Item item = args.GetItem(path);
if (item == null)
{
path = args.Url.ItemPath;
item = args.GetItem(path);
}
if (item == null)
{
path = args.LocalPath;
item = args.GetItem(path);
}
if (item == null)
{
path = MainUtil.DecodeName(args.LocalPath);
item = args.GetItem(path);
}
SiteContext site = Sitecore.Context.Site;
string rootPath = site != null ? site.RootPath : string.Empty;
if (item == null)
{
path = FileUtil.MakePath(rootPath, args.LocalPath, '/');
item = args.GetItem(path);
}
if (item == null)
{
path = MainUtil.DecodeName(FileUtil.MakePath(rootPath, args.LocalPath, '/'));
item = args.GetItem(path);
}
// I've ommited resolving item using DisplayName but you can add if necessary here
return item;
}
}