U4-10173 - refactor start nodes

This commit is contained in:
Stephan
2017-07-18 15:09:34 +02:00
parent 945050858e
commit 8c3f6dfc25
9 changed files with 122 additions and 69 deletions

View File

@@ -308,7 +308,7 @@ namespace Umbraco.Core.Models.Membership
[IgnoreDataMember]
public int[] AllStartContentIds
{
get { return _allStartContentIds ?? (_allStartContentIds = StartContentIds.Concat(Groups.Where(x => x.StartContentId.HasValue).Select(x => x.StartContentId.Value)).Distinct().ToArray()); }
get { return this.GetAllContentStartNodes(ApplicationContext.Current.Services.EntityService); }
}
/// <summary>
@@ -317,7 +317,7 @@ namespace Umbraco.Core.Models.Membership
[IgnoreDataMember]
public int[] AllStartMediaIds
{
get { return _allStartMediaIds ?? (_allStartMediaIds = StartMediaIds.Concat(Groups.Where(x => x.StartMediaId.HasValue).Select(x => x.StartMediaId.Value)).Distinct().ToArray()); }
get { return this.GetAllMediaStartNodes(ApplicationContext.Current.Services.EntityService); }
}
/// <summary>

View File

@@ -107,17 +107,34 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Checks if the user has access to the content item based on their start noe
/// </summary>
/// <param name="user"></param>
/// <param name="content"></param>
/// <returns></returns>
internal static bool HasPathAccess(this IUser user, IContent content)
internal static bool HasContentRootAccess(this IUser user, IEntityService entityService)
{
if (user == null) throw new ArgumentNullException("user");
if (content == null) throw new ArgumentNullException("content");
return HasPathAccess(content.Path, user.AllStartContentIds, Constants.System.RecycleBinContent);
return HasPathAccess(Constants.System.Root.ToInvariantString(), user.GetAllContentStartNodes(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);
}
internal static bool HasMediaRootAccess(this IUser user, IEntityService entityService)
{
return HasPathAccess(Constants.System.Root.ToInvariantString(), user.GetAllMediaStartNodes(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);
}
internal static bool HasPathAccess(this IUser user, IContent content, IEntityService entityService)
{
return HasPathAccess(content.Path, user.GetAllContentStartNodes(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);
}
internal static bool HasPathAccess(string path, int[] startNodeIds, int recycleBinId)
@@ -151,19 +168,6 @@ namespace Umbraco.Core.Models
return false;
}
/// <summary>
/// Checks if the user has access to the media item based on their start noe
/// </summary>
/// <param name="user"></param>
/// <param name="media"></param>
/// <returns></returns>
internal static bool HasPathAccess(this IUser user, IMedia media)
{
if (user == null) throw new ArgumentNullException("user");
if (media == null) throw new ArgumentNullException("media");
return HasPathAccess(media.Path, user.AllStartMediaIds, Constants.System.RecycleBinMedia);
}
/// <summary>
/// Determines whether this user is an admin.
/// </summary>
@@ -176,5 +180,63 @@ namespace Umbraco.Core.Models
if (user == null) throw new ArgumentNullException("user");
return user.Groups != null && user.Groups.Any(x => x.Alias == Constants.Security.AdminGroupAlias);
}
public static int[] GetAllContentStartNodes(this IUser user, IEntityService entityService)
{
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);
}
public static int[] GetAllMediaStartNodes(this IUser user, IEntityService entityService)
{
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);
}
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)
{
// assume groupSn and userSn each don't contain duplicates
var asn = groupSn.Concat(userSn).Distinct().ToArray();
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)
{
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
lsn.Add(sn);
}
var usn = new List<int>();
foreach (var sn in userSn)
{
if (groupSn.Contains(sn)) continue;
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
usn.Add(sn);
}
foreach (var sn in usn)
{
var snp = paths[sn];
lsn.RemoveAll(x => StartsWithPath(snp, paths[x]) || StartsWithPath(paths[x], snp)); // remove anything above or below this sn
lsn.Add(sn);
}
return lsn.ToArray();
}
}
}

View File

@@ -1,5 +1,6 @@
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
@@ -23,7 +24,7 @@ namespace Umbraco.Tests.Models
contentMock.Setup(c => c.Path).Returns(contentPath);
var content = contentMock.Object;
Assert.AreEqual(outcome, user.HasPathAccess(content));
Assert.AreEqual(outcome, user.HasPathAccess(content, ApplicationContext.Current.Services.EntityService));
}
}
}

View File

@@ -1059,17 +1059,12 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var entityService = ApplicationContext.Current.Services.EntityService;
var hasPathAccess = (nodeId == Constants.System.Root)
? UserExtensions.HasPathAccess(
Constants.System.Root.ToInvariantString(),
user.AllStartContentIds,
Constants.System.RecycleBinContent)
? user.HasContentRootAccess(entityService)
: (nodeId == Constants.System.RecycleBinContent)
? UserExtensions.HasPathAccess(
Constants.System.RecycleBinContent.ToInvariantString(),
user.AllStartContentIds,
Constants.System.RecycleBinContent)
: user.HasPathAccess(contentItem);
? user.HasContentBinAccess(entityService)
: user.HasPathAccess(contentItem, entityService);
if (hasPathAccess == false)
{

View File

@@ -551,10 +551,10 @@ namespace Umbraco.Web.Editors
switch (type)
{
case UmbracoEntityTypes.Document:
aids = Security.CurrentUser.AllStartContentIds;
aids = Security.CurrentUser.GetAllContentStartNodes(Services.EntityService);
break;
case UmbracoEntityTypes.Media:
aids = Security.CurrentUser.AllStartMediaIds;
aids = Security.CurrentUser.GetAllMediaStartNodes(Services.EntityService);
break;
}
@@ -695,14 +695,14 @@ namespace Umbraco.Web.Editors
type = "media";
AddExamineSearchFrom(searchFrom, sb);
AddExamineUserStartNode(Security.CurrentUser.AllStartMediaIds, sb);
AddExamineUserStartNode(Security.CurrentUser.GetAllMediaStartNodes(Services.EntityService), sb);
break;
case UmbracoEntityTypes.Document:
type = "content";
AddExamineSearchFrom(searchFrom, sb);
AddExamineUserStartNode(Security.CurrentUser.AllStartContentIds, sb);
AddExamineUserStartNode(Security.CurrentUser.GetAllContentStartNodes(Services.EntityService), sb);
break;
default:
@@ -950,10 +950,10 @@ namespace Umbraco.Web.Editors
switch (entityType)
{
case UmbracoEntityTypes.Document:
aids = Security.CurrentUser.AllStartContentIds;
aids = Security.CurrentUser.GetAllContentStartNodes(Services.EntityService);
break;
case UmbracoEntityTypes.Media:
aids = Security.CurrentUser.AllStartMediaIds;
aids = Security.CurrentUser.GetAllMediaStartNodes(Services.EntityService);
break;
}

View File

@@ -254,7 +254,7 @@ namespace Umbraco.Web.Editors
private int[] _userStartNodes;
protected int[] UserStartNodes
{
get { return _userStartNodes ?? (_userStartNodes = Security.CurrentUser.AllStartMediaIds); }
get { return _userStartNodes ?? (_userStartNodes = Security.CurrentUser.GetAllMediaStartNodes(Services.EntityService)); }
}
/// <summary>
@@ -910,17 +910,12 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var entityService = Core.ApplicationContext.Current.Services.EntityService;
var hasPathAccess = (nodeId == Constants.System.Root)
? UserExtensions.HasPathAccess(
Constants.System.Root.ToInvariantString(),
user.AllStartMediaIds,
Constants.System.RecycleBinMedia)
? user.HasMediaRootAccess(entityService)
: (nodeId == Constants.System.RecycleBinMedia)
? UserExtensions.HasPathAccess(
Constants.System.RecycleBinMedia.ToInvariantString(),
user.AllStartMediaIds,
Constants.System.RecycleBinMedia)
: user.HasPathAccess(media);
? user.HasMediaBinAccess(entityService)
: user.HasPathAccess(media, entityService);
return hasPathAccess;
}

View File

@@ -215,7 +215,7 @@ namespace Umbraco.Web.Trees
{
return false;
}
return Security.CurrentUser.HasPathAccess(content);
return Security.CurrentUser.HasPathAccess(content, Services.EntityService);
}
/// <summary>

View File

@@ -163,7 +163,7 @@ namespace Umbraco.Web.Trees
{
return false;
}
return Security.CurrentUser.HasPathAccess(media);
return Security.CurrentUser.HasPathAccess(media, Services.EntityService);
}
}
}

View File

@@ -294,8 +294,8 @@ namespace umbraco.BasePages
AllowedApplications = u.GetApplications().Select(x => x.alias).ToArray(),
RealName = u.Name,
Roles = u.GetGroups(),
StartContentNodes = u.UserEntity.AllStartContentIds,
StartMediaNodes = u.UserEntity.AllStartMediaIds,
StartContentNodes = u.UserEntity.GetAllContentStartNodes(ApplicationContext.Current.Services.EntityService),
StartMediaNodes = u.UserEntity.GetAllMediaStartNodes(ApplicationContext.Current.Services.EntityService),
Username = u.LoginName,
Culture = ui.Culture(u)