diff --git a/src/Umbraco.Tests/Controllers/WebApiEditors/ContentControllerUnitTests.cs b/src/Umbraco.Tests/Controllers/WebApiEditors/ContentControllerUnitTests.cs index 679a55897a..45dd854f74 100644 --- a/src/Umbraco.Tests/Controllers/WebApiEditors/ContentControllerUnitTests.cs +++ b/src/Umbraco.Tests/Controllers/WebApiEditors/ContentControllerUnitTests.cs @@ -13,7 +13,7 @@ namespace Umbraco.Tests.Controllers.WebApiEditors public class ContentControllerUnitTests { [Test] - public void Does_Not_Throw_Exception_When_Access_Allowed_By_Path() + public void Access_Allowed_By_Path() { //arrange var userMock = new Mock(); @@ -26,13 +26,9 @@ namespace Umbraco.Tests.Controllers.WebApiEditors var contentServiceMock = new Mock(); contentServiceMock.Setup(x => x.GetById(1234)).Returns(content); var contentService = contentServiceMock.Object; - var userServiceMock = new Mock(); - var permissions = new List(); - userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions); - var userService = userServiceMock.Object; //act - var result = ContentController.CheckPermissions(new Dictionary(), user, userService, contentService, 1234, 'F'); + var result = ContentController.CheckPermissions(new Dictionary(), user, null, contentService, 1234); //assert Assert.IsTrue(result); @@ -62,7 +58,7 @@ namespace Umbraco.Tests.Controllers.WebApiEditors } [Test] - public void Throws_Exception_When_No_Access_By_Path() + public void No_Access_By_Path() { //arrange var userMock = new Mock(); @@ -88,7 +84,7 @@ namespace Umbraco.Tests.Controllers.WebApiEditors } [Test] - public void Throws_Exception_When_No_Access_By_Permission() + public void No_Access_By_Permission() { //arrange var userMock = new Mock(); @@ -117,7 +113,7 @@ namespace Umbraco.Tests.Controllers.WebApiEditors } [Test] - public void Does_Not_Throw_Exception_When_Access_Allowed_By_Permission() + public void Access_Allowed_By_Permission() { //arrange var userMock = new Mock(); @@ -146,34 +142,166 @@ namespace Umbraco.Tests.Controllers.WebApiEditors } [Test] - public void Does_Not_Throw_Exception_When_No_Permissions_Assigned() + public void Access_To_Root_By_Path() { //arrange var userMock = new Mock(); - userMock.Setup(u => u.Id).Returns(9); + userMock.Setup(u => u.Id).Returns(0); userMock.Setup(u => u.StartContentId).Returns(-1); var user = userMock.Object; - var contentMock = new Mock(); - contentMock.Setup(c => c.Path).Returns("-1,1234,5678"); - var content = contentMock.Object; - var contentServiceMock = new Mock(); - contentServiceMock.Setup(x => x.GetById(1234)).Returns(content); - var contentService = contentServiceMock.Object; - var userServiceMock = new Mock(); - var permissions = new List(); - userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions); - var userService = userServiceMock.Object; - + //act - var result = ContentController.CheckPermissions(new Dictionary(), user, userService, contentService, 1234, 'F'); + var result = ContentController.CheckPermissions(new Dictionary(), user, null, null, -1); //assert Assert.IsTrue(result); } - } + [Test] + public void Access_To_Recycle_Bin_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(-1); + var user = userMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, null, null, -20); - //we REALLY need a way to nicely mock the service context, etc... so we don't have to do integration tests... coming soon. + //assert + Assert.IsTrue(result); + } + + [Test] + public void No_Access_To_Recycle_Bin_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(1234); + var user = userMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, null, null, -20); + + //assert + Assert.IsFalse(result); + } + + [Test] + public void No_Access_To_Root_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(1234); + var user = userMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, null, null, -1); + + //assert + Assert.IsFalse(result); + } + + [Test] + public void Access_To_Root_By_Permission() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(-1); + var user = userMock.Object; + + var userServiceMock = new Mock(); + var permissions = new List + { + new EntityPermission(9, 1234, new string[]{ "A" }) + }; + userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions); + var userService = userServiceMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, userService, null, -1, 'A'); + + //assert + Assert.IsTrue(result); + } + + [Test] + public void No_Access_To_Root_By_Permission() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(-1); + var user = userMock.Object; + + var userServiceMock = new Mock(); + var permissions = new List + { + new EntityPermission(9, 1234, new string[]{ "A" }) + }; + userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions); + var userService = userServiceMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, userService, null, -1, 'B'); + + //assert + Assert.IsFalse(result); + } + + [Test] + public void Access_To_Recycle_Bin_By_Permission() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(-1); + var user = userMock.Object; + + var userServiceMock = new Mock(); + var permissions = new List + { + new EntityPermission(9, 1234, new string[]{ "A" }) + }; + userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions); + var userService = userServiceMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, userService, null, -20, 'A'); + + //assert + Assert.IsTrue(result); + } + + [Test] + public void No_Access_To_Recycle_Bin_By_Permission() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartContentId).Returns(-1); + var user = userMock.Object; + + var userServiceMock = new Mock(); + var permissions = new List + { + new EntityPermission(9, 1234, new string[]{ "A" }) + }; + userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions); + var userService = userServiceMock.Object; + + //act + var result = ContentController.CheckPermissions(new Dictionary(), user, userService, null, -20, 'B'); + + //assert + Assert.IsFalse(result); + } + + } //NOTE: The below self hosted stuff does work so need to get some tests written. Some are not possible atm because // of the legacy SQL calls like checking permissions. diff --git a/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs b/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs index 0a81bc1b4b..c24b5059a2 100644 --- a/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs +++ b/src/Umbraco.Tests/Controllers/WebApiEditors/MediaControllerUnitTests.cs @@ -13,7 +13,7 @@ namespace Umbraco.Tests.Controllers.WebApiEditors public class MediaControllerUnitTests { [Test] - public void Does_Not_Throw_Exception_When_Access_Allowed_By_Path() + public void Access_Allowed_By_Path() { //arrange var userMock = new Mock(); @@ -54,7 +54,7 @@ namespace Umbraco.Tests.Controllers.WebApiEditors } [Test] - public void Throws_Exception_When_No_Access_By_Path() + public void No_Access_By_Path() { //arrange var userMock = new Mock(); @@ -75,5 +75,68 @@ namespace Umbraco.Tests.Controllers.WebApiEditors Assert.IsFalse(result); } + [Test] + public void Access_To_Root_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartMediaId).Returns(-1); + var user = userMock.Object; + + //act + var result = MediaController.CheckPermissions(new Dictionary(), user, null, -1); + + //assert + Assert.IsTrue(result); + } + + [Test] + public void No_Access_To_Root_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartMediaId).Returns(1234); + var user = userMock.Object; + + //act + var result = MediaController.CheckPermissions(new Dictionary(), user, null, -1); + + //assert + Assert.IsFalse(result); + } + + [Test] + public void Access_To_Recycle_Bin_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartMediaId).Returns(-1); + var user = userMock.Object; + + //act + var result = MediaController.CheckPermissions(new Dictionary(), user, null, -21); + + //assert + Assert.IsTrue(result); + } + + [Test] + public void No_Access_To_Recycle_Bin_By_Path() + { + //arrange + var userMock = new Mock(); + userMock.Setup(u => u.Id).Returns(0); + userMock.Setup(u => u.StartMediaId).Returns(1234); + var user = userMock.Object; + + //act + var result = MediaController.CheckPermissions(new Dictionary(), user, null, -21); + + //assert + Assert.IsFalse(result); + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index d07c4c02b2..2875eb446d 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -190,7 +190,6 @@ namespace Umbraco.Web.Editors //TODO: We need to support 'send to publish' - //TODO: We'll need to save the new template, publishat, etc... values here contentItem.PersistedContent.ExpireDate = contentItem.ExpireDate; contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate; //only set the template if it didn't change @@ -323,7 +322,7 @@ namespace Umbraco.Web.Editors /// attributed with EnsureUserPermissionForContent to verify the user has access to the recycle bin /// [HttpDelete] - /* [EnsureUserPermissionForContent(Constants.System.RecycleBinContent)]*/ + [EnsureUserPermissionForContent(Constants.System.RecycleBinContent)] public HttpResponseMessage EmptyRecycleBin() { Services.ContentService.EmptyRecycleBin(); @@ -532,11 +531,11 @@ namespace Umbraco.Web.Editors IUserService userService, IContentService contentService, int nodeId, - char permissionToCheck, + char? permissionToCheck = null, IContent contentItem = null) { - if (contentItem == null && nodeId != Constants.System.Root) + if (contentItem == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinContent) { contentItem = contentService.GetById(nodeId); //put the content item into storage so it can be retreived @@ -544,29 +543,41 @@ namespace Umbraco.Web.Editors storage[typeof(IContent).ToString()] = contentItem; } - if (contentItem == null && nodeId != Constants.System.Root) + if (contentItem == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinContent) { throw new HttpResponseException(HttpStatusCode.NotFound); } var hasPathAccess = (nodeId == Constants.System.Root) - ? UserExtensions.HasPathAccess("-1", user.StartContentId, Constants.System.RecycleBinContent) - : user.HasPathAccess(contentItem); + ? UserExtensions.HasPathAccess( + Constants.System.Root.ToInvariantString(), + user.StartContentId, + Constants.System.RecycleBinContent) + : (nodeId == Constants.System.RecycleBinContent) + ? UserExtensions.HasPathAccess( + Constants.System.RecycleBinContent.ToInvariantString(), + user.StartContentId, + Constants.System.RecycleBinContent) + : user.HasPathAccess(contentItem); if (hasPathAccess == false) { return false; } - var permission = userService.GetPermissions(user, nodeId).FirstOrDefault(); - if (permission == null || permission.AssignedPermissions.Contains(permissionToCheck.ToString(CultureInfo.InvariantCulture))) + if (permissionToCheck.HasValue == false) { return true; } - else + + var permission = userService.GetPermissions(user, nodeId).FirstOrDefault(); + + if (permission != null && permission.AssignedPermissions.Contains(permissionToCheck.Value.ToString(CultureInfo.InvariantCulture))) { - return false; + return true; } + + return false; } } diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 768b4b628c..728510e75a 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -464,7 +464,7 @@ namespace Umbraco.Web.Editors /// internal static bool CheckPermissions(IDictionary storage, IUser user, IMediaService mediaService, int nodeId, IMedia media = null) { - if (media == null && nodeId != Constants.System.Root) + if (media == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinMedia) { media = mediaService.GetById(nodeId); //put the content item into storage so it can be retreived @@ -472,14 +472,22 @@ namespace Umbraco.Web.Editors storage[typeof(IMedia).ToString()] = media; } - if (media == null && nodeId != Constants.System.Root) + if (media == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinMedia) { throw new HttpResponseException(HttpStatusCode.NotFound); } var hasPathAccess = (nodeId == Constants.System.Root) - ? UserExtensions.HasPathAccess("-1", user.StartMediaId, Constants.System.RecycleBinMedia) - : user.HasPathAccess(media); + ? UserExtensions.HasPathAccess( + Constants.System.Root.ToInvariantString(), + user.StartMediaId, + Constants.System.RecycleBinMedia) + : (nodeId == Constants.System.RecycleBinMedia) + ? UserExtensions.HasPathAccess( + Constants.System.RecycleBinMedia.ToInvariantString(), + user.StartMediaId, + Constants.System.RecycleBinMedia) + : user.HasPathAccess(media); return hasPathAccess; } diff --git a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs index a968deef2e..3fe408fa12 100644 --- a/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.WebApi.Filters { private readonly int? _nodeId; private readonly string _paramName; - private readonly char _permissionToCheck; + private readonly char? _permissionToCheck; /// /// This constructor will only be able to test the start node access