From e178cd08b79b6e81129acd00404be5b4d0c288d4 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Wed, 2 Dec 2020 19:50:56 +0100 Subject: [PATCH] Added tests for TreeHandler. --- .../Builders/TreeBuilder.cs | 79 ++++++++++++ .../Authorization/TreeHandlerTests.cs | 114 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 src/Umbraco.Tests.Common/Builders/TreeBuilder.cs create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Authorization/TreeHandlerTests.cs diff --git a/src/Umbraco.Tests.Common/Builders/TreeBuilder.cs b/src/Umbraco.Tests.Common/Builders/TreeBuilder.cs new file mode 100644 index 0000000000..072e838d5a --- /dev/null +++ b/src/Umbraco.Tests.Common/Builders/TreeBuilder.cs @@ -0,0 +1,79 @@ +using Umbraco.Core; +using Umbraco.Tests.Common.Builders.Interfaces; +using Umbraco.Web.Trees; + +namespace Umbraco.Tests.Common.Builders +{ + public class TreeBuilder + : BuilderBase, + IWithAliasBuilder, + IWithSortOrderBuilder + { + private int? _sortOrder; + private string _alias; + private string _sectionAlias; + private string _group; + private string _title; + private TreeUse? _treeUse; + private bool? _isSingleNode; + + public TreeBuilder WithSectionAlias(string sectionAlias) + { + _sectionAlias = sectionAlias; + return this; + } + + public TreeBuilder WithGroup(string group) + { + _group = group; + return this; + } + + public TreeBuilder WithTitle(string title) + { + _title = title; + return this; + } + + public TreeBuilder WithTreeUse(TreeUse treeUse) + { + _treeUse = treeUse; + return this; + } + + public TreeBuilder WithTreeUse(bool isSingleNode) + { + _isSingleNode = isSingleNode; + return this; + } + + public override Tree Build() + { + var sortOrder = _sortOrder ?? 1; + var alias = _alias ?? "testTree"; + var sectionAlias = _sectionAlias ?? Constants.Applications.Content; + var group = _group ?? string.Empty; + var title = _title ?? string.Empty; + var treeUse = _treeUse ?? TreeUse.Main; + var isSingleNode = _isSingleNode ?? false; + + return new Tree(sortOrder, sectionAlias, group, alias, title, treeUse, typeof(SampleTreeController), isSingleNode); + } + + string IWithAliasBuilder.Alias + { + get => _alias; + set => _alias = value; + } + + int? IWithSortOrderBuilder.SortOrder + { + get => _sortOrder; + set => _sortOrder = value; + } + + private class SampleTreeController + { + } + } +} diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Authorization/TreeHandlerTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Authorization/TreeHandlerTests.cs new file mode 100644 index 0000000000..8c688d10d3 --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Authorization/TreeHandlerTests.cs @@ -0,0 +1,114 @@ +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Models.Membership; +using Umbraco.Core.Security; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Common.Builders.Extensions; +using Umbraco.Web.BackOffice.Authorization; +using Umbraco.Web.Services; +using Umbraco.Web.Trees; + +namespace Umbraco.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(userIsAuthorized: true, userCanAccessContentSection: 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(userIsAuthorized: 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())); + var resource = new object(); + return new AuthorizationHandlerContext(new List { 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 CreateMockTreeService() + { + var mockTreeService = new Mock(); + mockTreeService + .Setup(x => x.GetByAlias(It.Is(y => y == Tree1Alias))) + .Returns(CreateTree(Tree1Alias, Constants.Applications.Content)); + mockTreeService + .Setup(x => x.GetByAlias(It.Is(y => y == Tree2Alias))) + .Returns(CreateTree(Tree2Alias, Constants.Applications.Media)); + return mockTreeService; + } + + private static Tree CreateTree(string alias, string sectionAlias) + { + return new TreeBuilder() + .WithAlias(alias) + .WithSectionAlias(sectionAlias) + .Build(); + } + + private static Mock CreateMockBackOfficeSecurityAccessor(bool userIsAuthorized, bool userCanAccessContentSection) + { + var user = CreateUser(); + var mockBackOfficeSecurity = new Mock(); + mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(userIsAuthorized ? user : null); + mockBackOfficeSecurity + .Setup(x => x.UserHasSectionAccess(Constants.Applications.Content, It.Is(y => y.Username == user.Username))) + .Returns(userCanAccessContentSection); + mockBackOfficeSecurity + .Setup(x => x.UserHasSectionAccess(Constants.Applications.Media, It.Is(y => y.Username == user.Username))) + .Returns(false); + var mockBackOfficeSecurityAccessor = new Mock(); + mockBackOfficeSecurityAccessor.Setup(x => x.BackOfficeSecurity).Returns(mockBackOfficeSecurity.Object); + return mockBackOfficeSecurityAccessor; + } + + private static User CreateUser() + { + return new UserBuilder() + .Build(); + } + } +}