Fixed caching issues on editing node permissions

This commit is contained in:
AndyButland
2016-10-30 11:58:36 +01:00
parent f316b3f694
commit 6560f38cb0
7 changed files with 143 additions and 56 deletions
-2
View File
@@ -56,8 +56,6 @@ namespace Umbraco.Core.Cache
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserCacheKey = "UmbracoUser";
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
+17 -1
View File
@@ -71,6 +71,18 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="EntityPermission"/></returns>
IEnumerable<EntityPermission> GetPermissions(IUser user, params int[] nodeIds);
/// <summary>
/// Get permissions set for a group and optional node Ids
/// </summary>
/// <param name="group">Group to retrieve permissions for</param>
/// <param name="directlyAssignedOnly">
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
/// </param>
/// <param name="nodeIds">Specifiying nothing will return all permissions for all nodes</param>
/// <returns>An enumerable list of <see cref="EntityPermission"/></returns>
IEnumerable<EntityPermission> GetPermissions(IUserGroup group, bool directlyAssignedOnly, params int[] nodeIds);
/// <summary>
/// Gets the permissions for the provided user and path
/// </summary>
@@ -84,8 +96,12 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="group">User to check permissions for</param>
/// <param name="path">Path to check permissions for</param>
/// <param name="directlyAssignedOnly">
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
/// </param>
/// <returns>String indicating permissions for provided user and path</returns>
string GetPermissionsForPath(IUserGroup group, string path);
string GetPermissionsForPath(IUserGroup group, string path, bool directlyAssignedOnly = true);
/// <summary>
/// Replaces the same permission set for a single group to any number of entities
+45 -30
View File
@@ -767,7 +767,7 @@ namespace Umbraco.Core.Services
var result = new List<EntityPermission>();
foreach (var group in user.Groups)
{
foreach (var permission in GetPermissions(group, nodeIds))
foreach (var permission in GetPermissions(group, false, nodeIds))
{
AddOrAmendPermissionList(result, permission);
}
@@ -776,6 +776,39 @@ namespace Umbraco.Core.Services
return result;
}
/// <summary>
/// Get permissions set for a group and node Id
/// </summary>
/// <param name="group">Group to retrieve permissions for</param>
/// <param name="directlyAssignedOnly">
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
/// </param>
/// <param name="nodeIds">Specifiying nothing will return all permissions for all nodes</param>
/// <returns>An enumerable list of <see cref="EntityPermission"/></returns>
public IEnumerable<EntityPermission> GetPermissions(IUserGroup group, bool directlyAssignedOnly, params int[] nodeIds)
{
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateUserGroupRepository(uow))
{
var explicitPermissions = repository.GetPermissionsForEntities(group.Id, nodeIds);
var result = new List<EntityPermission>(explicitPermissions);
// If requested, and no permissions are assigned to a particular node, then we will fill in those permissions with the group's defaults
if (directlyAssignedOnly == false)
{
var missingIds = nodeIds.Except(result.Select(x => x.EntityId)).ToList();
if (missingIds.Any())
{
result.AddRange(missingIds
.Select(i => new EntityPermission(i, group.Permissions.ToArray())));
}
}
return result;
}
}
/// <summary>
/// For an existing list of <see cref="EntityPermission"/>, takes a new <see cref="EntityPermission"/> and aggregates it.
/// If a permission for the entity associated with the new permission already exists, it's updated with those permissions to create a distinct, most permissive set.
@@ -823,7 +856,7 @@ namespace Umbraco.Core.Services
private IEnumerable<string> GetPermissionsForGroupsAndPath(IEnumerable<IUserGroup> groups, string path)
{
return groups
.Select(g => GetPermissionsForPath(g, path))
.Select(g => GetPermissionsForPath(g, path, directlyAssignedOnly: false))
.ToList();
}
@@ -844,11 +877,19 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="group">User to check permissions for</param>
/// <param name="path">Path to check permissions for</param>
/// <param name="directlyAssignedOnly">
/// Flag indicating if we want to get just the permissions directly assigned for the group and path,
/// or fall back to the group's default permissions when nothing is directly assigned
/// </param>
/// <returns>String indicating permissions for provided user and path</returns>
public string GetPermissionsForPath(IUserGroup group, string path)
public string GetPermissionsForPath(IUserGroup group, string path, bool directlyAssignedOnly = true)
{
var nodeId = GetNodeIdFromPath(path);
return string.Join(string.Empty, GetPermissions(group, nodeId).Single().AssignedPermissions);
var permission = GetPermissions(group, directlyAssignedOnly, nodeId)
.SingleOrDefault();
return permission != null
? string.Join(string.Empty, permission.AssignedPermissions)
: string.Empty;
}
/// <summary>
@@ -863,32 +904,6 @@ namespace Umbraco.Core.Services
: int.Parse(path);
}
/// <summary>
/// Get permissions set for a group and node Id
/// </summary>
/// <param name="group">Group to retrieve permissions for</param>
/// <param name="nodeIds">Specifiying nothing will return all permissions for all nodes</param>
/// <returns>An enumerable list of <see cref="EntityPermission"/></returns>
private IEnumerable<EntityPermission> GetPermissions(IUserGroup group, params int[] nodeIds)
{
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateUserGroupRepository(uow))
{
var explicitPermissions = repository.GetPermissionsForEntities(group.Id, nodeIds);
var result = new List<EntityPermission>(explicitPermissions);
// If no permissions are assigned to a particular node then we will fill in those permissions with the group's defaults
var missingIds = nodeIds.Except(result.Select(x => x.EntityId)).ToList();
if (missingIds.Any())
{
result.AddRange(missingIds
.Select(i => new EntityPermission(i, group.Permissions.ToArray())));
}
return result;
}
}
private static bool IsNotNullActionPermission(EntityPermission x)
{
const string NullActionChar = "-";
+78 -7
View File
@@ -93,7 +93,72 @@ namespace Umbraco.Tests.Services
Assert.AreEqual(2, permissions.ElementAt(1).AssignedPermissions.Count());
Assert.AreEqual(1, permissions.ElementAt(2).AssignedPermissions.Count());
}
[Test]
public void UserService_Get_UserGroup_Assigned_Permissions()
{
// Arrange
var userService = ServiceContext.UserService;
var userGroup = CreateTestUserGroup();
var contentType = MockedContentTypes.CreateSimpleContentType();
ServiceContext.ContentTypeService.Save(contentType);
var content = new[]
{
MockedContent.CreateSimpleContent(contentType),
MockedContent.CreateSimpleContent(contentType),
MockedContent.CreateSimpleContent(contentType)
};
ServiceContext.ContentService.Save(content);
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(2), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
// Act
var permissions = userService.GetPermissions(userGroup, true, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id);
//assert
Assert.AreEqual(3, permissions.Count());
Assert.AreEqual(3, permissions.ElementAt(0).AssignedPermissions.Count());
Assert.AreEqual(2, permissions.ElementAt(1).AssignedPermissions.Count());
Assert.AreEqual(1, permissions.ElementAt(2).AssignedPermissions.Count());
}
[Test]
public void UserService_Get_UserGroup_Assigned_And_Default_Permissions()
{
// Arrange
var userService = ServiceContext.UserService;
var userGroup = CreateTestUserGroup();
var contentType = MockedContentTypes.CreateSimpleContentType();
ServiceContext.ContentTypeService.Save(contentType);
var content = new[]
{
MockedContent.CreateSimpleContent(contentType),
MockedContent.CreateSimpleContent(contentType),
MockedContent.CreateSimpleContent(contentType)
};
ServiceContext.ContentService.Save(content);
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(0), ActionMove.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionBrowse.Instance.Letter, new int[] { userGroup.Id });
ServiceContext.ContentService.AssignContentPermission(content.ElementAt(1), ActionDelete.Instance.Letter, new int[] { userGroup.Id });
// Act
var permissions = userService.GetPermissions(userGroup, false, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id);
//assert
Assert.AreEqual(3, permissions.Count());
Assert.AreEqual(3, permissions.ElementAt(0).AssignedPermissions.Count());
Assert.AreEqual(2, permissions.ElementAt(1).AssignedPermissions.Count());
Assert.AreEqual(17, permissions.ElementAt(2).AssignedPermissions.Count());
}
[Test]
public void Can_Delete_User()
{
@@ -524,6 +589,17 @@ namespace Umbraco.Tests.Services
}
private IUser CreateTestUser()
{
var userGroup = CreateTestUserGroup();
var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com");
user.AddGroup(userGroup);
user.SetGroupsLoaded();
ServiceContext.UserService.Save(user);
return user;
}
private UserGroup CreateTestUserGroup()
{
var userGroup = new UserGroup
{
@@ -535,12 +611,7 @@ namespace Umbraco.Tests.Services
ServiceContext.UserService.SaveUserGroup(userGroup);
ServiceContext.UserService.AddSectionToAllUserGroups("content", 1);
ServiceContext.UserService.AddSectionToAllUserGroups("media", 1);
var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com");
user.AddGroup(userGroup);
user.SetGroupsLoaded();
ServiceContext.UserService.Save(user);
return user;
return userGroup;
}
}
}
+1 -14
View File
@@ -2,9 +2,7 @@
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Repositories;
using umbraco.interfaces;
namespace Umbraco.Web.Cache
{
@@ -31,8 +29,6 @@ namespace Umbraco.Web.Cache
public override void RefreshAll()
{
ClearAllIsolatedCacheByEntityType<IUser>();
if (UserPermissionsCache)
UserPermissionsCache.Result.ClearCacheByKeySearch(CacheKeys.UserPermissionsCacheKey);
base.RefreshAll();
}
@@ -47,17 +43,8 @@ namespace Umbraco.Web.Cache
var userCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<IUser>();
if (userCache)
userCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey<IUser>(id));
if (UserPermissionsCache)
UserPermissionsCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.UserPermissionsCacheKey, id));
base.Remove(id);
}
private Attempt<IRuntimeCacheProvider> UserPermissionsCache
{
get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<EntityPermission>(); }
}
}
}
@@ -60,7 +60,7 @@ namespace Umbraco.Web.Cache
private Attempt<IRuntimeCacheProvider> UserGroupPermissionsCache
{
get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<UserGroupEntityPermission>(); }
get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<EntityPermission>(); }
}
}
}
@@ -52,7 +52,7 @@ namespace Umbraco.Web.Cache
private Attempt<IRuntimeCacheProvider> UserGroupPermissionsCache
{
get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<UserGroupEntityPermission>(); }
get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache<EntityPermission>(); }
}
}
}