From 5036df4174e83dd4624a130db91cc79fae7666e3 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 10 Sep 2013 13:38:45 +1000 Subject: [PATCH] Fixes permissions issue with default permissions and ensures default permissions come from the user type instead of the unused db column in the umbracoUser table. Fixes up the FilterAllowedOutgoingContentAttributeTests attribute with the new permissions changes. Fixes: U4-2771 Content sort dialog, ysod on loading children --- .../Models/Membership/EntityPermission.cs | 7 +- src/Umbraco.Core/Models/Membership/IUser.cs | 9 +- .../Persistence/Factories/UserFactory.cs | 10 +- .../Persistence/Mappers/UserMapper.cs | 3 +- .../Repositories/ContentRepository.cs | 4 +- .../Interfaces/IContentRepository.cs | 2 +- .../Repositories/PermissionRepository.cs | 13 +- .../Repositories/UserRepository.cs | 6 + src/Umbraco.Core/Services/ContentService.cs | 12 ++ src/Umbraco.Core/Services/IContentService.cs | 2 + src/Umbraco.Core/Services/UserService.cs | 25 +++- ...terAllowedOutgoingContentAttributeTests.cs | 130 ++++++++++++++++++ .../WebApiEditors/MediaControllerUnitTests.cs | 122 ---------------- .../Repositories/ContentRepositoryTest.cs | 2 +- .../Repositories/UserRepositoryTest.cs | 23 +++- .../Services/UserServiceTests.cs | 67 +++++++++ src/Umbraco.Tests/Umbraco.Tests.csproj | 1 + .../FilterAllowedOutgoingContentAttribute.cs | 6 +- 18 files changed, 300 insertions(+), 144 deletions(-) create mode 100644 src/Umbraco.Tests/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs diff --git a/src/Umbraco.Core/Models/Membership/EntityPermission.cs b/src/Umbraco.Core/Models/Membership/EntityPermission.cs index 8a72eb69ba..c417a4985c 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermission.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermission.cs @@ -12,12 +12,13 @@ AssignedPermissions = assignedPermissions; } - public object UserId { get; set; } - public int EntityId { get; set; } + public object UserId { get; private set; } + public int EntityId { get; private set; } /// /// The assigned permissions for the user/entity combo /// - public string[] AssignedPermissions { get; set; } + public string[] AssignedPermissions { get; private set; } } + } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index 268ed04219..264ccbf1a7 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -19,7 +19,14 @@ namespace Umbraco.Core.Models.Membership bool NoConsole { get; set; } IUserType UserType { get; } - string DefaultPermissions { get; set; } + + /// + /// The default permissions for the user + /// + /// + /// The default permissions are assigned to the user object based on the user type's default permissions + /// + string DefaultPermissions { get; } } internal interface IUserProfile : IProfile diff --git a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs index 0a046ca7a0..c1be1d360b 100644 --- a/src/Umbraco.Core/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/UserFactory.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Globalization; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; @@ -32,7 +33,9 @@ namespace Umbraco.Core.Persistence.Factories Language = dto.UserLanguage, DefaultToLiveEditing = dto.DefaultToLiveEditing, NoConsole = dto.NoConsole, - DefaultPermissions = dto.DefaultPermissions + + //NOTE: The umbracoUser.DefaultPermissions column is never used, the default permission come from the user type's default permissions + DefaultPermissions = _userType.Permissions }; foreach (var app in dto.User2AppDtos) @@ -61,8 +64,9 @@ namespace Umbraco.Core.Persistence.Factories Password = entity.Password, UserLanguage = entity.Language, UserName = entity.Name, - Type = short.Parse(entity.UserType.Id.ToString()), - DefaultPermissions = entity.DefaultPermissions, + Type = short.Parse(entity.UserType.Id.ToString(CultureInfo.InvariantCulture)), + //NOTE: This column in the db is *not* used so we'll just let it remain null + DefaultPermissions = null, User2AppDtos = new List() }; diff --git a/src/Umbraco.Core/Persistence/Mappers/UserMapper.cs b/src/Umbraco.Core/Persistence/Mappers/UserMapper.cs index 5e2947c3a7..68bf091fc5 100644 --- a/src/Umbraco.Core/Persistence/Mappers/UserMapper.cs +++ b/src/Umbraco.Core/Persistence/Mappers/UserMapper.cs @@ -33,7 +33,8 @@ namespace Umbraco.Core.Persistence.Mappers CacheMap(src => src.Username, dto => dto.Login); CacheMap(src => src.Password, dto => dto.Password); CacheMap(src => src.Name, dto => dto.UserName); - CacheMap(src => src.DefaultPermissions, dto => dto.DefaultPermissions); + //NOTE: This column in the db is *not* used! + //CacheMap(src => src.DefaultPermissions, dto => dto.DefaultPermissions); CacheMap(src => src.StartMediaId, dto => dto.MediaStartId); CacheMap(src => src.StartContentId, dto => dto.ContentStartId); CacheMap(src => src.DefaultToLiveEditing, dto => dto.DefaultToLiveEditing); diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index a4351ef99f..da34715234 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -251,7 +251,7 @@ namespace Umbraco.Core.Persistence.Repositories var userPermissions = ( from perm in parentPermissions from p in perm.AssignedPermissions - select new KeyValuePair(perm.UserId, p)).ToList(); + select new Tuple(perm.UserId, p)).ToList(); permissionsRepo.AssignEntityPermissions(entity, userPermissions); //flag the entity's permissions changed flag so we can track those changes. @@ -505,7 +505,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetByVersion(dto.ContentVersionDto.VersionId); } - public void AssignEntityPermissions(IContent entity, string permission, IEnumerable userIds) + public void AssignEntityPermissions(IContent entity, char permission, IEnumerable userIds) { var repo = new PermissionRepository(UnitOfWork); repo.AssignEntityPermissions(entity, permission, userIds); diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs index 92748f1029..06beebda9e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IContentRepository.cs @@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Repositories /// An enumerable list of IEnumerable GetByPublishedVersion(IQuery query); - void AssignEntityPermissions(IContent entity, string permission, IEnumerable userIds); + void AssignEntityPermissions(IContent entity, char permission, IEnumerable userIds); IEnumerable GetPermissionsForEntity(int entityId); } diff --git a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs index f61f4f0d33..d04a3fc9bf 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Dynamic; +using System.Globalization; using System.Linq; using System.Text; using Umbraco.Core.Models; @@ -32,7 +33,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - /// + /// internal IEnumerable GetUserPermissionsForEntities(object userId, params int[] entityIds) { var whereBuilder = new StringBuilder(); @@ -108,12 +109,12 @@ namespace Umbraco.Core.Persistence.Repositories /// /// /// - internal void AssignEntityPermissions(TEntity entity, string permission, IEnumerable userIds) + internal void AssignEntityPermissions(TEntity entity, char permission, IEnumerable userIds) { var actions = userIds.Select(id => new User2NodePermissionDto { NodeId = entity.Id, - Permission = permission, + Permission = permission.ToString(CultureInfo.InvariantCulture), UserId = (int)id }); @@ -127,13 +128,13 @@ namespace Umbraco.Core.Persistence.Repositories /// /// A key/value pair list containing a userId and a permission to assign /// - internal void AssignEntityPermissions(TEntity entity, IEnumerable> userPermissions) + internal void AssignEntityPermissions(TEntity entity, IEnumerable> userPermissions) { var actions = userPermissions.Select(p => new User2NodePermissionDto { NodeId = entity.Id, - Permission = p.Value, - UserId = (int)p.Key + Permission = p.Item2, + UserId = (int)p.Item1 }); _unitOfWork.Database.BulkInsertRecords(actions); diff --git a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs index 00438bb935..144e2a9d8f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UserRepository.cs @@ -223,6 +223,12 @@ namespace Umbraco.Core.Persistence.Repositories return ConvertFromDtos(Database.Fetch(new UserSectionRelator().Map, sql)); } + /// + /// Returns permissions for a given user for any number of nodes + /// + /// + /// + /// public IEnumerable GetUserPermissionsForEntities(object userId, params int[] entityIds) { var repo = new PermissionRepository(UnitOfWork); diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 6d0e002eea..225e523493 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; +using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Caching; @@ -57,6 +58,17 @@ namespace Umbraco.Core.Services _repositoryFactory = repositoryFactory; } + //TODO: There are various ways to expose permission setting on this service, we just need to list out the different ways we'll need to + // be able to acheive this for the core, for now this is here so I can run a unit test. + internal void AssignContentPermissions(IContent entity, char permission, IEnumerable userIds) + { + var uow = _uowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateContentRepository(uow)) + { + repository.AssignEntityPermissions(entity, permission, userIds); + } + } + /// /// Creates an object using the alias of the /// that this Content should based on. diff --git a/src/Umbraco.Core/Services/IContentService.cs b/src/Umbraco.Core/Services/IContentService.cs index 6525a9d825..2d5a44e0ff 100644 --- a/src/Umbraco.Core/Services/IContentService.cs +++ b/src/Umbraco.Core/Services/IContentService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Umbraco.Core.Models; +using Umbraco.Core.Models.Membership; namespace Umbraco.Core.Services { @@ -9,6 +10,7 @@ namespace Umbraco.Core.Services /// public interface IContentService : IService { + /// /// Creates an object using the alias of the /// that this Content should based on. diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index 7118e5cc1e..421283e3e1 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -168,12 +168,35 @@ namespace Umbraco.Core.Services return uow.Database.Fetch(sql); } + /// + /// Returns permissions for a given user for any number of nodes + /// + /// + /// + /// + /// + /// If no permissions are found for a particular entity then the user's default permissions will be applied + /// public IEnumerable GetPermissions(IUser user, params int[] nodeIds) { var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateUserRepository(uow)) { - return repository.GetUserPermissionsForEntities(user.Id, nodeIds); + var explicitPermissions = repository.GetUserPermissionsForEntities(user.Id, nodeIds); + + //if no permissions are assigned to a particular node then we will fill in those permissions with the user's defaults + var result = new List(explicitPermissions); + var missingIds = nodeIds.Except(result.Select(x => x.EntityId)); + foreach(var id in missingIds) + { + result.Add( + new EntityPermission( + user.Id, + id, + user.DefaultPermissions.ToCharArray().Select(c => c.ToString(CultureInfo.InvariantCulture)).ToArray())); + } + + return result; } } diff --git a/src/Umbraco.Tests/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs b/src/Umbraco.Tests/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs new file mode 100644 index 0000000000..510941ed0c --- /dev/null +++ b/src/Umbraco.Tests/Controllers/WebApiEditors/FilterAllowedOutgoingContentAttributeTests.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Formatting; +using System.Net.Http.Headers; +using NUnit.Framework; +using Rhino.Mocks; +using Umbraco.Core; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.WebApi.Filters; + +namespace Umbraco.Tests.Controllers.WebApiEditors +{ + [TestFixture] + public class FilterAllowedOutgoingContentAttributeTests + { + [Test] + public void GetValueFromResponse_Already_EnumerableContent() + { + var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable)); + var val = new List() {new ContentItemBasic()}; + var result = att.GetValueFromResponse( + new ObjectContent(typeof (IEnumerable), + val, + new JsonMediaTypeFormatter(), + new MediaTypeHeaderValue("html/text"))); + + Assert.AreEqual(val, result); + Assert.AreEqual(1, ((IEnumerable)result).Count()); + } + + [Test] + public void GetValueFromResponse_From_Property() + { + var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable), "MyList"); + var val = new List() { new ContentItemBasic() }; + var container = new MyTestClass() {MyList = val}; + + var result = att.GetValueFromResponse( + new ObjectContent(typeof(MyTestClass), + container, + new JsonMediaTypeFormatter(), + new MediaTypeHeaderValue("html/text"))); + + Assert.AreEqual(val, result); + Assert.AreEqual(1, ((IEnumerable)result).Count()); + } + + [Test] + public void GetValueFromResponse_Returns_Null_Not_Found_Property() + { + var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable), "DontFind"); + var val = new List() { new ContentItemBasic() }; + var container = new MyTestClass() { MyList = val }; + + var result = att.GetValueFromResponse( + new ObjectContent(typeof(MyTestClass), + container, + new JsonMediaTypeFormatter(), + new MediaTypeHeaderValue("html/text"))); + + Assert.AreEqual(null, result); + + } + + [Test] + public void Filter_On_Start_Node() + { + var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable)); + var list = new List(); + var path = ""; + for (var i = 0; i < 10; i++) + { + if (i > 0 && path.EndsWith(",") == false) + { + path += ","; + } + path += i.ToInvariantString(); + list.Add(new ContentItemBasic { Id = i, Name = "Test" + i, ParentId = i, Path = path }); + } + var user = MockRepository.GenerateStub(); + user.Id = 9; + user.StartContentId = 5; + + att.FilterBasedOnStartNode(list, user); + + Assert.AreEqual(5, list.Count); + + } + + [Test] + public void Filter_On_Permissions() + { + var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable)); + var list = new List(); + for (var i = 0; i < 10; i++) + { + list.Add(new ContentItemBasic{Id = i, Name = "Test" + i, ParentId = -1}); + } + var ids = list.Select(x => (int)x.Id).ToArray(); + var user = MockRepository.GenerateStub(); + user.Id = 9; + user.StartContentId = -1; + var userService = MockRepository.GenerateStub(); + //we're only assigning 3 nodes browse permissions so that is what we expect as a result + var permissions = new List + { + new EntityPermission(9, 1, new string[]{ "F" }), + new EntityPermission(9, 2, new string[]{ "F" }), + new EntityPermission(9, 3, new string[]{ "F" }), + new EntityPermission(9, 4, new string[]{ "A" }) + }; + userService.Stub(x => x.GetPermissions(user, ids)).Return(permissions); + + att.FilterBasedOnPermissions(list, user, userService); + + Assert.AreEqual(3, list.Count); + Assert.AreEqual(1, list.ElementAt(0).Id); + Assert.AreEqual(2, list.ElementAt(1).Id); + Assert.AreEqual(3, list.ElementAt(2).Id); + } + + private class MyTestClass + { + public IEnumerable MyList { get; set; } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs b/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs index c9704a8cf5..9a04aab6cd 100644 --- a/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs +++ b/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs @@ -1,136 +1,14 @@ using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Net.Http.Headers; using System.Web.Http; using NUnit.Framework; using Rhino.Mocks; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Editors; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.WebApi.Filters; namespace Umbraco.Tests.Controllers.WebApiEditors { - [TestFixture] - public class FilterAllowedOutgoingContentAttributeTests - { - [Test] - public void GetValueFromResponse_Already_EnumerableContent() - { - var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable)); - var val = new List() {new ContentItemBasic()}; - var result = att.GetValueFromResponse( - new ObjectContent(typeof (IEnumerable), - val, - new JsonMediaTypeFormatter(), - new MediaTypeHeaderValue("html/text"))); - - Assert.AreEqual(val, result); - Assert.AreEqual(1, ((IEnumerable)result).Count()); - } - - [Test] - public void GetValueFromResponse_From_Property() - { - var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable), "MyList"); - var val = new List() { new ContentItemBasic() }; - var container = new MyTestClass() {MyList = val}; - - var result = att.GetValueFromResponse( - new ObjectContent(typeof(MyTestClass), - container, - new JsonMediaTypeFormatter(), - new MediaTypeHeaderValue("html/text"))); - - Assert.AreEqual(val, result); - Assert.AreEqual(1, ((IEnumerable)result).Count()); - } - - [Test] - public void GetValueFromResponse_Returns_Null_Not_Found_Property() - { - var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable), "DontFind"); - var val = new List() { new ContentItemBasic() }; - var container = new MyTestClass() { MyList = val }; - - var result = att.GetValueFromResponse( - new ObjectContent(typeof(MyTestClass), - container, - new JsonMediaTypeFormatter(), - new MediaTypeHeaderValue("html/text"))); - - Assert.AreEqual(null, result); - - } - - [Test] - public void Filter_On_Start_Node() - { - var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable)); - var list = new List(); - var path = ""; - for (var i = 0; i < 10; i++) - { - if (i > 0 && path.EndsWith(",") == false) - { - path += ","; - } - path += i.ToInvariantString(); - list.Add(new ContentItemBasic { Id = i, Name = "Test" + i, ParentId = i, Path = path }); - } - var user = MockRepository.GenerateStub(); - user.Id = 9; - user.StartContentId = 5; - - att.FilterBasedOnStartNode(list, user); - - Assert.AreEqual(5, list.Count); - - } - - [Test] - public void Filter_On_Permissions() - { - var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable)); - var list = new List(); - for (var i = 0; i < 10; i++) - { - list.Add(new ContentItemBasic{Id = i, Name = "Test" + i, ParentId = -1}); - } - var ids = list.Select(x => (int)x.Id).ToArray(); - var user = MockRepository.GenerateStub(); - user.Id = 9; - user.StartContentId = -1; - var userService = MockRepository.GenerateStub(); - //we're only assigning 3 nodes browse permissions so that is what we expect as a result - var permissions = new List - { - new EntityPermission(9, 1, new string[]{ "F" }), - new EntityPermission(9, 2, new string[]{ "F" }), - new EntityPermission(9, 3, new string[]{ "F" }), - new EntityPermission(9, 4, new string[]{ "A" }) - }; - userService.Stub(x => x.GetPermissions(user, ids)).Return(permissions); - - att.FilterBasedOnPermissions(list, user, userService); - - Assert.AreEqual(3, list.Count); - Assert.AreEqual(1, list.ElementAt(0).Id); - Assert.AreEqual(2, list.ElementAt(1).Id); - Assert.AreEqual(3, list.ElementAt(2).Id); - } - - private class MyTestClass - { - public IEnumerable MyList { get; set; } - } - } - [TestFixture] public class MediaControllerUnitTests { diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index 301b844be4..388c390234 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -59,7 +59,7 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); // Act - repository.AssignEntityPermissions(parentPage, "A", new object[] {0}); + repository.AssignEntityPermissions(parentPage, 'A', new object[] {0}); var childPage = MockedContent.CreateSimpleContent(contentType, "child", parentPage); repository.AddOrUpdate(childPage); unitOfWork.Commit(); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 4c3026e27b..011cf2e2b1 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -115,7 +115,8 @@ namespace Umbraco.Tests.Persistence.Repositories var resolved = repository.Get((int)user.Id); resolved.Name = "New Name"; - resolved.DefaultPermissions = "ZYX"; + //the db column is not used, default permissions are taken from the user type's permissions, this is a getter only + //resolved.DefaultPermissions = "ZYX"; resolved.Language = "fr"; resolved.IsApproved = false; resolved.Password = "new"; @@ -134,7 +135,7 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(updatedItem.Id, Is.EqualTo(resolved.Id)); Assert.That(updatedItem.Name, Is.EqualTo(resolved.Name)); - Assert.That(updatedItem.DefaultPermissions, Is.EqualTo(resolved.DefaultPermissions)); + //Assert.That(updatedItem.DefaultPermissions, Is.EqualTo(resolved.DefaultPermissions)); Assert.That(updatedItem.Language, Is.EqualTo(resolved.Language)); Assert.That(updatedItem.IsApproved, Is.EqualTo(resolved.IsApproved)); Assert.That(updatedItem.Password, Is.EqualTo(resolved.Password)); @@ -427,6 +428,24 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.IsTrue(names.Contains("TestUser3")); } + [Test] + public void Default_User_Permissions_Based_On_User_Type() + { + // Arrange + var provider = new PetaPocoUnitOfWorkProvider(); + var unitOfWork = provider.GetUnitOfWork(); + var repository = RepositoryResolver.Current.ResolveByType(unitOfWork); + + + // Act + var user1 = MockedUser.CreateUser(CreateAndCommitUserType(), "1", "test", "media"); + repository.AddOrUpdate(user1); + unitOfWork.Commit(); + + // Assert + Assert.AreEqual("ABC", user1.DefaultPermissions); + } + private void AssertPropertyValues(IUser updatedItem, IUser originalUser) { Assert.That(updatedItem.Id, Is.EqualTo(originalUser.Id)); diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index b8cc7f6225..b36520d927 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -4,6 +4,9 @@ using System.Security.Cryptography; using System.Text; using NUnit.Framework; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Services; +using Umbraco.Tests.TestHelpers.Entities; +using umbraco.BusinessLogic.Actions; namespace Umbraco.Tests.Services { @@ -25,6 +28,70 @@ namespace Umbraco.Tests.Services base.TearDown(); } + [Test] + public void UserService_Get_User_Permissions_For_Unassigned_Permission_Nodes() + { + // Arrange + var userService = ServiceContext.UserService; + var userType = userService.GetUserTypeByAlias("admin"); + //we know this actually is an IUser so we'll just cast + var user = (IUser)ServiceContext.UserService.CreateMembershipUser("test1", "test1", "test1", userType, "test1@test.com"); + var contentType = MockedContentTypes.CreateSimpleContentType(); + ServiceContext.ContentTypeService.Save(contentType); + var content = new [] + { + MockedContent.CreateSimpleContent(contentType), + MockedContent.CreateSimpleContent(contentType), + MockedContent.CreateSimpleContent(contentType) + }; + ServiceContext.ContentService.Save(content); + + // Act + var permissions = userService.GetPermissions(user, content.ElementAt(0).Id, content.ElementAt(1).Id, content.ElementAt(2).Id); + + //assert + Assert.AreEqual(3, permissions.Count()); + Assert.AreEqual(17, permissions.ElementAt(0).AssignedPermissions.Count()); + Assert.AreEqual(17, permissions.ElementAt(1).AssignedPermissions.Count()); + Assert.AreEqual(17, permissions.ElementAt(2).AssignedPermissions.Count()); + } + + [Test] + public void UserService_Get_User_Permissions_For_Assigned_Permission_Nodes() + { + // Arrange + var userService = ServiceContext.UserService; + var userType = userService.GetUserTypeByAlias("admin"); + //we know this actually is an IUser so we'll just cast + var user = (IUser)ServiceContext.UserService.CreateMembershipUser("test1", "test1", "test1", userType, "test1@test.com"); + var contentType = MockedContentTypes.CreateSimpleContentType(); + ServiceContext.ContentTypeService.Save(contentType); + var content = new[] + { + MockedContent.CreateSimpleContent(contentType), + MockedContent.CreateSimpleContent(contentType), + MockedContent.CreateSimpleContent(contentType) + }; + ServiceContext.ContentService.Save(content); + ((ContentService)ServiceContext.ContentService).AssignContentPermissions(content.ElementAt(0), ActionBrowse.Instance.Letter, new object[] { user.Id }); + ((ContentService)ServiceContext.ContentService).AssignContentPermissions(content.ElementAt(0), ActionDelete.Instance.Letter, new object[] { user.Id }); + ((ContentService)ServiceContext.ContentService).AssignContentPermissions(content.ElementAt(0), ActionMove.Instance.Letter, new object[] { user.Id }); + + ((ContentService)ServiceContext.ContentService).AssignContentPermissions(content.ElementAt(1), ActionBrowse.Instance.Letter, new object[] { user.Id }); + ((ContentService)ServiceContext.ContentService).AssignContentPermissions(content.ElementAt(1), ActionDelete.Instance.Letter, new object[] { user.Id }); + + ((ContentService)ServiceContext.ContentService).AssignContentPermissions(content.ElementAt(2), ActionBrowse.Instance.Letter, new object[] { user.Id }); + + // Act + var permissions = userService.GetPermissions(user, 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_Can_Persist_New_User() { diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index b1840c6915..92720fe76c 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -234,6 +234,7 @@ + diff --git a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs index dda78dc4d2..8193b528f6 100644 --- a/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/FilterAllowedOutgoingContentAttribute.cs @@ -34,6 +34,7 @@ namespace Umbraco.Web.WebApi.Filters public FilterAllowedOutgoingContentAttribute(Type outgoingType, string propertyName) : base(outgoingType, propertyName) { + _permissionToCheck = ActionBrowse.Instance.Letter; } protected override void FilterItems(IUser user, IList items) @@ -57,9 +58,12 @@ namespace Umbraco.Web.WebApi.Filters foreach(dynamic item in items) { var nodePermission = permissions.Where(x => x.EntityId == item.Id).ToArray(); - //if there are no permissions for this id, then remove the item + //if there are no permissions for this id then we need to check what the user's default + // permissions are. if (nodePermission.Any() == false) { + //var defaultP = user.DefaultPermissions + toRemove.Add(item); } else