Fixed caching issues on editing node permissions
This commit is contained in:
@@ -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")]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = "-";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user