Removes the AllStartNodeIds properties from IUser, updates all unit tests to work with the new methods, ensures the calculation is cached to the user object

This commit is contained in:
Shannon
2017-07-19 16:15:16 +10:00
parent 8c3f6dfc25
commit 38cd3dcf94
20 changed files with 364 additions and 157 deletions

View File

@@ -109,32 +109,32 @@ namespace Umbraco.Core.Models
internal static bool HasContentRootAccess(this IUser user, IEntityService entityService)
{
return HasPathAccess(Constants.System.Root.ToInvariantString(), user.GetAllContentStartNodes(entityService), Constants.System.RecycleBinContent);
return HasPathAccess(Constants.System.Root.ToInvariantString(), user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
}
internal static bool HasContentBinAccess(this IUser user, IEntityService entityService)
{
return HasPathAccess(Constants.System.RecycleBinContent.ToInvariantString(), user.GetAllContentStartNodes(entityService), Constants.System.RecycleBinContent);
return HasPathAccess(Constants.System.RecycleBinContent.ToInvariantString(), user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
}
internal static bool HasMediaRootAccess(this IUser user, IEntityService entityService)
{
return HasPathAccess(Constants.System.Root.ToInvariantString(), user.GetAllMediaStartNodes(entityService), Constants.System.RecycleBinMedia);
return HasPathAccess(Constants.System.Root.ToInvariantString(), user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
}
internal static bool HasMediaBinAccess(this IUser user, IEntityService entityService)
{
return HasPathAccess(Constants.System.RecycleBinMedia.ToInvariantString(), user.GetAllMediaStartNodes(entityService), Constants.System.RecycleBinMedia);
return HasPathAccess(Constants.System.RecycleBinMedia.ToInvariantString(), user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
}
internal static bool HasPathAccess(this IUser user, IContent content, IEntityService entityService)
{
return HasPathAccess(content.Path, user.GetAllContentStartNodes(entityService), Constants.System.RecycleBinContent);
return HasPathAccess(content.Path, user.CalculateContentStartNodeIds(entityService), Constants.System.RecycleBinContent);
}
internal static bool HasPathAccess(this IUser user, IMedia media, IEntityService entityService)
{
return HasPathAccess(media.Path, user.GetAllMediaStartNodes(entityService), Constants.System.RecycleBinMedia);
return HasPathAccess(media.Path, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
}
internal static bool HasPathAccess(string path, int[] startNodeIds, int recycleBinId)
@@ -181,37 +181,79 @@ namespace Umbraco.Core.Models
return user.Groups != null && user.Groups.Any(x => x.Alias == Constants.Security.AdminGroupAlias);
}
public static int[] GetAllContentStartNodes(this IUser user, IEntityService entityService)
public static int[] CalculateContentStartNodeIds(this IUser user, IEntityService entityService)
{
const string cacheKey = "AllContentStartNodes";
//try to look them up from cache so we don't recalculate
var valuesInUserCache = FromUserCache(user, cacheKey);
if (valuesInUserCache != null) return valuesInUserCache;
var gsn = user.Groups.Where(x => x.StartContentId.HasValue).Select(x => x.StartContentId.Value).Distinct().ToArray();
var usn = user.StartContentIds;
return CombineStartNodes(gsn, usn, entityService);
var vals = CombineStartNodes(gsn, usn, entityService);
ToUserCache(user, cacheKey, vals);
return vals;
}
public static int[] GetAllMediaStartNodes(this IUser user, IEntityService entityService)
public static int[] CalculateMediaStartNodeIds(this IUser user, IEntityService entityService)
{
const string cacheKey = "AllMediaStartNodes";
//try to look them up from cache so we don't recalculate
var valuesInUserCache = FromUserCache(user, cacheKey);
if (valuesInUserCache != null) return valuesInUserCache;
var gsn = user.Groups.Where(x => x.StartMediaId.HasValue).Select(x => x.StartMediaId.Value).Distinct().ToArray();
var usn = user.StartMediaIds;
return CombineStartNodes(gsn, usn, entityService);
var vals = CombineStartNodes(gsn, usn, entityService);
ToUserCache(user, cacheKey, vals);
return vals;
}
private static int[] FromUserCache(IUser user, string cacheKey)
{
var entityUser = user as User;
if (entityUser != null)
{
object allContentStartNodes;
if (entityUser.AdditionalData.TryGetValue(cacheKey, out allContentStartNodes))
{
var asArray = allContentStartNodes as int[];
if (asArray != null) return asArray;
}
}
return null;
}
private static void ToUserCache(IUser user, string cacheKey, int[] vals)
{
var entityUser = user as User;
if (entityUser != null)
{
entityUser.AdditionalData[cacheKey] = vals;
}
}
private static bool StartsWithPath(string test, string path)
{
return test.StartsWith(path) && test.Length > path.Length && test[path.Length] == ',';
}
private static int[] CombineStartNodes(int[] groupSn, int[] userSn, IEntityService entityService)
//TODO: Unit test this
internal static int[] CombineStartNodes(int[] groupSn, int[] userSn, IEntityService entityService)
{
// assume groupSn and userSn each don't contain duplicates
var asn = groupSn.Concat(userSn).Distinct().ToArray();
var asn = groupSn.Concat(userSn).Distinct().ToArray();
//TODO: Change this to a more optimal lookup just to retrieve paths
var paths = entityService.GetAll(UmbracoObjectTypes.Document, asn).ToDictionary(x => x.Id, x => x.Path);
paths[-1] = "-1"; // entityService does not get that one
var lsn = new List<int>();
foreach (var sn in groupSn)
{
{
//TODO: Change this to TryGetValue
var snp = paths[sn];
if (lsn.Any(x => StartsWithPath(snp, paths[x]))) continue; // skip if something above this sn
lsn.RemoveAll(x => StartsWithPath(paths[x], snp)); // remove anything below this sn
@@ -223,6 +265,7 @@ namespace Umbraco.Core.Models
{
if (groupSn.Contains(sn)) continue;
//TODO: Change this to TryGetValue
var snp = paths[sn];
if (usn.Any(x => StartsWithPath(paths[x], snp))) continue; // skip if something below this sn
usn.RemoveAll(x => StartsWithPath(snp, paths[x])); // remove anything above this sn