diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index 596bf2455b..02b01f1e78 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -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")] diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 08454c3b86..dafe746fc8 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -71,6 +71,18 @@ namespace Umbraco.Core.Services /// An enumerable list of IEnumerable GetPermissions(IUser user, params int[] nodeIds); + /// + /// Get permissions set for a group and optional node Ids + /// + /// Group to retrieve permissions for + /// + /// 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 + /// + /// Specifiying nothing will return all permissions for all nodes + /// An enumerable list of + IEnumerable GetPermissions(IUserGroup group, bool directlyAssignedOnly, params int[] nodeIds); + /// /// Gets the permissions for the provided user and path /// @@ -84,8 +96,12 @@ namespace Umbraco.Core.Services /// /// User to check permissions for /// Path to check permissions for + /// + /// 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 + /// /// String indicating permissions for provided user and path - string GetPermissionsForPath(IUserGroup group, string path); + string GetPermissionsForPath(IUserGroup group, string path, bool directlyAssignedOnly = true); /// /// Replaces the same permission set for a single group to any number of entities diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index 45dc0c921d..81a71e0f05 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -767,7 +767,7 @@ namespace Umbraco.Core.Services var result = new List(); 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; } + /// + /// Get permissions set for a group and node Id + /// + /// Group to retrieve permissions for + /// + /// 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 + /// + /// Specifiying nothing will return all permissions for all nodes + /// An enumerable list of + public IEnumerable 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(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; + } + } + /// /// For an existing list of , takes a new 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 GetPermissionsForGroupsAndPath(IEnumerable 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 /// /// User to check permissions for /// Path to check permissions for + /// + /// 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 + /// /// String indicating permissions for provided user and path - 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; } /// @@ -863,32 +904,6 @@ namespace Umbraco.Core.Services : int.Parse(path); } - /// - /// Get permissions set for a group and node Id - /// - /// Group to retrieve permissions for - /// Specifiying nothing will return all permissions for all nodes - /// An enumerable list of - private IEnumerable 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(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 = "-"; diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index 795088f48f..8992eebd95 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -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; } } } diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs index 6f9cc7db80..861d5e6abf 100644 --- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs @@ -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(); - if (UserPermissionsCache) - UserPermissionsCache.Result.ClearCacheByKeySearch(CacheKeys.UserPermissionsCacheKey); base.RefreshAll(); } @@ -47,17 +43,8 @@ namespace Umbraco.Web.Cache var userCache = ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache(); if (userCache) userCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey(id)); - - if (UserPermissionsCache) - UserPermissionsCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.UserPermissionsCacheKey, id)); - + base.Remove(id); } - - private Attempt UserPermissionsCache - { - get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache(); } - } - } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs index 60b5c9a710..5f36f60bab 100644 --- a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs @@ -60,7 +60,7 @@ namespace Umbraco.Web.Cache private Attempt UserGroupPermissionsCache { - get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache(); } + get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache(); } } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs index cf091b6618..8ea1b26f47 100644 --- a/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.Cache private Attempt UserGroupPermissionsCache { - get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache(); } + get { return ApplicationContext.Current.ApplicationCache.IsolatedRuntimeCache.GetCache(); } } } } \ No newline at end of file