From dd3bdef34e5428c6ac045a43c88ace479d31f324 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 24 Mar 2019 17:17:11 +0100 Subject: [PATCH] More tests. --- src/Squidex.Web/ApiPermissionAttribute.cs | 6 +- .../Pipeline/ApiPermissionUnifier.cs | 3 +- .../ApiPermissionAttributeTests.cs | 117 ++++++++++++++++++ .../Pipeline/ApiPermissionUnifierTests.cs | 61 +++++++++ 4 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs create mode 100644 tests/Squidex.Web.Tests/Pipeline/ApiPermissionUnifierTests.cs diff --git a/src/Squidex.Web/ApiPermissionAttribute.cs b/src/Squidex.Web/ApiPermissionAttribute.cs index 1df4fd5e2..d515c76ce 100644 --- a/src/Squidex.Web/ApiPermissionAttribute.cs +++ b/src/Squidex.Web/ApiPermissionAttribute.cs @@ -49,7 +49,11 @@ namespace Squidex.Web id = id.Replace($"{{{routeParam.Key}}}", routeParam.Value?.ToString()); } - hasPermission |= set.Allows(new Permission(id)); + if (set.Allows(new Permission(id))) + { + hasPermission = true; + break; + } } if (!hasPermission) diff --git a/src/Squidex.Web/Pipeline/ApiPermissionUnifier.cs b/src/Squidex.Web/Pipeline/ApiPermissionUnifier.cs index 1751b1241..672022d73 100644 --- a/src/Squidex.Web/Pipeline/ApiPermissionUnifier.cs +++ b/src/Squidex.Web/Pipeline/ApiPermissionUnifier.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; @@ -22,7 +23,7 @@ namespace Squidex.Web.Pipeline { var identity = principal.Identities.First(); - if (string.Equals(identity.FindFirst(identity.RoleClaimType)?.Value, AdministratorRole)) + if (string.Equals(identity.FindFirst(identity.RoleClaimType)?.Value, AdministratorRole, StringComparison.OrdinalIgnoreCase)) { identity.AddClaim(new Claim(SquidexClaimTypes.Permissions, Permissions.Admin)); } diff --git a/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs b/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs new file mode 100644 index 000000000..3a539a478 --- /dev/null +++ b/tests/Squidex.Web.Tests/ApiPermissionAttributeTests.cs @@ -0,0 +1,117 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using FakeItEasy; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Routing; +using Squidex.Domain.Apps.Entities; +using Squidex.Shared; +using Squidex.Shared.Identity; +using Xunit; + +#pragma warning disable IDE0017 // Simplify object initialization + +namespace Squidex.Web.Pipeline +{ + public class ApiPermissionAttributeTests + { + private readonly IAppProvider appProvider = A.Fake(); + private readonly HttpContext httpContext = new DefaultHttpContext(); + private readonly ActionContext actionContext; + private readonly ActionExecutingContext actionExecutingContext; + private readonly ActionExecutionDelegate next; + private readonly ClaimsIdentity user = new ClaimsIdentity(); + private bool isNextCalled; + + public ApiPermissionAttributeTests() + { + actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor + { + FilterDescriptors = new List() + }); + + actionExecutingContext = new ActionExecutingContext(actionContext, new List(), new Dictionary(), this); + actionExecutingContext.HttpContext = httpContext; + actionExecutingContext.HttpContext.User = new ClaimsPrincipal(user); + + next = () => + { + isNextCalled = true; + + return Task.FromResult(null); + }; + } + + [Fact] + public void Should_use_bearer_schemes() + { + var sut = new ApiPermissionAttribute(); + + Assert.Equal("Bearer", sut.AuthenticationSchemes); + } + + [Fact] + public async Task Should_call_next_when_user_has_correct_permission() + { + actionExecutingContext.RouteData.Values["app"] = "my-app"; + + user.AddClaim(new Claim(SquidexClaimTypes.Permissions, "squidex.apps.my-app")); + + var sut = new ApiPermissionAttribute(Permissions.AppSchemasRead); + + await sut.OnActionExecutionAsync(actionExecutingContext, next); + + Assert.Null(actionExecutingContext.Result); + Assert.True(isNextCalled); + } + + [Fact] + public async Task Should_return_forbidden_when_user_has_wrong_permission() + { + actionExecutingContext.RouteData.Values["app"] = "my-app"; + + user.AddClaim(new Claim(SquidexClaimTypes.Permissions, "squidex.apps.other-app")); + + var sut = new ApiPermissionAttribute(Permissions.AppSchemasRead); + + await sut.OnActionExecutionAsync(actionExecutingContext, next); + + Assert.Equal(403, (actionExecutingContext.Result as StatusCodeResult)?.StatusCode); + Assert.False(isNextCalled); + } + + [Fact] + public async Task Should_return_forbidden_when_route_data_has_no_value() + { + user.AddClaim(new Claim(SquidexClaimTypes.Permissions, "squidex.apps.other-app")); + + var sut = new ApiPermissionAttribute(Permissions.AppSchemasRead); + + await sut.OnActionExecutionAsync(actionExecutingContext, next); + + Assert.Equal(403, (actionExecutingContext.Result as StatusCodeResult)?.StatusCode); + Assert.False(isNextCalled); + } + + [Fact] + public async Task Should_return_forbidden_when_user_has_no_permission() + { + var sut = new ApiPermissionAttribute(Permissions.AppSchemasRead); + + await sut.OnActionExecutionAsync(actionExecutingContext, next); + + Assert.Equal(403, (actionExecutingContext.Result as StatusCodeResult)?.StatusCode); + Assert.False(isNextCalled); + } + } +} diff --git a/tests/Squidex.Web.Tests/Pipeline/ApiPermissionUnifierTests.cs b/tests/Squidex.Web.Tests/Pipeline/ApiPermissionUnifierTests.cs new file mode 100644 index 000000000..265658925 --- /dev/null +++ b/tests/Squidex.Web.Tests/Pipeline/ApiPermissionUnifierTests.cs @@ -0,0 +1,61 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Squidex.Shared; +using Squidex.Shared.Identity; +using Xunit; + +namespace Squidex.Web.Pipeline +{ + public class ApiPermissionUnifierTests + { + private readonly ApiPermissionUnifier sut = new ApiPermissionUnifier(); + + [Theory] + [InlineData("administrator")] + [InlineData("ADMINISTRATOR")] + public async Task Should_add_admin_permission_when_user_is_in_role(string role) + { + var userIdentity = new ClaimsIdentity(); + var userPrinicpal = new ClaimsPrincipal(userIdentity); + + userIdentity.AddClaim(new Claim(userIdentity.RoleClaimType, role)); + + var result = await sut.TransformAsync(userPrinicpal); + + Assert.Equal(Permissions.Admin, result.Claims.FirstOrDefault(x => x.Type == SquidexClaimTypes.Permissions)?.Value); + Assert.Equal(role, result.Claims.FirstOrDefault(x => x.Type == userIdentity.RoleClaimType)?.Value); + } + + [Fact] + public async Task Should_not_add_admin_persmission_when_user_has_other_role() + { + var userIdentity = new ClaimsIdentity(); + var userPrinicpal = new ClaimsPrincipal(userIdentity); + + userIdentity.AddClaim(new Claim(userIdentity.RoleClaimType, "Developer")); + + var result = await sut.TransformAsync(userPrinicpal); + + Assert.Single(result.Claims); + } + + [Fact] + public async Task Should_not_add_admin_persmission_when_user_has_no_role() + { + var userIdentity = new ClaimsIdentity(); + var userPrinicpal = new ClaimsPrincipal(userIdentity); + + var result = await sut.TransformAsync(userPrinicpal); + + Assert.Empty(result.Claims); + } + } +}