diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
index ab473fd0c0..5031d178bf 100644
--- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/AuthenticateEverythingMiddleware.cs
@@ -8,6 +8,9 @@ using Umbraco.Core.Security;
namespace Umbraco.Tests.TestHelpers.ControllerTesting
{
+ ///
+ /// Ensures there's an admin user assigned to the request
+ ///
public class AuthenticateEverythingMiddleware : AuthenticationMiddleware
{
public AuthenticateEverythingMiddleware(OwinMiddleware next, IAppBuilder app, AuthenticationOptions options)
@@ -26,7 +29,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
{
var sessionId = Guid.NewGuid().ToString();
var identity = new UmbracoBackOfficeIdentity(
- -1, "admin", "Admin", null, null, "en-US", sessionId, sessionId, new[] { "content", "media", "members" }, new[] { "admin" });
+ -1, "admin", "Admin", new []{-1}, new[] { -1 }, "en-US", sessionId, sessionId, new[] { "content", "media", "members" }, new[] { "admin" });
return Task.FromResult(new AuthenticationTicket(identity,
new AuthenticationProperties()
diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs
index f64e8cb545..64a22926a0 100644
--- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs
+++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestRunner.cs
@@ -22,8 +22,16 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
_controllerFactory = controllerFactory;
}
- public async Task> Execute(string controllerName, string actionName, HttpMethod method, HttpContent content = null)
+ public async Task> Execute(string controllerName, string actionName, HttpMethod method,
+ HttpContent content = null,
+ MediaTypeWithQualityHeaderValue mediaTypeHeader = null,
+ bool assertOkResponse = true)
{
+ if (mediaTypeHeader == null)
+ {
+ mediaTypeHeader = new MediaTypeWithQualityHeaderValue("application/json");
+ }
+
var startup = new TestStartup(
configuration =>
{
@@ -44,7 +52,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
if (content != null)
request.Content = content;
- request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ request.Headers.Accept.Add(mediaTypeHeader);
Console.WriteLine(request);
var response = await server.HttpClient.SendAsync(request);
@@ -62,7 +70,11 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
Console.Write(JsonConvert.SerializeObject(deserialized, Formatting.Indented));
}
- Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ if (assertOkResponse)
+ {
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ }
+
return Tuple.Create(response, json);
}
}
diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj
index fc70e6ae9e..e842343e96 100644
--- a/src/Umbraco.Tests/Umbraco.Tests.csproj
+++ b/src/Umbraco.Tests/Umbraco.Tests.csproj
@@ -212,6 +212,7 @@
+
diff --git a/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs
new file mode 100644
index 0000000000..d8811c4237
--- /dev/null
+++ b/src/Umbraco.Tests/Web/Controllers/ContentControllerTests.cs
@@ -0,0 +1,208 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Web.Http;
+using Moq;
+using Newtonsoft.Json;
+using NUnit.Framework;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Models;
+using Umbraco.Core.Models.Entities;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Services;
+using Umbraco.Tests.TestHelpers;
+using Umbraco.Tests.TestHelpers.ControllerTesting;
+using Umbraco.Tests.TestHelpers.Entities;
+using Umbraco.Tests.Testing;
+using Umbraco.Web;
+using Umbraco.Web.Editors;
+using Umbraco.Web.Models.ContentEditing;
+using Umbraco.Web.PublishedCache;
+using Umbraco.Web._Legacy.Actions;
+using Task = System.Threading.Tasks.Task;
+
+namespace Umbraco.Tests.Web.Controllers
+{
+ [TestFixture]
+ [UmbracoTest(Database = UmbracoTestOptions.Database.None)]
+ public class ContentControllerTests : TestWithDatabaseBase
+ {
+ protected override void ComposeApplication(bool withApplication)
+ {
+ base.ComposeApplication(withApplication);
+
+ //Replace with mockable services:
+
+ var userServiceMock = new Mock();
+ userServiceMock.Setup(service => service.GetUserById(It.IsAny()))
+ .Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List(), new int[0], new int[0]) : null);
+ userServiceMock.Setup(service => service.GetPermissionsForPath(It.IsAny(), It.IsAny()))
+ .Returns(new EntityPermissionSet(123, new EntityPermissionCollection(new[]
+ {
+ new EntityPermission(0, 123, new[]
+ {
+ ActionBrowse.Instance.Letter.ToString(),
+ ActionUpdate.Instance.Letter.ToString(),
+ ActionPublish.Instance.Letter.ToString(),
+ ActionNew.Instance.Letter.ToString()
+ }),
+ })));
+
+ var entityService = new Mock();
+ entityService.Setup(x => x.GetAllPaths(UmbracoObjectTypes.Document, It.IsAny()))
+ .Returns((UmbracoObjectTypes objType, int[] ids) => ids.Select(x => new TreeEntityPath {Path = $"-1,{x}", Id = x}).ToList());
+
+ var dataTypeService = new Mock();
+ dataTypeService.Setup(service => service.GetDataType(It.IsAny()))
+ .Returns(MockedDataType());
+
+ Container.RegisterSingleton(f => Mock.Of());
+ Container.RegisterSingleton(f => userServiceMock.Object);
+ Container.RegisterSingleton(f => entityService.Object);
+ Container.RegisterSingleton(f => dataTypeService.Object);
+ }
+
+ private IDataType MockedDataType()
+ {
+ return Mock.Of(type => type.Id == 9876 && type.Name == "text");
+ }
+
+ private MultipartFormDataContent GetMultiPartRequestContent(string json)
+ {
+ var multiPartBoundary = "----WebKitFormBoundary123456789";
+ return new MultipartFormDataContent(multiPartBoundary)
+ {
+ new StringContent(json)
+ {
+ Headers =
+ {
+ ContentDisposition = new ContentDispositionHeaderValue("form-data")
+ {
+ Name = "contentItem"
+ }
+ }
+ }
+ };
+ }
+
+ private const string PublishJson1 = @"{
+ ""id"": 123,
+ ""contentTypeAlias"": ""page"",
+ ""parentId"": -1,
+ ""action"": ""save"",
+ ""variants"": [
+ {
+ ""name"": null,
+ ""properties"": [
+ {
+ ""id"": 1,
+ ""alias"": ""title"",
+ ""value"": ""asdf""
+ }
+ ],
+ ""culture"": ""en-US""
+ },
+ {
+ ""name"": null,
+ ""properties"": [
+ {
+ ""id"": 1,
+ ""alias"": ""title"",
+ ""value"": ""asdf""
+ }
+ ],
+ ""culture"": ""fr-FR""
+ },
+ {
+ ""name"": ""asdf"",
+ ""properties"": [
+ {
+ ""id"": 1,
+ ""alias"": ""title"",
+ ""value"": ""asdf""
+ }
+ ],
+ ""culture"": ""es-ES"",
+ ""save"": true,
+ ""publish"": true
+ }
+ ]
+}";
+
+ ///
+ /// Returns 404 if the content wasn't found based on the ID specified
+ ///
+ ///
+ [Test]
+ public async Task PostSave_Validate_Existing_Content()
+ {
+ ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
+ {
+ //var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
+ //content.Id = 999999999; //this will not be found
+ //content.Path = "-1,999999999";
+
+ var contentServiceMock = Mock.Get(Current.Services.ContentService);
+ contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
+
+ var publishedSnapshot = Mock.Of();
+ var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()));
+ var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
+ Container.InjectProperties(usersController);
+ return usersController;
+ }
+
+ var runner = new TestRunner(Factory);
+ var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
+ content: GetMultiPartRequestContent(PublishJson1),
+ mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
+ assertOkResponse: false);
+
+ Assert.AreEqual(HttpStatusCode.NotFound, response.Item1.StatusCode);
+
+ //var obj = JsonConvert.DeserializeObject>(response.Item2);
+ //Assert.AreEqual(0, obj.TotalItems);
+ }
+
+ ///
+ /// Returns 404 if any of the posted properties dont actually exist
+ ///
+ ///
+ [Test, Ignore("Not implemented yet")]
+ public async Task PostSave_Validate_Properties_Exist()
+ {
+ //TODO: Make this work! to finish it, we need to include a property in the POST data that doesn't exist on the content type
+ // or change the content type below to not include one of the posted ones
+
+ ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
+ {
+ var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
+ content.Id = 123;
+ content.Path = "-1,123";
+
+ var contentServiceMock = Mock.Get(Current.Services.ContentService);
+ contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
+
+ var publishedSnapshot = Mock.Of();
+ var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()));
+ var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
+ Container.InjectProperties(usersController);
+ return usersController;
+ }
+
+ var runner = new TestRunner(Factory);
+ var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
+ content: GetMultiPartRequestContent(PublishJson1),
+ mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
+ assertOkResponse: false);
+
+ Assert.AreEqual(HttpStatusCode.NotFound, response.Item1.StatusCode);
+
+ //var obj = JsonConvert.DeserializeObject>(response.Item2);
+ //Assert.AreEqual(0, obj.TotalItems);
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs b/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs
index 8c76ceea3d..40c1138393 100644
--- a/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs
+++ b/src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs
@@ -45,17 +45,14 @@ namespace Umbraco.Web.Editors.Filters
var model = (ContentItemSave)actionContext.ActionArguments["contentItem"];
var contentItemValidator = new ContentItemValidationHelper(_logger, _umbracoContextAccessor);
- if (ValidateUserAccess(model, actionContext))
+ if (!contentItemValidator.ValidateExistingContent(model, actionContext)) return;
+ if (!ValidateUserAccess(model, actionContext)) return;
+
+ //validate for each variant that is being updated
+ foreach (var variant in model.Variants.Where(x => x.Save))
{
- //now do each validation step
- if (contentItemValidator.ValidateExistingContent(model, actionContext) == false) return;
-
- //validate for each variant that is being updated
- foreach (var variant in model.Variants.Where(x => x.Save))
- {
- if (contentItemValidator.ValidateProperties(model, variant, actionContext))
- contentItemValidator.ValidatePropertyData(model, variant, variant.PropertyCollectionDto, actionContext.ModelState);
- }
+ if (contentItemValidator.ValidateProperties(model, variant, actionContext))
+ contentItemValidator.ValidatePropertyData(model, variant, variant.PropertyCollectionDto, actionContext.ModelState);
}
}