V14: Remove old backoffice project. (#15752)

* Move magical route to management api

* Move auth around

* Remove "New" cookies, as they are no longer needed

* Move all installer related

* Remove BackOfficeServerVariables.cs and trees

* Move webhooks to management api

* Remove remainting controllers

* Remove last services

* Move preview to management api

* Remove mroe extensions

* Remove tours

* Remove old Auth handlers

* Remove server variables entirely

* Remove old backoffice controller

* Remove controllers namespace entirely

* Move rest of preview

* move last services

* Move language file extension

* Remove old backoffice entirely (Backoffice and Web.UI projects)

* Clean up unused security classes

* Fix up installer route

* Remove obsolete tests

* Fix up DI in integration test

* Add missing property mapping

* Move core mapping into core

* Add composers to integration test

* remove identity

* Fix up DI

* Outcomment failing test :)

* Fix up remaining test

* Update mapper

* Remove the actual project files

* Remove backoffice cs proj

* Remove old backoffice from yml

* Run belissima before login

* Remove caching

* Refactor file paths

* Remove belle from static assets

* Dont refer to old project in templates

* update gitignore

* Add missing files

* Remove install view as its no longer used

* Fix up failing test

* Remove outcommented code

* Update submodule to latest

* fix build

---------

Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Nikolaj Geisle
2024-02-27 12:40:30 +01:00
committed by GitHub
parent 593f1eea6c
commit 595ee242aa
2606 changed files with 655 additions and 273115 deletions

View File

@@ -5,6 +5,8 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Moq;
using Umbraco.Cms.Api.Management.Controllers.Security;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
@@ -13,9 +15,6 @@ using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Install;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.BackOffice.Install;
using Umbraco.Cms.Web.BackOffice.Routing;
using Umbraco.Cms.Web.Common.Security;
namespace Umbraco.Cms.Tests.UnitTests.AutoFixture.Customizations;
@@ -29,14 +28,10 @@ internal class UmbracoCustomizations : ICustomization
(a, b, c) => BackOfficeIdentityUser.CreateNew(new GlobalSettings(), a, b, c)));
fixture
.Customize(new ConstructorCustomization(typeof(UsersController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(InstallController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(PreviewController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(BackOfficeController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(BackOfficeUserManager), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(BackOfficeDefaultController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(MemberManager), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(DatabaseSchemaCreatorFactory), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(BackOfficeServerVariables), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(InstallHelper), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(DatabaseBuilder), new GreedyConstructorQuery()));

View File

@@ -3,10 +3,10 @@
using Microsoft.AspNetCore.Authentication;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Security;
using Umbraco.Cms.Core;
using Umbraco.Cms.Web.BackOffice.Security;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Security;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Cms.Api.Management.Security;
[TestFixture]
public class BackOfficeAuthenticationBuilderTests

View File

@@ -1,7 +1,6 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Linq;
using System.Reflection;
using System.Xml;
using Microsoft.Extensions.Logging;
@@ -9,7 +8,6 @@ using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Web.BackOffice.Trees;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Composing;
@@ -45,22 +43,6 @@ public class TypeFinderTests
Assert.AreEqual(2, typesFound.Count());
}
[Test]
public void Find_Classes_With_Attribute()
{
var typeFinder = new TypeFinder(
Mock.Of<ILogger<TypeFinder>>(),
new DefaultUmbracoAssemblyProvider(GetType().Assembly, NullLoggerFactory.Instance));
var typesFound = typeFinder.FindClassesWithAttribute<TreeAttribute>(_assemblies);
Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree]
typesFound = typeFinder.FindClassesWithAttribute<TreeAttribute>(new[] { typeof(TreeAttribute).Assembly });
Assert.AreEqual(24, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree]
typesFound = typeFinder.FindClassesWithAttribute<TreeAttribute>();
Assert.AreEqual(24, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree]
}
[AttributeUsage(AttributeTargets.Class)]
public class MyTestAttribute : Attribute
{

View File

@@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="NUnit3TestAdapter" />
<PackageReference Include="System.Data.Odbc" />
<PackageReference Include="System.Data.Odbc" />
<PackageReference Include="System.Data.OleDb" />
</ItemGroup>

View File

@@ -1,218 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Globalization;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Editors;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class AdminUsersHandlerTests
{
private const string SingleUserEditQueryStringName = "id";
private const string MultipleUserEditQueryStringName = "ids";
private const int Admin1UserId = 0;
private const int Admin2UserId = 1;
private const int NonAdmin1UserId = 2;
private const int NonAdmin2UserId = 3;
private const int NonAdmin3UserId = 4;
[Test]
public async Task Missing_QueryString_Value_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler("xxx");
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Non_Integer_QueryString_Value_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(queryStringValue: "xxx");
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Editing_Single_Admin_User_By_Admin_User_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(
queryStringValue: Admin2UserId.ToString(CultureInfo.InvariantCulture),
editingWithAdmin: true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Editing_Single_Admin_User_By_Non_Admin_User_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(queryStringValue: Admin2UserId.ToString(CultureInfo.InvariantCulture));
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Editing_Single_Non_Admin_User_By_Non_Admin_User_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(queryStringValue: NonAdmin2UserId.ToString(CultureInfo.InvariantCulture));
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Editing_Multiple_Users_Including_Admins_By_Admin_User_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(MultipleUserEditQueryStringName);
var sut = CreateHandler(MultipleUserEditQueryStringName, $"{Admin2UserId},{NonAdmin2UserId}", true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Editing_Multiple_Users_Including_Admins_By_Non_Admin_User_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(MultipleUserEditQueryStringName);
var sut = CreateHandler(MultipleUserEditQueryStringName, $"{Admin2UserId},{NonAdmin2UserId}");
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Editing_Multiple_Users_Not_Including_Admins_By_Non_Admin_User_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(MultipleUserEditQueryStringName);
var sut = CreateHandler(MultipleUserEditQueryStringName, $"{NonAdmin2UserId},{NonAdmin3UserId}");
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext(
string queryStringName = SingleUserEditQueryStringName)
{
var requirement = new AdminUsersRequirement(queryStringName);
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private AdminUsersHandler CreateHandler(
string queryStringName = SingleUserEditQueryStringName,
string queryStringValue = "",
bool editingWithAdmin = false)
{
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName, queryStringValue);
CreateMockUserServiceAndSecurityAccessor(editingWithAdmin, out var mockUserService, out var mockBackOfficeSecurityAccessor);
var userEditorAuthorizationHelper = CreateUserEditorAuthorizationHelper();
return new AdminUsersHandler(
mockHttpContextAccessor.Object,
mockUserService.Object,
mockBackOfficeSecurityAccessor.Object,
userEditorAuthorizationHelper);
}
private static Mock<IHttpContextAccessor> CreateMockHttpContextAccessor(string queryStringName, string queryStringValue)
{
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
var mockHttpContext = new Mock<HttpContext>();
var mockHttpRequest = new Mock<HttpRequest>();
var queryParams = new Dictionary<string, StringValues> { { queryStringName, queryStringValue } };
mockHttpRequest.SetupGet(x => x.Query).Returns(new QueryCollection(queryParams));
mockHttpContext.SetupGet(x => x.Request).Returns(mockHttpRequest.Object);
mockHttpContextAccessor.SetupGet(x => x.HttpContext).Returns(mockHttpContext.Object);
return mockHttpContextAccessor;
}
private static void CreateMockUserServiceAndSecurityAccessor(
bool editingWithAdmin,
out Mock<IUserService> mockUserService,
out Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor)
{
mockUserService = new Mock<IUserService>();
var adminUser1 = CreateUser(Admin1UserId, mockUserService, true);
var adminUser2 = CreateUser(Admin2UserId, mockUserService, true);
var nonAdminUser1 = CreateUser(NonAdmin1UserId, mockUserService);
var nonAdminUser2 = CreateUser(NonAdmin2UserId, mockUserService);
var nonAdminUser3 = CreateUser(NonAdmin3UserId, mockUserService);
// Single user requests have been setup in the create user operations, but
// we also need to mock the responses when multiple users are being editing.
mockUserService
.Setup(x => x.GetUsersById(It.Is<int[]>(y =>
y.Length == 2 && y[0] == Admin2UserId && y[1] == NonAdmin2UserId)))
.Returns(new List<IUser> { adminUser2, nonAdminUser2 });
mockUserService
.Setup(x => x.GetUsersById(It.Is<int[]>(y =>
y.Length == 2 && y[0] == NonAdmin2UserId && y[1] == NonAdmin3UserId)))
.Returns(new List<IUser> { nonAdminUser2, nonAdminUser3 });
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(editingWithAdmin ? adminUser1 : nonAdminUser1);
mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
}
private static User CreateUser(int id, Mock<IUserService> mockUserService, bool isAdmin = false)
{
var user = new UserBuilder()
.WithId(id)
.AddUserGroup()
.WithAlias(isAdmin ? Constants.Security.AdminGroupAlias : Constants.Security.EditorGroupAlias)
.Done()
.Build();
mockUserService
.Setup(x => x.GetUsersById(It.Is<int[]>(y => y.Length == 1 && y[0] == id)))
.Returns(new List<IUser> { user });
return user;
}
private static UserEditorAuthorizationHelper CreateUserEditorAuthorizationHelper()
{
var mockContentService = new Mock<IContentService>();
var mockMediaService = new Mock<IMediaService>();
var mockEntityService = new Mock<IEntityService>();
return new UserEditorAuthorizationHelper(
mockContentService.Object,
mockMediaService.Object,
mockEntityService.Object,
AppCaches.Disabled);
}
}

View File

@@ -1,130 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class BackOfficeHandlerTests
{
[Test]
public async Task Runtime_State_Install_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(RuntimeLevel.Install);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Runtime_State_Upgrade_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(RuntimeLevel.Upgrade);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Unauthenticated_User_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler();
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Authenticated_User_Is_Not_Authorized_When_Not_Approved_And_Approval_Required()
{
var authHandlerContext = CreateAuthorizationHandlerContext(true);
var sut = CreateHandler(currentUserIsAuthenticated: true);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Authenticated_User_Is_Authorized_When_Not_Approved_And_Approval_Not_Required()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(currentUserIsAuthenticated: true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Authenticated_User_Is_Authorized_When_Approved_And_Approval_Required()
{
var authHandlerContext = CreateAuthorizationHandlerContext(true);
var sut = CreateHandler(currentUserIsAuthenticated: true, currentUserIsApproved: true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext(bool requireApproval = false)
{
var requirement = new BackOfficeRequirement(requireApproval);
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private BackOfficeHandler CreateHandler(
RuntimeLevel runtimeLevel = RuntimeLevel.Run,
bool currentUserIsAuthenticated = false,
bool currentUserIsApproved = false)
{
var mockBackOfficeSecurityAccessor =
CreateMockBackOfficeSecurityAccessor(currentUserIsAuthenticated, currentUserIsApproved);
var mockRuntimeState = CreateMockRuntimeState(runtimeLevel);
return new BackOfficeHandler(mockBackOfficeSecurityAccessor.Object, mockRuntimeState.Object);
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(
bool currentUserIsAuthenticated, bool currentUserIsApproved)
{
var user = new UserBuilder()
.WithIsApproved(currentUserIsApproved)
.Build();
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.Setup(x => x.IsAuthenticated()).Returns(currentUserIsAuthenticated);
if (currentUserIsAuthenticated)
{
mockBackOfficeSecurity.Setup(x => x.CurrentUser).Returns(user);
}
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static Mock<IRuntimeState> CreateMockRuntimeState(RuntimeLevel runtimeLevel)
{
var mockRuntimeState = new Mock<IRuntimeState>();
mockRuntimeState.SetupGet(x => x.Level).Returns(runtimeLevel);
return mockRuntimeState;
}
}

View File

@@ -1,178 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Globalization;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Persistence.Querying;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class ContentPermissionsPublishBranchHandlerTests
{
private const int NodeId = 1000;
private const int DescendentNodeId1 = 1001;
private const int DescendentNodeId2 = 1002;
[Test]
public async Task User_With_Access_To_All_Descendent_Nodes_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockUserService = CreateMockUserService(
NodeId,
new Dictionary<int, string[]> { { DescendentNodeId1, new[] { "A" } }, { DescendentNodeId2, new[] { "A" } } });
var sut = CreateHandler(mockUserService.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
mockUserService.Verify(x => x.GetPermissionsForPath(It.IsAny<IUser>(), It.IsAny<string>()), Times.Exactly(2));
}
[Test]
public async Task User_Without_Access_To_One_Descendent_Node_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockUserService = CreateMockUserService(
NodeId,
new Dictionary<int, string[]> { { DescendentNodeId1, new[] { "A" } }, { DescendentNodeId2, new[] { "B" } } });
var sut = CreateHandler(mockUserService.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
mockUserService.Verify(x => x.GetPermissionsForPath(It.IsAny<IUser>(), It.IsAny<string>()), Times.Exactly(2));
}
[Test]
public async Task User_Without_Access_To_First_Descendent_Node_Is_Not_Authorized_And_Checks_Exit_Early()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockUserService = CreateMockUserService(
NodeId,
new Dictionary<int, string[]> { { DescendentNodeId1, new[] { "B" } }, { DescendentNodeId2, new[] { "A" } } });
var sut = CreateHandler(mockUserService.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
mockUserService.Verify(x => x.GetPermissionsForPath(It.IsAny<IUser>(), It.IsAny<string>()), Times.Exactly(1));
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext()
{
var requirement = new ContentPermissionsPublishBranchRequirement('A');
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = CreateContent(NodeId);
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private static Mock<IUserService> CreateMockUserService(
int parentNodeId,
Dictionary<int, string[]> descendendNodePermissionsForPath)
{
var mockUserService = new Mock<IUserService>();
mockUserService
.Setup(x => x.GetPermissionsForPath(
It.IsAny<IUser>(),
It.Is<string>(y =>
y ==
$"{Constants.System.RootString},{parentNodeId.ToString(CultureInfo.InvariantCulture)},{DescendentNodeId1}")))
.Returns(new EntityPermissionSet(
parentNodeId,
new EntityPermissionCollection(new List<EntityPermission>
{
new(1, parentNodeId, descendendNodePermissionsForPath[DescendentNodeId1]),
})));
mockUserService
.Setup(x => x.GetPermissionsForPath(
It.IsAny<IUser>(),
It.Is<string>(y =>
y ==
$"{Constants.System.RootString},{parentNodeId.ToString(CultureInfo.InvariantCulture)},{DescendentNodeId1},{DescendentNodeId2}")))
.Returns(new EntityPermissionSet(
parentNodeId,
new EntityPermissionCollection(new List<EntityPermission>
{
new(1, parentNodeId, descendendNodePermissionsForPath[DescendentNodeId2]),
})));
return mockUserService;
}
private ContentPermissionsPublishBranchHandler CreateHandler(IUserService userService, int nodeId)
{
var mockEntityService = CreateMockEntityService();
var contentPermissions = CreateContentPermissions(mockEntityService.Object, userService, nodeId);
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
return new ContentPermissionsPublishBranchHandler(mockEntityService.Object, contentPermissions, mockBackOfficeSecurityAccessor.Object);
}
private static Mock<IEntityService> CreateMockEntityService()
{
long totalRecords;
var mockEntityService = new Mock<IEntityService>();
mockEntityService
.Setup(x => x.GetPagedDescendants(
It.Is<int>(y => y == NodeId),
It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document),
It.IsAny<long>(),
It.IsAny<int>(),
out totalRecords,
It.IsAny<IQuery<IUmbracoEntity>>(),
It.IsAny<Ordering>()))
.Returns(new List<IEntitySlim>
{
new EntitySlim { Id = DescendentNodeId1, Path = $"-1,{NodeId},{DescendentNodeId1}" },
new EntitySlim
{
Id = DescendentNodeId2, Path = $"-1,{NodeId},{DescendentNodeId1},{DescendentNodeId2}",
},
});
return mockEntityService;
}
private static ContentPermissions CreateContentPermissions(IEntityService entityService, IUserService userService, int nodeId)
{
var mockContentService = new Mock<IContentService>();
mockContentService
.Setup(x => x.GetById(It.Is<int>(y => y == nodeId)))
.Returns(CreateContent(nodeId));
return new ContentPermissions(userService, mockContentService.Object, entityService, AppCaches.Disabled);
}
private static IContent CreateContent(int nodeId)
{
var contentType = ContentTypeBuilder.CreateBasicContentType();
return ContentBuilder.CreateBasicContent(contentType, nodeId);
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor()
{
var user = CreateUser();
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser() =>
new UserBuilder()
.Build();
}

View File

@@ -1,266 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Web.BackOffice.Authorization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class ContentPermissionsQueryStringHandlerTests
{
private const string QueryStringName = "id";
private const int NodeId = 1000;
private static readonly Guid s_nodeGuid = Guid.NewGuid();
private static readonly Udi s_nodeUdi =
UdiParser.Parse($"umb://document/{s_nodeGuid.ToString().ToLowerInvariant().Replace("-", string.Empty)}");
[Test]
public async Task Node_Id_From_Requirement_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
var mockHttpContextAccessor = CreateMockHttpContextAccessor();
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Node_Id_From_Requirement_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
var mockHttpContextAccessor = CreateMockHttpContextAccessor();
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "B" });
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Id_Missing_From_Requirement_And_QueryString_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor("xxx");
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Node_Integer_Id_From_QueryString_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Integer_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "B" });
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Udi_Id_From_QueryString_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Udi_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "B" });
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Guid_Id_From_QueryString_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Guid_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "B" });
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertContentCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Invalid_Id_From_QueryString_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: "invalid");
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext(int? nodeId = null)
{
const char Permission = 'A';
var requirement = nodeId.HasValue
? new ContentPermissionsQueryStringRequirement(nodeId.Value, Permission)
: new ContentPermissionsQueryStringRequirement(Permission);
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private static Mock<IHttpContextAccessor> CreateMockHttpContextAccessor(
string queryStringName = QueryStringName,
string queryStringValue = "")
{
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
var mockHttpContext = new Mock<HttpContext>();
var mockHttpRequest = new Mock<HttpRequest>();
var queryParams = new Dictionary<string, StringValues> { { queryStringName, queryStringValue } };
mockHttpRequest.SetupGet(x => x.Query).Returns(new QueryCollection(queryParams));
mockHttpContext.SetupGet(x => x.Request).Returns(mockHttpRequest.Object);
mockHttpContext.SetupGet(x => x.Items).Returns(new Dictionary<object, object>());
mockHttpContextAccessor.SetupGet(x => x.HttpContext).Returns(mockHttpContext.Object);
return mockHttpContextAccessor;
}
private ContentPermissionsQueryStringHandler CreateHandler(
IHttpContextAccessor httpContextAccessor,
int nodeId,
string[] permissionsForPath)
{
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
var mockEntityService = CreateMockEntityService();
var contentPermissions = CreateContentPermissions(mockEntityService.Object, nodeId, permissionsForPath);
return new ContentPermissionsQueryStringHandler(
mockBackOfficeSecurityAccessor.Object,
httpContextAccessor,
mockEntityService.Object,
contentPermissions);
}
private static Mock<IEntityService> CreateMockEntityService()
{
var mockEntityService = new Mock<IEntityService>();
mockEntityService
.Setup(x => x.GetId(It.Is<Udi>(y => y == s_nodeUdi)))
.Returns(Attempt<int>.Succeed(NodeId));
mockEntityService
.Setup(x => x.GetId(
It.Is<Guid>(y => y == s_nodeGuid),
It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document)))
.Returns(Attempt<int>.Succeed(NodeId));
return mockEntityService;
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor()
{
var user = CreateUser();
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser() =>
new UserBuilder()
.Build();
private static ContentPermissions CreateContentPermissions(
IEntityService entityService,
int nodeId,
string[] permissionsForPath)
{
var mockUserService = new Mock<IUserService>();
mockUserService
.Setup(x => x.GetPermissionsForPath(
It.IsAny<IUser>(),
It.Is<string>(y => y == $"{Constants.System.RootString},{nodeId.ToInvariantString()}")))
.Returns(new EntityPermissionSet(
nodeId,
new EntityPermissionCollection(new List<EntityPermission> { new(1, nodeId, permissionsForPath) })));
var mockContentService = new Mock<IContentService>();
mockContentService
.Setup(x => x.GetById(It.Is<int>(y => y == nodeId)))
.Returns(CreateContent(nodeId));
return new ContentPermissions(
mockUserService.Object,
mockContentService.Object,
entityService,
AppCaches.Disabled);
}
private static IContent CreateContent(int nodeId)
{
var contentType = ContentTypeBuilder.CreateBasicContentType();
return ContentBuilder.CreateBasicContent(contentType, nodeId);
}
private static void AssertContentCached(Mock<IHttpContextAccessor> mockHttpContextAccessor) =>
Assert.AreEqual(
NodeId,
((IContent)mockHttpContextAccessor.Object.HttpContext.Items[typeof(IContent).ToString()]).Id);
}

View File

@@ -1,135 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Web.BackOffice.Authorization;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class ContentPermissionsResourceHandlerTests
{
private const int NodeId = 1000;
[Test]
public async Task Resource_With_Node_Id_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, true);
var sut = CreateHandler(NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Resource_With_Content_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
var sut = CreateHandler(NodeId, new[] { "A" });
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Resource_With_Node_Id_Withou_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, true);
var sut = CreateHandler(NodeId, new[] { "B" });
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Resource_With_Content_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
var sut = CreateHandler(NodeId, new[] { "B" });
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext(
int nodeId,
bool createWithNodeId = false)
{
var requirement = new ContentPermissionsResourceRequirement();
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var content = CreateContent(nodeId);
var permissions = new List<char> { 'A' }.AsReadOnly();
var resource = createWithNodeId
? new ContentPermissionsResource(content, nodeId, permissions)
: new ContentPermissionsResource(content, permissions);
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private static IContent CreateContent(int nodeId)
{
var contentType = ContentTypeBuilder.CreateBasicContentType();
return ContentBuilder.CreateBasicContent(contentType, nodeId);
}
private ContentPermissionsResourceHandler CreateHandler(int nodeId, string[] permissionsForPath)
{
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
var contentPermissions = CreateContentPermissions(nodeId, permissionsForPath);
return new ContentPermissionsResourceHandler(mockBackOfficeSecurityAccessor.Object, contentPermissions);
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor()
{
var user = CreateUser();
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser() =>
new UserBuilder()
.Build();
private static ContentPermissions CreateContentPermissions(int nodeId, string[] permissionsForPath)
{
var mockUserService = new Mock<IUserService>();
mockUserService
.Setup(x => x.GetPermissionsForPath(
It.IsAny<IUser>(),
It.Is<string>(y => y == $"{Constants.System.RootString},{nodeId.ToInvariantString()}")))
.Returns(new EntityPermissionSet(
nodeId,
new EntityPermissionCollection(new List<EntityPermission> { new(1, nodeId, permissionsForPath) })));
var mockContentService = new Mock<IContentService>();
mockContentService
.Setup(x => x.GetById(It.Is<int>(y => y == nodeId)))
.Returns(CreateContent(nodeId));
var mockEntityService = new Mock<IEntityService>();
return new ContentPermissions(
mockUserService.Object,
mockContentService.Object,
mockEntityService.Object,
AppCaches.Disabled);
}
}

View File

@@ -1,61 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Web.BackOffice.Authorization;
using Umbraco.Cms.Web.BackOffice.Security;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class DenyLocalLoginHandlerTests
{
[Test]
public async Task With_Deny_Local_Login_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(true);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Without_Deny_Local_Login_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler();
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext()
{
var requirement = new DenyLocalLoginRequirement();
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private DenyLocalLoginHandler CreateHandler(bool denyLocalLogin = false)
{
var mockBackOfficeExternalLoginProviders = CreateMockBackOfficeExternalLoginProviders(denyLocalLogin);
return new DenyLocalLoginHandler(mockBackOfficeExternalLoginProviders.Object);
}
private static Mock<IBackOfficeExternalLoginProviders> CreateMockBackOfficeExternalLoginProviders(
bool denyLocalLogin)
{
var mockBackOfficeExternalLoginProviders = new Mock<IBackOfficeExternalLoginProviders>();
mockBackOfficeExternalLoginProviders.Setup(x => x.HasDenyLocalLogin()).Returns(denyLocalLogin);
return mockBackOfficeExternalLoginProviders;
}
}

View File

@@ -1,221 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class MediaPermissionsQueryStringHandlerTests
{
private const string QueryStringName = "id";
private const int NodeId = 1000;
private static readonly Guid s_nodeGuid = Guid.NewGuid();
private static readonly Udi s_nodeUdi =
UdiParser.Parse($"umb://document/{s_nodeGuid.ToString().ToLowerInvariant().Replace("-", string.Empty)}");
[Test]
public async Task Node_Id_Missing_From_QueryString_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor("xxx");
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Node_Integer_Id_From_QueryString_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
AssertMediaCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Integer_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, 1001);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertMediaCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Udi_Id_From_QueryString_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
AssertMediaCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Udi_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, 1001);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertMediaCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Guid_Id_From_QueryString_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
AssertMediaCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Guid_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, 1001);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
AssertMediaCached(mockHttpContextAccessor);
}
[Test]
public async Task Node_Invalid_Id_From_QueryString_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: "invalid");
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext()
{
var requirement = new MediaPermissionsQueryStringRequirement(QueryStringName);
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private static Mock<IHttpContextAccessor> CreateMockHttpContextAccessor(
string queryStringName = QueryStringName,
string queryStringValue = "")
{
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
var mockHttpContext = new Mock<HttpContext>();
var mockHttpRequest = new Mock<HttpRequest>();
var queryParams = new Dictionary<string, StringValues> { { queryStringName, queryStringValue } };
mockHttpRequest.SetupGet(x => x.Query).Returns(new QueryCollection(queryParams));
mockHttpContext.SetupGet(x => x.Request).Returns(mockHttpRequest.Object);
mockHttpContext.SetupGet(x => x.Items).Returns(new Dictionary<object, object>());
mockHttpContextAccessor.SetupGet(x => x.HttpContext).Returns(mockHttpContext.Object);
return mockHttpContextAccessor;
}
private MediaPermissionsQueryStringHandler CreateHandler(
IHttpContextAccessor httpContextAccessor,
int nodeId,
int startMediaId = -1)
{
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(startMediaId);
var mockEntityService = CreateMockEntityService();
var mediaPermissions = CreateMediaPermissions(mockEntityService.Object, nodeId);
return new MediaPermissionsQueryStringHandler(
mockBackOfficeSecurityAccessor.Object,
httpContextAccessor,
mockEntityService.Object,
mediaPermissions);
}
private static Mock<IEntityService> CreateMockEntityService()
{
var mockEntityService = new Mock<IEntityService>();
mockEntityService
.Setup(x => x.GetId(It.Is<Udi>(y => y == s_nodeUdi)))
.Returns(Attempt<int>.Succeed(NodeId));
mockEntityService
.Setup(x => x.GetId(
It.Is<Guid>(y => y == s_nodeGuid),
It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document)))
.Returns(Attempt<int>.Succeed(NodeId));
return mockEntityService;
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(int startMediaId)
{
var user = CreateUser(startMediaId);
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser(int startMediaId) =>
new UserBuilder()
.WithStartMediaId(startMediaId)
.Build();
private static MediaPermissions CreateMediaPermissions(IEntityService entityService, int nodeId)
{
var mockMediaService = new Mock<IMediaService>();
mockMediaService
.Setup(x => x.GetById(It.Is<int>(y => y == nodeId)))
.Returns(CreateMedia(nodeId));
return new MediaPermissions(mockMediaService.Object, entityService, AppCaches.Disabled);
}
private static IMedia CreateMedia(int nodeId)
{
var mediaType = MediaTypeBuilder.CreateSimpleMediaType("image", "Image");
return MediaBuilder.CreateSimpleMedia(mediaType, "Test image", -1, nodeId);
}
private static void AssertMediaCached(Mock<IHttpContextAccessor> mockHttpContextAccessor) =>
Assert.AreEqual(
NodeId,
((IMedia)mockHttpContextAccessor.Object.HttpContext.Items[typeof(IMedia).ToString()]).Id);
}

View File

@@ -1,119 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class MediaPermissionsResourceHandlerTests
{
private const int NodeId = 1000;
[Test]
public async Task Resource_With_Node_Id_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, true);
var sut = CreateHandler(NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Resource_With_Media_With_Permission_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
var sut = CreateHandler(NodeId);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Resource_With_Node_Id_Withou_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, true);
var sut = CreateHandler(NodeId, 1001);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Resource_With_Media_Without_Permission_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
var sut = CreateHandler(NodeId, 1001);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext(
int nodeId,
bool createWithNodeId = false)
{
var requirement = new MediaPermissionsResourceRequirement();
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var media = CreateMedia(nodeId);
var resource = createWithNodeId
? new MediaPermissionsResource(nodeId)
: new MediaPermissionsResource(media);
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private static IMedia CreateMedia(int nodeId)
{
var mediaType = MediaTypeBuilder.CreateSimpleMediaType("image", "Image");
return MediaBuilder.CreateSimpleMedia(mediaType, "Test image", -1, nodeId);
}
private MediaPermissionsResourceHandler CreateHandler(int nodeId, int startMediaId = -1)
{
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(startMediaId);
var contentPermissions = CreateMediaPermissions(nodeId);
return new MediaPermissionsResourceHandler(mockBackOfficeSecurityAccessor.Object, contentPermissions);
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(int startMediaId)
{
var user = CreateUser(startMediaId);
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser(int startMediaId) =>
new UserBuilder()
.WithStartMediaId(startMediaId)
.Build();
private static MediaPermissions CreateMediaPermissions(int nodeId)
{
var mockMediaService = new Mock<IMediaService>();
mockMediaService
.Setup(x => x.GetById(It.Is<int>(y => y == nodeId)))
.Returns(CreateMedia(nodeId));
var mockEntityService = new Mock<IEntityService>();
return new MediaPermissions(mockMediaService.Object, mockEntityService.Object, AppCaches.Disabled);
}
}

View File

@@ -1,94 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class SectionHandlerTests
{
[Test]
public async Task Unauthorized_User_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler();
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_With_Section_Access_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(true, true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_Without_Section_Access_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(true);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext()
{
var requirement = new SectionRequirement(Constants.Applications.Content, Constants.Applications.Media);
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private SectionHandler CreateHandler(bool userIsAuthorized = false, bool userCanAccessContentSection = false)
{
var mockBackOfficeSecurityAccessor =
CreateMockBackOfficeSecurityAccessor(userIsAuthorized, userCanAccessContentSection);
return new SectionHandler(mockBackOfficeSecurityAccessor.Object);
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(
bool userIsAuthorized,
bool userCanAccessContentSection)
{
var user = CreateUser();
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(userIsAuthorized ? user : null);
mockBackOfficeSecurity
.Setup(x => x.UserHasSectionAccess(
Constants.Applications.Content,
It.Is<IUser>(y => y.Username == user.Username)))
.Returns(userCanAccessContentSection);
mockBackOfficeSecurity
.Setup(x => x.UserHasSectionAccess(
Constants.Applications.Media,
It.Is<IUser>(y => y.Username == user.Username)))
.Returns(false);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser() =>
new UserBuilder()
.Build();
}

View File

@@ -1,118 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Trees;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class TreeHandlerTests
{
private const string Tree1Alias = "Tree1";
private const string Tree2Alias = "Tree2";
[Test]
public async Task Unauthorized_User_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler();
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_With_Access_To_Tree_Section_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(true, true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_Without_Access_To_Tree_Section_Is_Not_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(true);
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext()
{
var requirement = new TreeRequirement(Tree1Alias, Tree2Alias);
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private TreeHandler CreateHandler(bool userIsAuthorized = false, bool userCanAccessContentSection = false)
{
var mockTreeService = CreateMockTreeService();
var mockBackOfficeSecurityAccessor =
CreateMockBackOfficeSecurityAccessor(userIsAuthorized, userCanAccessContentSection);
return new TreeHandler(mockTreeService.Object, mockBackOfficeSecurityAccessor.Object);
}
private static Mock<ITreeService> CreateMockTreeService()
{
var mockTreeService = new Mock<ITreeService>();
mockTreeService
.Setup(x => x.GetByAlias(It.Is<string>(y => y == Tree1Alias)))
.Returns(CreateTree(Tree1Alias, Constants.Applications.Content));
mockTreeService
.Setup(x => x.GetByAlias(It.Is<string>(y => y == Tree2Alias)))
.Returns(CreateTree(Tree2Alias, Constants.Applications.Media));
return mockTreeService;
}
private static Tree CreateTree(string alias, string sectionAlias) =>
new TreeBuilder()
.WithAlias(alias)
.WithSectionAlias(sectionAlias)
.Build();
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(
bool userIsAuthorized,
bool userCanAccessContentSection)
{
var user = CreateUser();
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(userIsAuthorized ? user : null);
mockBackOfficeSecurity
.Setup(x => x.UserHasSectionAccess(
Constants.Applications.Content,
It.Is<IUser>(y => y.Username == user.Username)))
.Returns(userCanAccessContentSection);
mockBackOfficeSecurity
.Setup(x => x.UserHasSectionAccess(
Constants.Applications.Media,
It.Is<IUser>(y => y.Username == user.Username)))
.Returns(false);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser() => new UserBuilder()
.Build();
}

View File

@@ -1,190 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Authorization;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization;
public class UserGroupHandlerTests
{
private const string QueryStringName = "id";
private const int Group1Id = 1;
private const string Group1Alias = "group1";
private const int Group2Id = 2;
private const string Group2Alias = "group2";
private const int Group3Id = 3;
private const string Group3Alias = "group3";
[Test]
public async Task Missing_QueryString_Value_Is_Authorized()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler();
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task Admin_User_Is_Authorised()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(Group1Id.ToString(), true);
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_Matching_Single_Requested_Group_Id_Is_Authorised()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(Group1Id.ToString());
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_Matching_Only_One_Of_Requested_Group_Ids_Is_NOT_Authorised()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler($"{Group1Id},{Group2Id}");
await sut.HandleAsync(authHandlerContext);
Assert.IsTrue(authHandlerContext.HasFailed);
}
[Test]
public async Task User_Not_Matching_Single_Requested_Group_Id_Is_Not_Authorised()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler(Group2Id.ToString());
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
[Test]
public async Task User_Not_Matching_Any_Of_Requested_Group_Ids_Is_Not_Authorised()
{
var authHandlerContext = CreateAuthorizationHandlerContext();
var sut = CreateHandler($"{Group2Id},{Group3Id}");
await sut.HandleAsync(authHandlerContext);
Assert.IsFalse(authHandlerContext.HasSucceeded);
}
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext()
{
var requirement = new UserGroupRequirement();
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
var resource = new object();
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
}
private UserGroupHandler CreateHandler(string queryStringValue = "", bool userIsAdmin = false)
{
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue);
var mockUserService = CreateMockUserService();
var mockContentService = new Mock<IContentService>();
var mockMediaService = new Mock<IMediaService>();
var mockEntityService = new Mock<IEntityService>();
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAdmin);
return new UserGroupHandler(
mockHttpContextAccessor.Object,
mockUserService.Object,
mockContentService.Object,
mockMediaService.Object,
mockEntityService.Object,
mockBackOfficeSecurityAccessor.Object,
AppCaches.Disabled);
}
private static Mock<IHttpContextAccessor> CreateMockHttpContextAccessor(string queryStringValue)
{
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
var mockHttpContext = new Mock<HttpContext>();
var mockHttpRequest = new Mock<HttpRequest>();
var queryParams = new Dictionary<string, StringValues> { { QueryStringName, queryStringValue } };
mockHttpRequest.SetupGet(x => x.Query).Returns(new QueryCollection(queryParams));
mockHttpContext.SetupGet(x => x.Request).Returns(mockHttpRequest.Object);
mockHttpContextAccessor.SetupGet(x => x.HttpContext).Returns(mockHttpContext.Object);
return mockHttpContextAccessor;
}
private Mock<IUserService> CreateMockUserService()
{
var mockUserService = new Mock<IUserService>();
mockUserService
.Setup(x => x.GetAllUserGroups(It.Is<int[]>(y => y.Length == 1 && y[0] == Group1Id)))
.Returns(new List<IUserGroup> { CreateUserGroup(Group1Id, Group1Alias) });
mockUserService
.Setup(x => x.GetAllUserGroups(It.Is<int[]>(y => y.Length == 1 && y[0] == Group2Id)))
.Returns(new List<IUserGroup> { CreateUserGroup(Group2Id, Group2Alias) });
mockUserService
.Setup(x => x.GetAllUserGroups(It.Is<int[]>(y => y.Length == 2 && y[0] == Group1Id && y[1] == Group2Id)))
.Returns(new List<IUserGroup>
{
CreateUserGroup(Group1Id, Group1Alias),
CreateUserGroup(Group2Id, Group2Alias),
});
mockUserService
.Setup(x => x.GetAllUserGroups(It.Is<int[]>(y => y.Length == 2 && y[0] == Group2Id && y[1] == Group3Id)))
.Returns(new List<IUserGroup>
{
CreateUserGroup(Group2Id, Group2Alias),
CreateUserGroup(Group3Id, Group3Alias),
});
return mockUserService;
}
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(bool userIsAdmin)
{
var user = CreateUser(userIsAdmin);
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object);
return mockBackOfficeSecurityAccessor;
}
private static User CreateUser(bool isAdmin = false) =>
new UserBuilder()
.AddUserGroup()
.WithAlias(isAdmin ? Constants.Security.AdminGroupAlias : Group1Alias)
.Done()
.Build();
private IUserGroup CreateUserGroup(int id, string alias) =>
new UserGroupBuilder()
.WithId(id)
.WithAlias(alias)
.Build();
}

View File

@@ -1,43 +0,0 @@
using System.Linq;
using NUnit.Framework;
using Umbraco.Cms.Core.Trees;
using Umbraco.Cms.Web.BackOffice.Trees;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.CollectionBuilders;
public class TreeCollectionBuilderTests
{
[Test]
public void Adding_Tree_To_Collection_Builder()
{
var collectionBuilder = new TreeCollectionBuilder();
var treeDefinition = new Tree(
0,
"test",
"test",
"test",
"test",
TreeUse.Main,
typeof(LanguageTreeController),
false);
collectionBuilder.AddTree(treeDefinition);
var collection = collectionBuilder.CreateCollection(null);
Assert.AreEqual(1, collection.Count);
Assert.AreEqual(treeDefinition, collection.FirstOrDefault());
}
[Test]
public void Remove_Tree_From_Collection_Builder()
{
var collectionBuilder = new TreeCollectionBuilder();
var treeDefinition = new Tree(0, "test", "test", "test", "test", TreeUse.Main, typeof(LanguageTreeController), false);
collectionBuilder.AddTree(treeDefinition);
collectionBuilder.RemoveTreeController<LanguageTreeController>();
var collection = collectionBuilder.CreateCollection(null);
Assert.AreEqual(0, collection.Count);
}
}

View File

@@ -1,279 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Dictionary;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Mapping;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Controllers;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers;
[TestFixture]
public class ContentControllerTests
{
[Test]
public void Root_Node_With_Domains_Causes_No_Warning()
{
// Setup domain service
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(1060, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/", "da-dk"), new UmbracoDomain("/en", "en-us") });
// Create content, we need to specify and ID in order to be able to configure domain service
var rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.Done()
.Build();
var culturesPublished = new[] { "en-us", "da-dk" };
var notifications = new SimpleNotificationModel();
var contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.IsEmpty(notifications.Notifications);
}
[Test]
public void Node_With_Single_Published_Culture_Causes_No_Warning()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(Enumerable.Empty<IDomain>());
var rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.Done()
.Build();
var culturesPublished = new[] { "da-dk" };
var notifications = new SimpleNotificationModel();
var contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.IsEmpty(notifications.Notifications);
}
[Test]
public void Root_Node_Without_Domains_Causes_SingleWarning()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(Enumerable.Empty<IDomain>());
var rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.Done()
.Build();
var culturesPublished = new[] { "en-us", "da-dk" };
var notifications = new SimpleNotificationModel();
var contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.AreEqual(1, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
[Test]
public void One_Warning_Per_Culture_Being_Published()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/", "da-dk") });
var rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.Done()
.Build();
var culturesPublished = new[] { "en-us", "da-dk", "nl-bk", "se-sv" };
var notifications = new SimpleNotificationModel();
var contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
Assert.AreEqual(3, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
[Test]
public void Ancestor_Domains_Counts()
{
var rootId = 1060;
var level1Id = 1061;
var level2Id = 1062;
var level3Id = 1063;
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(rootId, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/", "da-dk") });
domainServiceMock.Setup(x => x.GetAssignedDomains(level1Id, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/en", "en-us") });
domainServiceMock.Setup(x => x.GetAssignedDomains(level2Id, It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/se", "se-sv"), new UmbracoDomain("/nl", "nl-bk") });
var level3Node = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(level3Id)
.WithPath($"-1,{rootId},{level1Id},{level2Id},{level3Id}")
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.AddCultureInfos()
.WithCultureIso("se-sv")
.Done()
.AddCultureInfos()
.WithCultureIso("nl-bk")
.Done()
.AddCultureInfos()
.WithCultureIso("de-de")
.Done()
.Done()
.Build();
var culturesPublished = new[] { "en-us", "da-dk", "nl-bk", "se-sv", "de-de" };
var contentController = CreateContentController(domainServiceMock.Object);
var notifications = new SimpleNotificationModel();
contentController.AddDomainWarnings(level3Node, culturesPublished, notifications);
// We expect one error because all domains except "de-de" is registered somewhere in the ancestor path
Assert.AreEqual(1, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
[Test]
public void Only_Warns_About_Cultures_Being_Published()
{
var domainServiceMock = new Mock<IDomainService>();
domainServiceMock.Setup(x => x.GetAssignedDomains(It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new[] { new UmbracoDomain("/", "da-dk") });
var rootNode = new ContentBuilder()
.WithContentType(CreateContentType())
.WithId(1060)
.AddContentCultureInfosCollection()
.AddCultureInfos()
.WithCultureIso("da-dk")
.Done()
.AddCultureInfos()
.WithCultureIso("en-us")
.Done()
.AddCultureInfos()
.WithCultureIso("se-sv")
.Done()
.AddCultureInfos()
.WithCultureIso("de-de")
.Done()
.Done()
.Build();
var culturesPublished = new[] { "en-us", "se-sv" };
var notifications = new SimpleNotificationModel();
var contentController = CreateContentController(domainServiceMock.Object);
contentController.AddDomainWarnings(rootNode, culturesPublished, notifications);
// We only get two errors, one for each culture being published, so no errors from previously published cultures.
Assert.AreEqual(2, notifications.Notifications.Count(x => x.NotificationType == NotificationStyle.Warning));
}
private ContentController CreateContentController(IDomainService domainService)
{
// We have to configure ILocalizedTextService to return a new string every time Localize is called
// Otherwise it won't add the notification because it skips dupes
var localizedTextServiceMock = new Mock<ILocalizedTextService>();
localizedTextServiceMock.Setup(x => x.Localize(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CultureInfo>(),
It.IsAny<IDictionary<string, string>>()))
.Returns(() => Guid.NewGuid().ToString());
var controller = new ContentController(
Mock.Of<ICultureDictionary>(),
NullLoggerFactory.Instance,
Mock.Of<IShortStringHelper>(),
Mock.Of<IEventMessagesFactory>(),
localizedTextServiceMock.Object,
new PropertyEditorCollection(new DataEditorCollection(() => null)),
Mock.Of<IContentService>(),
Mock.Of<IUserService>(),
Mock.Of<IBackOfficeSecurityAccessor>(),
Mock.Of<IContentTypeService>(),
Mock.Of<IUmbracoMapper>(),
Mock.Of<IPublishedUrlProvider>(),
domainService,
Mock.Of<IDataTypeService>(),
Mock.Of<ILocalizationService>(),
Mock.Of<IFileService>(),
Mock.Of<INotificationService>(),
new ActionCollection(() => null),
Mock.Of<ISqlContext>(),
Mock.Of<IJsonSerializer>(),
Mock.Of<ICoreScopeProvider>(),
Mock.Of<IAuthorizationService>(),
Mock.Of<IContentVersionService>(),
Mock.Of<ICultureImpactFactory>(),
Mock.Of<IUserGroupService>(),
new OptionsWrapper<ContentSettings>(new ContentSettings()));
return controller;
}
private IContentType CreateContentType() =>
new ContentTypeBuilder().WithContentVariation(ContentVariation.Culture).Build();
}

View File

@@ -1,34 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using AutoFixture.NUnit3;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Tests.UnitTests.AutoFixture;
using Umbraco.Cms.Web.BackOffice.Controllers;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers;
[TestFixture]
public class UsersControllerTests
{
[Test]
[AutoMoqData]
public void PostUnlockUsers_When_User_Lockout_Update_Fails_Expect_Failure_Response(
[Frozen] IBackOfficeUserManager backOfficeUserManager,
UsersController sut,
BackOfficeIdentityUser user,
int[] userIds,
string expectedMessage)
{
Mock.Get(backOfficeUserManager)
.Setup(x => x.FindByIdAsync(It.IsAny<string>()))
.ReturnsAsync(user);
var result = sut.PostUnlockUsers(userIds).Result as ObjectResult;
Assert.AreEqual(StatusCodes.Status400BadRequest, result.StatusCode);
}
}

View File

@@ -1,130 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Services;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Extensions;
[TestFixture]
public class ModelStateExtensionsTests
{
[Test]
public void Get_Cultures_With_Errors()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", null); // invariant property
ms.AddPropertyError(new ValidationResult("title missing"), "title", "en-US"); // variant property
var result = ms.GetVariantsWithErrors("en-US");
// even though there are 2 errors, they are both for en-US since that is the default language and one of the errors is for an invariant property
Assert.AreEqual(1, result.Count);
Assert.AreEqual("en-US", result[0].culture);
ms = new ModelStateDictionary();
ms.AddVariantValidationError("en-US", null, "generic culture error");
result = ms.GetVariantsWithErrors("en-US");
Assert.AreEqual(1, result.Count);
Assert.AreEqual("en-US", result[0].culture);
}
[Test]
public void Get_Cultures_With_Property_Errors()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", null); // invariant property
ms.AddPropertyError(new ValidationResult("title missing"), "title", "en-US"); // variant property
var result = ms.GetVariantsWithPropertyErrors("en-US");
// even though there are 2 errors, they are both for en-US since that is the default language and one of the errors is for an invariant property
Assert.AreEqual(1, result.Count);
Assert.AreEqual("en-US", result[0].culture);
}
[Test]
public void Add_Invariant_Property_Error()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", null); // invariant property
Assert.AreEqual("_Properties.headerImage.invariant.null", ms.Keys.First());
}
[Test]
public void Add_Variant_Property_Error()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", "en-US"); // variant property
Assert.AreEqual("_Properties.headerImage.en-US.null", ms.Keys.First());
}
[Test]
public void Add_Invariant_Segment_Property_Error()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", null, "mySegment"); // invariant/segment property
Assert.AreEqual("_Properties.headerImage.invariant.mySegment", ms.Keys.First());
}
[Test]
public void Add_Variant_Segment_Property_Error()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image"), "headerImage", "en-US", "mySegment"); // variant/segment property
Assert.AreEqual("_Properties.headerImage.en-US.mySegment", ms.Keys.First());
}
[Test]
public void Add_Invariant_Segment_Field_Property_Error()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image", new[] { "myField" }), "headerImage", null, "mySegment"); // invariant/segment property
Assert.AreEqual("_Properties.headerImage.invariant.mySegment.myField", ms.Keys.First());
}
[Test]
public void Add_Variant_Segment_Field_Property_Error()
{
var ms = new ModelStateDictionary();
var localizationService = new Mock<ILocalizationService>();
localizationService.Setup(x => x.GetDefaultLanguageIsoCode()).Returns("en-US");
ms.AddPropertyError(new ValidationResult("no header image", new[] { "myField" }), "headerImage", "en-US", "mySegment"); // variant/segment property
Assert.AreEqual("_Properties.headerImage.en-US.mySegment.myField", ms.Keys.First());
}
}

View File

@@ -1,129 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Web.BackOffice.Filters;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Filters;
[TestFixture]
public class AppendUserModifiedHeaderAttributeTests
{
[Test]
public void Appends_Header_When_No_User_Parameter_Provider()
{
// Arrange
var context = CreateContext();
var attribute = new AppendUserModifiedHeaderAttribute();
// Act
attribute.OnActionExecuting(context);
// Assert
context.HttpContext.Response.Headers.TryGetValue("X-Umb-User-Modified", out var headerValue);
Assert.AreEqual("1", headerValue[0]);
}
[Test]
public void Does_Not_Append_Header_If_Already_Exists()
{
// Arrange
var context = CreateContext("0");
var attribute = new AppendUserModifiedHeaderAttribute();
// Act
attribute.OnActionExecuting(context);
// Assert
context.HttpContext.Response.Headers.TryGetValue("X-Umb-User-Modified", out var headerValue);
Assert.AreEqual("0", headerValue[0]);
}
[Test]
public void Does_Not_Append_Header_When_User_Id_Parameter_Provided_And_Does_Not_Match_Current_User()
{
// Arrange
var context = CreateContext(actionArgument: new KeyValuePair<string, object>("UserId", 99));
var userIdParameter = "UserId";
var attribute = new AppendUserModifiedHeaderAttribute(userIdParameter);
// Act
attribute.OnActionExecuting(context);
// Assert
Assert.IsFalse(context.HttpContext.Response.Headers.ContainsKey("X-Umb-User-Modified"));
}
[Test]
public void Appends_Header_When_User_Id_Parameter_Provided_And_Does_Not_Match_Current_User()
{
// Arrange
var context = CreateContext(actionArgument: new KeyValuePair<string, object>("UserId", 100));
var userIdParameter = "UserId";
var attribute = new AppendUserModifiedHeaderAttribute(userIdParameter);
// Act
attribute.OnActionExecuting(context);
// Assert
context.HttpContext.Response.Headers.TryGetValue("X-Umb-User-Modified", out var headerValue);
Assert.AreEqual("1", headerValue[0]);
}
private static ActionExecutingContext CreateContext(
string headerValue = null,
KeyValuePair<string, object> actionArgument = default)
{
var httpContext = new DefaultHttpContext();
if (!string.IsNullOrEmpty(headerValue))
{
httpContext.Response.Headers.Add("X-Umb-User-Modified", headerValue);
}
var currentUserMock = new Mock<IUser>();
currentUserMock
.SetupGet(x => x.Id)
.Returns(100);
var backofficeSecurityMock = new Mock<IBackOfficeSecurity>();
backofficeSecurityMock
.SetupGet(x => x.CurrentUser)
.Returns(currentUserMock.Object);
var backofficeSecurityAccessorMock = new Mock<IBackOfficeSecurityAccessor>();
backofficeSecurityAccessorMock
.SetupGet(x => x.BackOfficeSecurity)
.Returns(backofficeSecurityMock.Object);
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock
.Setup(x => x.GetService(typeof(IBackOfficeSecurityAccessor)))
.Returns(backofficeSecurityAccessorMock.Object);
httpContext.RequestServices = serviceProviderMock.Object;
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
var context = new ActionExecutingContext(
actionContext,
new List<IFilterMetadata>(),
new Dictionary<string, object>(),
new Mock<Controller>().Object);
if (!EqualityComparer<KeyValuePair<string, object>>.Default.Equals(actionArgument, default))
{
context.ActionArguments.Add(actionArgument);
}
return context;
}
}

View File

@@ -1,113 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Umbraco.Cms.Core.PropertyEditors.Validation;
using Umbraco.Cms.Web.BackOffice.PropertyEditors.Validation;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Filters;
[TestFixture]
public class ContentModelValidatorTests
{
[Test]
public void Test_Serializer()
{
var nestedLevel2 = new ComplexEditorValidationResult();
var id1 = Guid.NewGuid();
var addressInfoElementTypeResult = new ComplexEditorElementTypeValidationResult("addressInfo", id1);
var cityPropertyTypeResult = new ComplexEditorPropertyTypeValidationResult("city");
cityPropertyTypeResult.AddValidationResult(new ValidationResult("City is invalid"));
cityPropertyTypeResult.AddValidationResult(new ValidationResult("City cannot be empty"));
cityPropertyTypeResult.AddValidationResult(new ValidationResult("City is not in Australia", new[] { "country" }));
cityPropertyTypeResult.AddValidationResult(new ValidationResult("Not a capital city", new[] { "capital" }));
addressInfoElementTypeResult.ValidationResults.Add(cityPropertyTypeResult);
nestedLevel2.ValidationResults.Add(addressInfoElementTypeResult);
var nestedLevel1 = new ComplexEditorValidationResult();
var id2 = Guid.NewGuid();
var addressBookElementTypeResult = new ComplexEditorElementTypeValidationResult("addressBook", id2);
var addressesPropertyTypeResult = new ComplexEditorPropertyTypeValidationResult("addresses");
addressesPropertyTypeResult.AddValidationResult(new ValidationResult("Must have at least 3 addresses", new[] { "counter" }));
addressesPropertyTypeResult.AddValidationResult(nestedLevel2); // This is a nested result within the level 1
addressBookElementTypeResult.ValidationResults.Add(addressesPropertyTypeResult);
var bookNamePropertyTypeResult = new ComplexEditorPropertyTypeValidationResult("bookName");
bookNamePropertyTypeResult.AddValidationResult(
new ValidationResult("Invalid address book name", new[] { "book" }));
addressBookElementTypeResult.ValidationResults.Add(bookNamePropertyTypeResult);
nestedLevel1.ValidationResults.Add(addressBookElementTypeResult);
var id3 = Guid.NewGuid();
var addressBookElementTypeResult2 = new ComplexEditorElementTypeValidationResult("addressBook", id3);
var addressesPropertyTypeResult2 = new ComplexEditorPropertyTypeValidationResult("addresses");
addressesPropertyTypeResult2.AddValidationResult(new ValidationResult("Must have at least 2 addresses", new[] { "counter" }));
addressBookElementTypeResult2.ValidationResults.Add(addressesPropertyTypeResult);
var bookNamePropertyTypeResult2 = new ComplexEditorPropertyTypeValidationResult("bookName");
bookNamePropertyTypeResult2.AddValidationResult(new ValidationResult("Name is too long"));
addressBookElementTypeResult2.ValidationResults.Add(bookNamePropertyTypeResult2);
nestedLevel1.ValidationResults.Add(addressBookElementTypeResult2);
// books is the outer most validation result and doesn't have it's own direct ValidationResult errors
var outerError = new ComplexEditorValidationResult();
var id4 = Guid.NewGuid();
var addressBookCollectionElementTypeResult =
new ComplexEditorElementTypeValidationResult("addressBookCollection", id4);
var booksPropertyTypeResult = new ComplexEditorPropertyTypeValidationResult("books");
booksPropertyTypeResult.AddValidationResult(nestedLevel1); // books is the outer most validation result
addressBookCollectionElementTypeResult.ValidationResults.Add(booksPropertyTypeResult);
outerError.ValidationResults.Add(addressBookCollectionElementTypeResult);
var serialized = JsonConvert.SerializeObject(outerError, Formatting.Indented, new ValidationResultConverter());
Console.WriteLine(serialized);
var jsonError = JsonConvert.DeserializeObject<JArray>(serialized);
Assert.IsNotNull(jsonError.SelectToken("$[0]"));
Assert.AreEqual(id4.ToString(), jsonError.SelectToken("$[0].$id").Value<string>());
Assert.AreEqual("addressBookCollection", jsonError.SelectToken("$[0].$elementTypeAlias").Value<string>());
Assert.AreEqual(string.Empty, jsonError.SelectToken("$[0].ModelState['_Properties.books.invariant.null'][0]").Value<string>());
var error0 = jsonError.SelectToken("$[0].books") as JArray;
Assert.IsNotNull(error0);
Assert.AreEqual(id2.ToString(), error0.SelectToken("$[0].$id").Value<string>());
Assert.AreEqual("addressBook", error0.SelectToken("$[0].$elementTypeAlias").Value<string>());
Assert.IsNotNull(error0.SelectToken("$[0].ModelState"));
Assert.AreEqual(string.Empty, error0.SelectToken("$[0].ModelState['_Properties.addresses.invariant.null'][0]").Value<string>());
var error1 = error0.SelectToken("$[0].ModelState['_Properties.addresses.invariant.null.counter']") as JArray;
Assert.IsNotNull(error1);
Assert.AreEqual(1, error1.Count);
var error2 = error0.SelectToken("$[0].ModelState['_Properties.bookName.invariant.null.book']") as JArray;
Assert.IsNotNull(error2);
Assert.AreEqual(1, error2.Count);
Assert.AreEqual(id3.ToString(), error0.SelectToken("$[1].$id").Value<string>());
Assert.AreEqual("addressBook", error0.SelectToken("$[1].$elementTypeAlias").Value<string>());
Assert.IsNotNull(error0.SelectToken("$[1].ModelState"));
Assert.AreEqual(string.Empty, error0.SelectToken("$[1].ModelState['_Properties.addresses.invariant.null'][0]").Value<string>());
var error6 = error0.SelectToken("$[1].ModelState['_Properties.addresses.invariant.null.counter']") as JArray;
Assert.IsNotNull(error6);
Assert.AreEqual(1, error6.Count);
var error7 = error0.SelectToken("$[1].ModelState['_Properties.bookName.invariant.null']") as JArray;
Assert.IsNotNull(error7);
Assert.AreEqual(1, error7.Count);
Assert.IsNotNull(error0.SelectToken("$[0].addresses"));
Assert.AreEqual(id1.ToString(), error0.SelectToken("$[0].addresses[0].$id").Value<string>());
Assert.AreEqual("addressInfo", error0.SelectToken("$[0].addresses[0].$elementTypeAlias").Value<string>());
Assert.IsNotNull(error0.SelectToken("$[0].addresses[0].ModelState"));
var error3 =
error0.SelectToken("$[0].addresses[0].ModelState['_Properties.city.invariant.null.country']") as JArray;
Assert.IsNotNull(error3);
Assert.AreEqual(1, error3.Count);
var error4 =
error0.SelectToken("$[0].addresses[0].ModelState['_Properties.city.invariant.null.capital']") as JArray;
Assert.IsNotNull(error4);
Assert.AreEqual(1, error4.Count);
var error5 = error0.SelectToken("$[0].addresses[0].ModelState['_Properties.city.invariant.null']") as JArray;
Assert.IsNotNull(error5);
Assert.AreEqual(2, error5.Count);
}
}

View File

@@ -1,176 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Web.BackOffice.Filters;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Filters;
[TestFixture]
public class FilterAllowedOutgoingContentAttributeTests
{
[Test]
public void GetValueFromResponse_Already_EnumerableContent()
{
var expected = new List<ContentItemBasic> { new() };
var att = new FilterAllowedOutgoingContentFilter(
expected.GetType(),
null,
ActionBrowse.ActionLetter,
Mock.Of<IUserService>(),
Mock.Of<IEntityService>(),
AppCaches.Disabled,
Mock.Of<IBackOfficeSecurityAccessor>());
var result = att.GetValueFromResponse(new ObjectResult(expected));
Assert.AreEqual(expected, result);
}
[Test]
public void GetValueFromResponse_From_Property()
{
var expected = new List<ContentItemBasic> { new() };
var container = new MyTestClass { MyList = expected };
var att = new FilterAllowedOutgoingContentFilter(
expected.GetType(),
nameof(MyTestClass.MyList),
ActionBrowse.ActionLetter,
Mock.Of<IUserService>(),
Mock.Of<IEntityService>(),
AppCaches.Disabled,
Mock.Of<IBackOfficeSecurityAccessor>());
var result = att.GetValueFromResponse(new ObjectResult(container));
Assert.AreEqual(expected, result);
}
[Test]
public void GetValueFromResponse_Returns_Null_Not_Found_Property()
{
var expected = new List<ContentItemBasic> { new() };
var container = new MyTestClass { MyList = expected };
var att = new FilterAllowedOutgoingContentFilter(
expected.GetType(),
"DontFind",
ActionBrowse.ActionLetter,
Mock.Of<IUserService>(),
Mock.Of<IEntityService>(),
AppCaches.Disabled,
Mock.Of<IBackOfficeSecurityAccessor>());
var actual = att.GetValueFromResponse(new ObjectResult(container));
Assert.IsNull(actual);
}
[Test]
public void Filter_On_Start_Node()
{
var user = CreateUser(9, 5);
var userServiceMock = new Mock<IUserService>();
var userService = userServiceMock.Object;
var entityServiceMock = new Mock<IEntityService>();
entityServiceMock.Setup(x => x.GetAllPaths(It.IsAny<UmbracoObjectTypes>(), It.IsAny<int[]>()))
.Returns(new[] { Mock.Of<TreeEntityPath>(entity => entity.Id == 5 && entity.Path == "-1,5") });
var entityService = entityServiceMock.Object;
var list = new List<ContentItemBasic>();
var att = new FilterAllowedOutgoingContentFilter(
list.GetType(),
null,
ActionBrowse.ActionLetter,
userService,
entityService,
AppCaches.Disabled,
Mock.Of<IBackOfficeSecurityAccessor>());
var path = string.Empty;
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 });
}
att.FilterBasedOnStartNode(list, user);
Assert.AreEqual(5, list.Count);
}
[Test]
public void Filter_On_Permissions()
{
var list = new List<ContentItemBasic>();
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 = CreateUser(9, 0);
var userServiceMock = new Mock<IUserService>();
// We're only assigning 3 nodes browse permissions so that is what we expect as a result
var permissions = new EntityPermissionCollection
{
new(9876, 1, new[] { ActionBrowse.ActionLetter.ToString() }),
new(9876, 2, new[] { ActionBrowse.ActionLetter.ToString() }),
new(9876, 3, new[] { ActionBrowse.ActionLetter.ToString() }),
new(9876, 4, new[] { ActionUpdate.ActionLetter.ToString() }),
};
userServiceMock.Setup(x => x.GetPermissions(user, ids)).Returns(permissions);
var userService = userServiceMock.Object;
var att = new FilterAllowedOutgoingContentFilter(
list.GetType(),
null,
ActionBrowse.ActionLetter,
userService,
Mock.Of<IEntityService>(),
AppCaches.Disabled,
Mock.Of<IBackOfficeSecurityAccessor>());
att.FilterBasedOnPermissions(list, user);
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 IUser CreateUser(int id = 0, int? startContentId = null) =>
new UserBuilder()
.WithId(id)
.WithStartContentIds(startContentId.HasValue ? new[] { startContentId.Value } : new int[0])
.Build();
private class MyTestClass
{
public IEnumerable<ContentItemBasic> MyList { get; set; }
}
}

View File

@@ -1,67 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Web.BackOffice.Filters;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Filters;
[TestFixture]
public class ValidationFilterAttributeTests
{
[Test]
public void Does_Not_Set_Result_When_No_Errors_In_Model_State()
{
// Arrange
var context = CreateContext();
var attribute = new ValidationFilterAttribute();
// Act
attribute.OnActionExecuting(context);
// Assert
Assert.IsNull(context.Result);
}
[Test]
public void Returns_Bad_Request_When_Errors_In_Model_State()
{
// Arrange
var context = CreateContext(true);
var attribute = new ValidationFilterAttribute();
// Act
attribute.OnActionExecuting(context);
// Assert
var typedResult = context.Result as BadRequestObjectResult;
Assert.IsNotNull(typedResult);
}
private static ActionExecutingContext CreateContext(bool withError = false)
{
var httpContext = new DefaultHttpContext();
var modelState = new ModelStateDictionary();
if (withError)
{
modelState.AddModelError(string.Empty, "Error");
}
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor(), modelState);
return new ActionExecutingContext(
actionContext,
new List<IFilterMetadata>(),
new Dictionary<string, object>(),
new Mock<Controller>().Object);
}
}

View File

@@ -1,132 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.BackOffice.Security;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Security;
[TestFixture]
public class BackOfficeCookieManagerTests
{
[Test]
public void ShouldAuthenticateRequest_When_Not_Configured()
{
var globalSettings = new GlobalSettings();
var umbracoRequestPathsOptions = new UmbracoRequestPathsOptions();
var runtime = Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Install);
var mgr = new BackOfficeCookieManager(
Mock.Of<IUmbracoContextAccessor>(),
runtime,
new UmbracoRequestPaths(Options.Create(globalSettings), TestHelper.GetHostingEnvironment(), Options.Create(umbracoRequestPathsOptions)),
Mock.Of<IBasicAuthService>());
var result = mgr.ShouldAuthenticateRequest("/umbraco");
Assert.IsFalse(result);
}
[Test]
public void ShouldAuthenticateRequest_When_Configured()
{
var globalSettings = new GlobalSettings();
var umbracoRequestPathsOptions = new UmbracoRequestPathsOptions();
var runtime = Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run);
var mgr = new BackOfficeCookieManager(
Mock.Of<IUmbracoContextAccessor>(),
runtime,
new UmbracoRequestPaths(
Options.Create(globalSettings),
Mock.Of<IHostingEnvironment>(x =>
x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco"),
Options.Create(umbracoRequestPathsOptions)),
Mock.Of<IBasicAuthService>());
var result = mgr.ShouldAuthenticateRequest("/umbraco");
Assert.IsTrue(result);
}
[Test]
public void ShouldAuthenticateRequest_Is_Back_Office()
{
var globalSettings = new GlobalSettings();
var umbracoRequestPathsOptions = new UmbracoRequestPathsOptions();
var runtime = Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run);
GenerateAuthPaths(out var remainingTimeoutSecondsPath, out var isAuthPath);
var mgr = new BackOfficeCookieManager(
Mock.Of<IUmbracoContextAccessor>(),
runtime,
new UmbracoRequestPaths(
Options.Create(globalSettings),
Mock.Of<IHostingEnvironment>(x =>
x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco" &&
x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"),
Options.Create(umbracoRequestPathsOptions)),
Mock.Of<IBasicAuthService>());
var result = mgr.ShouldAuthenticateRequest(remainingTimeoutSecondsPath);
Assert.IsTrue(result);
result = mgr.ShouldAuthenticateRequest(isAuthPath);
Assert.IsTrue(result);
}
[Test]
public void ShouldAuthenticateRequest_Not_Back_Office()
{
var globalSettings = new GlobalSettings();
var umbracoRequestPathsOptions = new UmbracoRequestPathsOptions();
var runtime = Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run);
var mgr = new BackOfficeCookieManager(
Mock.Of<IUmbracoContextAccessor>(),
runtime,
new UmbracoRequestPaths(
Options.Create(globalSettings),
Mock.Of<IHostingEnvironment>(x =>
x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco" &&
x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"),
Options.Create(umbracoRequestPathsOptions)),
Mock.Of<IBasicAuthService>());
var result = mgr.ShouldAuthenticateRequest("/notbackoffice");
Assert.IsFalse(result);
result = mgr.ShouldAuthenticateRequest("/umbraco/api/notbackoffice");
Assert.IsFalse(result);
result = mgr.ShouldAuthenticateRequest("/umbraco/surface/notbackoffice");
Assert.IsFalse(result);
}
private void GenerateAuthPaths(out string remainingTimeoutSecondsPath, out string isAuthPath)
{
var controllerName = ControllerExtensions.GetControllerName<AuthenticationController>();
// this path is not a back office request even though it's in the same controller - it's a 'special' endpoint
var rPath = remainingTimeoutSecondsPath =
$"/umbraco/{Constants.Web.Mvc.BackOfficePathSegment}/{Constants.Web.Mvc.BackOfficeApiArea}/{controllerName}/{nameof(AuthenticationController.GetRemainingTimeoutSeconds)}"
.ToLower();
// this is on the same controller but is considered a back office request
var aPath = isAuthPath =
$"/umbraco/{Constants.Web.Mvc.BackOfficePathSegment}/{Constants.Web.Mvc.BackOfficeApiArea}/{controllerName}/{nameof(AuthenticationController.IsAuthenticated)}"
.ToLower();
}
}

View File

@@ -1,41 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Threading.Tasks;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Infrastructure.WebAssets;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.AngularIntegration;
[TestFixture]
public class ServerVariablesParserTests
{
[Test]
public async Task Parse()
{
var parser = new ServerVariablesParser(Mock.Of<IEventAggregator>());
var d = new Dictionary<string, object>
{
{ "test1", "Test 1" },
{ "test2", "Test 2" },
{ "test3", "Test 3" },
{ "test4", "Test 4" },
{ "test5", "Test 5" },
};
var output = (await parser.ParseAsync(d)).StripWhitespace();
Assert.IsTrue(output.Contains(@"Umbraco.Sys.ServerVariables = {
""test1"": ""Test 1"",
""test2"": ""Test 2"",
""test3"": ""Test 3"",
""test4"": ""Test 4"",
""test5"": ""Test 5""
} ;".StripWhitespace()));
}
}

View File

@@ -6,11 +6,10 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.FileProviders;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Controllers.Security;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Tests.UnitTests.AutoFixture;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.BackOffice.Install;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common;
@@ -37,45 +36,7 @@ internal class FileNameTests
[Test]
[AutoMoqData]
public async Task InstallViewExists(
[Frozen] IHostingEnvironment hostingEnvironment,
InstallController sut)
{
Mock.Get(hostingEnvironment).Setup(x => x.ToAbsolute(It.IsAny<string>())).Returns("http://localhost/");
var viewResult = await sut.Index() as ViewResult;
var fileName = GetViewName(viewResult, Path.DirectorySeparatorChar.ToString());
var views = GetUiFiles(new[] { "umbraco", "UmbracoInstall" });
Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't");
}
[Test]
[AutoMoqData]
public void PreviewViewExists(PreviewController sut)
{
var viewResult = sut.Index() as ViewResult;
var fileName = GetViewName(viewResult);
var views = GetUiFiles(new[] { "umbraco", "UmbracoBackOffice" });
Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't");
}
[Test]
[AutoMoqData]
public async Task LoginViewExists(BackOfficeController sut)
{
var viewResult = await sut.Login() as ViewResult;
var fileName = GetViewName(viewResult);
var views = GetUiFiles(new[] { "umbraco", "UmbracoLogin" });
Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't");
}
[Test]
[AutoMoqData]
public void BackOfficeDefaultExists(BackOfficeController sut)
public void BackOfficeDefaultExists(BackOfficeDefaultController sut)
{
var viewResult = sut.DefaultView();
var fileName = GetViewName(viewResult);

View File

@@ -7,12 +7,12 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Controllers.Security;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.BackOffice.Routing;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Controllers;
using Umbraco.Extensions;
@@ -47,11 +47,11 @@ public class BackOfficeAreaRoutesTests
Assert.AreEqual(1, endpoints.DataSources.Count);
var route = endpoints.DataSources.First();
Assert.AreEqual(4, route.Endpoints.Count);
Assert.AreEqual(3, route.Endpoints.Count);
AssertMinimalBackOfficeRoutes(route);
var endpoint4 = (RouteEndpoint)route.Endpoints[3];
var endpoint4 = (RouteEndpoint)route.Endpoints[2];
var apiControllerName = ControllerExtensions.GetControllerName<Testing1Controller>();
Assert.AreEqual(
$"umbraco/backoffice/api/{apiControllerName.ToLowerInvariant()}/{{action}}/{{id?}}",
@@ -65,26 +65,8 @@ public class BackOfficeAreaRoutesTests
{
var endpoint1 = (RouteEndpoint)route.Endpoints[0];
Assert.AreEqual("umbraco/{action}/{id?}", endpoint1.RoutePattern.RawText);
Assert.AreEqual(Constants.Web.Mvc.BackOfficeArea, endpoint1.RoutePattern.Defaults[AreaToken]);
Assert.AreEqual("Default", endpoint1.RoutePattern.Defaults[ActionToken]);
Assert.AreEqual(
ControllerExtensions.GetControllerName<BackOfficeController>(),
endpoint1.RoutePattern.Defaults[ControllerToken]);
Assert.AreEqual(
endpoint1.RoutePattern.Defaults[AreaToken],
typeof(BackOfficeController).GetCustomAttribute<AreaAttribute>(false).RouteValue);
var endpoint2 = (RouteEndpoint)route.Endpoints[1];
var controllerName = ControllerExtensions.GetControllerName<AuthenticationController>();
Assert.AreEqual(
$"umbraco/backoffice/{Constants.Web.Mvc.BackOfficeApiArea.ToLowerInvariant()}/{controllerName.ToLowerInvariant()}/{{action}}/{{id?}}",
endpoint2.RoutePattern.RawText);
Assert.AreEqual(Constants.Web.Mvc.BackOfficeApiArea, endpoint2.RoutePattern.Defaults[AreaToken]);
Assert.IsFalse(endpoint2.RoutePattern.Defaults.ContainsKey(ActionToken));
Assert.AreEqual(controllerName, endpoint2.RoutePattern.Defaults[ControllerToken]);
Assert.AreEqual(
endpoint1.RoutePattern.Defaults[AreaToken],
typeof(BackOfficeController).GetCustomAttribute<AreaAttribute>(false).RouteValue);
Assert.AreEqual("Index", endpoint1.RoutePattern.Defaults[ActionToken]);
Assert.AreEqual(ControllerExtensions.GetControllerName<BackOfficeDefaultController>(), endpoint1.RoutePattern.Defaults[ControllerToken]);
}
private BackOfficeAreaRoutes GetBackOfficeAreaRoutes(RuntimeLevel level)

View File

@@ -1,98 +0,0 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.BackOffice.Install;
using Umbraco.Extensions;
using static Umbraco.Cms.Core.Constants.Web.Routing;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Routing;
[TestFixture]
public class InstallAreaRoutesTests
{
[TestCase(RuntimeLevel.BootFailed)]
[TestCase(RuntimeLevel.Unknown)]
[TestCase(RuntimeLevel.Boot)]
public void RuntimeState_No_Routes(RuntimeLevel level)
{
var routes = GetInstallAreaRoutes(level);
var endpoints = new TestRouteBuilder();
routes.CreateRoutes(endpoints);
Assert.AreEqual(0, endpoints.DataSources.Count);
}
[TestCase(RuntimeLevel.Install)]
[TestCase(RuntimeLevel.Upgrade)]
public void RuntimeState_Install(RuntimeLevel level)
{
var routes = GetInstallAreaRoutes(level);
var endpoints = new TestRouteBuilder();
routes.CreateRoutes(endpoints);
Assert.AreEqual(1, endpoints.DataSources.Count);
var route = endpoints.DataSources.First();
Assert.AreEqual(2, route.Endpoints.Count);
var endpoint1 = (RouteEndpoint)route.Endpoints[0];
Assert.AreEqual("install/api/{action}/{id?}", endpoint1.RoutePattern.RawText);
Assert.AreEqual(Constants.Web.Mvc.InstallArea, endpoint1.RoutePattern.Defaults[AreaToken]);
Assert.AreEqual("Index", endpoint1.RoutePattern.Defaults[ActionToken]);
Assert.AreEqual(
ControllerExtensions.GetControllerName<InstallApiController>(),
endpoint1.RoutePattern.Defaults[ControllerToken]);
Assert.AreEqual(
endpoint1.RoutePattern.Defaults[AreaToken],
typeof(InstallApiController).GetCustomAttribute<AreaAttribute>(false).RouteValue);
var endpoint2 = (RouteEndpoint)route.Endpoints[1];
Assert.AreEqual("install/{action}/{id?}", endpoint2.RoutePattern.RawText);
Assert.AreEqual(Constants.Web.Mvc.InstallArea, endpoint2.RoutePattern.Defaults[AreaToken]);
Assert.AreEqual("Index", endpoint2.RoutePattern.Defaults[ActionToken]);
Assert.AreEqual(
ControllerExtensions.GetControllerName<InstallController>(),
endpoint2.RoutePattern.Defaults[ControllerToken]);
Assert.AreEqual(
endpoint2.RoutePattern.Defaults[AreaToken],
typeof(InstallController).GetCustomAttribute<AreaAttribute>(false).RouteValue);
var dataSource = endpoints.DataSources.Last();
Assert.AreEqual(2, dataSource.Endpoints.Count);
Assert.AreEqual("Route: install/api/{action}/{id?}", dataSource.Endpoints[0].ToString());
Assert.AreEqual("Route: install/{action}/{id?}", dataSource.Endpoints[1].ToString());
}
[Test]
public void RuntimeState_Run()
{
var routes = GetInstallAreaRoutes(RuntimeLevel.Run);
var endpoints = new TestRouteBuilder();
routes.CreateRoutes(endpoints);
Assert.AreEqual(1, endpoints.DataSources.Count);
var route = endpoints.DataSources.First();
Assert.AreEqual(2, route.Endpoints.Count);
var endpoint = (RouteEndpoint)route.Endpoints[0];
Assert.AreEqual("install/api/{action}/{id?}", endpoint.RoutePattern.RawText);
endpoint = (RouteEndpoint)route.Endpoints[1];
Assert.AreEqual("install/{action}/{id?}", endpoint.RoutePattern.RawText);
}
private InstallAreaRoutes GetInstallAreaRoutes(RuntimeLevel level) =>
new(
Mock.Of<IRuntimeState>(x => x.Level == level),
Mock.Of<IHostingEnvironment>(x =>
x.ToAbsolute(It.IsAny<string>()) == "/install" && x.ApplicationVirtualPath == string.Empty),
Mock.Of<LinkGenerator>());
}

View File

@@ -1,18 +1,17 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Management.Controllers.Preview;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.BackOffice.Routing;
using Umbraco.Extensions;
using static Umbraco.Cms.Core.Constants.Web.Routing;
@@ -42,7 +41,7 @@ public class PreviewRoutesTests
var endpoints = new TestRouteBuilder();
routes.CreateRoutes(endpoints);
Assert.AreEqual(2, endpoints.DataSources.Count);
Assert.AreEqual(1, endpoints.DataSources.Count);
var route = endpoints.DataSources.First();
Assert.AreEqual(2, route.Endpoints.Count);
@@ -50,18 +49,6 @@ public class PreviewRoutesTests
Assert.AreEqual($"{routes.GetPreviewHubRoute()}/negotiate", endpoint0.RoutePattern.RawText);
var endpoint1 = (RouteEndpoint)route.Endpoints[1];
Assert.AreEqual($"{routes.GetPreviewHubRoute()}", endpoint1.RoutePattern.RawText);
var endpoint3 = (RouteEndpoint)endpoints.DataSources.Last().Endpoints[0];
var previewControllerName = ControllerExtensions.GetControllerName<PreviewController>();
Assert.AreEqual(
$"umbraco/{previewControllerName.ToLowerInvariant()}/{{action}}/{{id?}}",
endpoint3.RoutePattern.RawText);
Assert.AreEqual(Constants.Web.Mvc.BackOfficeArea, endpoint3.RoutePattern.Defaults["area"]);
Assert.AreEqual("Index", endpoint3.RoutePattern.Defaults[ActionToken]);
Assert.AreEqual(previewControllerName, endpoint3.RoutePattern.Defaults[ControllerToken]);
Assert.AreEqual(
endpoint3.RoutePattern.Defaults["area"],
typeof(PreviewController).GetCustomAttribute<AreaAttribute>(false).RouteValue);
}
private PreviewRoutes GetRoutes(RuntimeLevel level)