mirror of https://github.com/Squidex/squidex.git
16 changed files with 1056 additions and 2 deletions
@ -0,0 +1,14 @@ |
|||||
|
// ==========================================================================
|
||||
|
// GlobalSuppressions.cs
|
||||
|
// CivicPlus implementation of Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
|
// attributes that are applied to this project.
|
||||
|
// Project-level suppressions either have no target or are given
|
||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
|
||||
|
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File must have header", Justification = "CP Has their own headers.")] |
||||
|
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1652:Enable XML documentation output", Justification = "CP Has their own headers.")] |
||||
|
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives must be placed correctly", Justification = "Usings should be outside namespace")] |
||||
|
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "this. prefix isn't necessary.")] |
||||
|
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters must start on line after declaration", Justification = "Not necessary")] |
||||
@ -0,0 +1,86 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Abstractions; |
||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Moq; |
||||
|
using Squidex.Infrastructure.Log; |
||||
|
using Squidex.Pipeline; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline |
||||
|
{ |
||||
|
public class ActionContextLogAppenderTests |
||||
|
{ |
||||
|
private readonly Mock<IActionContextAccessor> actionContextAccessor = new Mock<IActionContextAccessor>(); |
||||
|
private readonly Mock<HttpContext> httpContextMock = new Mock<HttpContext>(); |
||||
|
private readonly Mock<ActionDescriptor> actionDescriptor = new Mock<ActionDescriptor>(); |
||||
|
private readonly RouteData routeData = new RouteData(); |
||||
|
private readonly Guid requestId = Guid.NewGuid(); |
||||
|
private readonly IDictionary<object, object> items = new Dictionary<object, object>(); |
||||
|
private readonly IObjectWriter writer = A.Fake<IObjectWriter>(); |
||||
|
private readonly HttpRequest request = A.Fake<HttpRequest>(); |
||||
|
private ActionContextLogAppender sut; |
||||
|
private ActionContext actionContext; |
||||
|
|
||||
|
[Fact] |
||||
|
public void Append_should_get_requestId() |
||||
|
{ |
||||
|
items.Add(nameof(requestId), requestId); |
||||
|
SetupTest(); |
||||
|
|
||||
|
A.CallTo(() => writer.WriteObject(It.IsAny<string>(), It.IsAny<Action<IObjectWriter>>())).Returns(writer); |
||||
|
sut.Append(writer); |
||||
|
|
||||
|
Assert.NotNull(writer); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Append_should_put_requestId() |
||||
|
{ |
||||
|
SetupTest(); |
||||
|
|
||||
|
sut.Append(writer); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Append_should_return_if_no_actionContext() |
||||
|
{ |
||||
|
sut = new ActionContextLogAppender(actionContextAccessor.Object); |
||||
|
|
||||
|
sut.Append(writer); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Append_should_return_if_no_httpContext_method() |
||||
|
{ |
||||
|
A.CallTo(() => request.Method).Returns(string.Empty); |
||||
|
httpContextMock.Setup(x => x.Request).Returns(request); |
||||
|
actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
actionContextAccessor.Setup(x => x.ActionContext).Returns(actionContext); |
||||
|
sut = new ActionContextLogAppender(actionContextAccessor.Object); |
||||
|
|
||||
|
sut.Append(writer); |
||||
|
} |
||||
|
|
||||
|
private void SetupTest() |
||||
|
{ |
||||
|
A.CallTo(() => request.Method).Returns("Get"); |
||||
|
httpContextMock.Setup(x => x.Items).Returns(items); |
||||
|
httpContextMock.Setup(x => x.Request).Returns(request); |
||||
|
actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
actionContextAccessor.Setup(x => x.ActionContext).Returns(actionContext); |
||||
|
sut = new ActionContextLogAppender(actionContextAccessor.Object); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using IdentityServer4.AccessTokenValidation; |
||||
|
using Squidex.Pipeline; |
||||
|
using Squidex.Shared.Identity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline |
||||
|
{ |
||||
|
public class ApiAuthorizeAttributeTests |
||||
|
{ |
||||
|
private ApiAuthorizeAttribute sut = new ApiAuthorizeAttribute(); |
||||
|
|
||||
|
[Fact] |
||||
|
public void AuthenticationSchemes_should_be_default() |
||||
|
{ |
||||
|
Assert.Equal(IdentityServerAuthenticationDefaults.AuthenticationScheme, sut.AuthenticationSchemes); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void MustBeAdmin_Test() |
||||
|
{ |
||||
|
sut = new MustBeAdministratorAttribute(); |
||||
|
Assert.Equal(SquidexRoles.Administrator, sut.Roles); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,104 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Http.Features; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Abstractions; |
||||
|
using Microsoft.AspNetCore.Mvc.Filters; |
||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Moq; |
||||
|
using Squidex.Domain.Apps.Entities.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Services; |
||||
|
using Squidex.Infrastructure.UsageTracking; |
||||
|
using Squidex.Pipeline; |
||||
|
using Xunit; |
||||
|
using static Squidex.Pipeline.AppApiFilter; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline |
||||
|
{ |
||||
|
public class ApiCostTests |
||||
|
{ |
||||
|
private readonly Mock<IActionContextAccessor> actionContextAccessor = new Mock<IActionContextAccessor>(); |
||||
|
private readonly RouteData routeData = new RouteData(); |
||||
|
private readonly Mock<ActionDescriptor> actionDescriptor = new Mock<ActionDescriptor>(); |
||||
|
private readonly IAppPlansProvider appPlanProvider = A.Fake<IAppPlansProvider>(); |
||||
|
private readonly IUsageTracker usageTracker = A.Fake<IUsageTracker>(); |
||||
|
private readonly long usage = 1; |
||||
|
private readonly Mock<HttpContext> httpContextMock = new Mock<HttpContext>(); |
||||
|
private readonly IFeatureCollection features = new FeatureCollection(); |
||||
|
private readonly IAppEntity appEntity = A.Fake<IAppEntity>(); |
||||
|
private readonly IAppFeature appFeature = A.Fake<IAppFeature>(); |
||||
|
private readonly IAppLimitsPlan appPlan = A.Fake<IAppLimitsPlan>(); |
||||
|
private readonly Guid appId = Guid.NewGuid(); |
||||
|
private ActionExecutingContext context; |
||||
|
private ActionExecutionDelegate next; |
||||
|
private ApiCostsFilter sut; |
||||
|
|
||||
|
public ApiCostTests() |
||||
|
{ |
||||
|
var actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
actionContextAccessor.Setup(x => x.ActionContext).Returns(actionContext); |
||||
|
context = new ActionExecutingContext(actionContext, new List<IFilterMetadata>(), new Dictionary<string, object>(), null); |
||||
|
context.Filters.Add(new ServiceFilterAttribute(typeof(ApiCostsFilter))); |
||||
|
|
||||
|
A.CallTo(() => appEntity.Id).Returns(appId); |
||||
|
A.CallTo(() => appFeature.App).Returns(appEntity); |
||||
|
|
||||
|
features.Set<IAppFeature>(new AppFeature(appEntity)); |
||||
|
httpContextMock.Setup(x => x.Features).Returns(features); |
||||
|
A.CallTo(() => usageTracker.GetMonthlyCalls(appId.ToString(), DateTime.Today)) |
||||
|
.Returns(usage); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_return_429_status_code_if_max_calls_over_limit() |
||||
|
{ |
||||
|
SetupSystem(2, 1); |
||||
|
|
||||
|
next = new ActionExecutionDelegate(async () => |
||||
|
{ |
||||
|
return null; |
||||
|
}); |
||||
|
await sut.OnActionExecutionAsync(context, next); |
||||
|
|
||||
|
Assert.Equal(new StatusCodeResult(429).StatusCode, (context.Result as StatusCodeResult).StatusCode); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_call_next_if_weight_is_0() |
||||
|
{ |
||||
|
SetupSystem(0, 1); |
||||
|
|
||||
|
var result = 0; |
||||
|
next = new ActionExecutionDelegate(async () => |
||||
|
{ |
||||
|
result = 1; |
||||
|
return null; |
||||
|
}); |
||||
|
await sut.OnActionExecutionAsync(context, next); |
||||
|
|
||||
|
Assert.Equal(1, result); |
||||
|
} |
||||
|
|
||||
|
private ApiCostsFilter SetupSystem(double weight, long maxCalls) |
||||
|
{ |
||||
|
A.CallTo(() => appPlan.MaxApiCalls).Returns(maxCalls); |
||||
|
A.CallTo(() => appPlanProvider.GetPlanForApp(appFeature.App)).Returns(appPlan); |
||||
|
|
||||
|
sut = new ApiCostsFilter(appPlanProvider, usageTracker); |
||||
|
sut.FilterDefinition = new ApiCostsAttribute(weight); |
||||
|
|
||||
|
return sut; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,101 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
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 Squidex.Domain.Apps.Entities.Apps; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Pipeline; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline |
||||
|
{ |
||||
|
public class ApiExceptionFilterAttributeTests |
||||
|
{ |
||||
|
private readonly Mock<HttpContext> httpContextMock = new Mock<HttpContext>(); |
||||
|
private readonly Mock<ActionDescriptor> actionDescriptor = new Mock<ActionDescriptor>(); |
||||
|
private readonly RouteData routeData = new RouteData(); |
||||
|
private readonly ApiExceptionFilterAttribute sut = new ApiExceptionFilterAttribute(); |
||||
|
private readonly ExceptionContext context; |
||||
|
private ActionContext actionContext; |
||||
|
|
||||
|
public ApiExceptionFilterAttributeTests() |
||||
|
{ |
||||
|
actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
context = new ExceptionContext(actionContext, new List<IFilterMetadata>()); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Domain_Object_Not_Found_Exception_should_be_caught() |
||||
|
{ |
||||
|
context.Exception = new DomainObjectNotFoundException("id", typeof(IAppEntity)); |
||||
|
|
||||
|
sut.OnException(context); |
||||
|
|
||||
|
Assert.Equal(new NotFoundResult().StatusCode, (context.Result as NotFoundResult).StatusCode); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Domain_Object_Version_Exception_should_be_caught() |
||||
|
{ |
||||
|
context.Exception = new DomainObjectVersionException("id", typeof(IAppEntity), 0, 1); |
||||
|
|
||||
|
sut.OnException(context); |
||||
|
var exptectedResult = BuildErrorResult(412, new ErrorDto { Message = context.Exception.Message }); |
||||
|
|
||||
|
Assert.Equal(exptectedResult.StatusCode, (context.Result as ObjectResult).StatusCode); |
||||
|
Assert.StartsWith("Requested version", ((context.Result as ObjectResult).Value as ErrorDto).Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Domain_Exception_should_be_caught() |
||||
|
{ |
||||
|
context.Exception = new DomainException("Domain exception caught."); |
||||
|
|
||||
|
sut.OnException(context); |
||||
|
var exptectedResult = BuildErrorResult(400, new ErrorDto { Message = context.Exception.Message }); |
||||
|
|
||||
|
Assert.Equal(exptectedResult.StatusCode, (context.Result as ObjectResult).StatusCode); |
||||
|
Assert.Equal("Domain exception caught.", ((context.Result as ObjectResult).Value as ErrorDto).Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Domain_Forbidden_Exception_should_be_caught() |
||||
|
{ |
||||
|
context.Exception = new DomainForbiddenException("Domain forbidden exception caught."); |
||||
|
|
||||
|
sut.OnException(context); |
||||
|
var exptectedResult = BuildErrorResult(403, new ErrorDto { Message = context.Exception.Message }); |
||||
|
|
||||
|
Assert.Equal(exptectedResult.StatusCode, (context.Result as ObjectResult).StatusCode); |
||||
|
Assert.Equal("Domain forbidden exception caught.", ((context.Result as ObjectResult).Value as ErrorDto).Message); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Validation_Exception_should_be_caught() |
||||
|
{ |
||||
|
var errors = new ValidationError("Validation error 1", new string[] { "prop1" }); |
||||
|
context.Exception = new ValidationException("Validation exception caught.", errors); |
||||
|
|
||||
|
sut.OnException(context); |
||||
|
var exptectedResult = BuildErrorResult(400, new ErrorDto { Message = context.Exception.Message }); |
||||
|
|
||||
|
Assert.Equal(exptectedResult.StatusCode, (context.Result as ObjectResult).StatusCode); |
||||
|
Assert.Equal("Validation exception caught: Validation error 1.", ((context.Result as ObjectResult).Value as ErrorDto).Message); |
||||
|
} |
||||
|
|
||||
|
private ObjectResult BuildErrorResult(int code, ErrorDto error) |
||||
|
{ |
||||
|
return new ObjectResult(error) { StatusCode = code }; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Net; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Http.Features; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Abstractions; |
||||
|
using Microsoft.AspNetCore.Mvc.Filters; |
||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Moq; |
||||
|
using Squidex.Domain.Apps.Entities; |
||||
|
using Squidex.Domain.Apps.Entities.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Services; |
||||
|
using Squidex.Infrastructure.UsageTracking; |
||||
|
using Squidex.Pipeline; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline |
||||
|
{ |
||||
|
public class AppApiTests |
||||
|
{ |
||||
|
private readonly Mock<IActionContextAccessor> actionContextAccessor = new Mock<IActionContextAccessor>(); |
||||
|
private readonly RouteData routeData = new RouteData(); |
||||
|
private readonly Mock<ActionDescriptor> actionDescriptor = new Mock<ActionDescriptor>(); |
||||
|
private readonly IAppPlansProvider appPlanProvider = A.Fake<IAppPlansProvider>(); |
||||
|
private readonly IUsageTracker usageTracker = A.Fake<IUsageTracker>(); |
||||
|
private readonly long usage = 1; |
||||
|
private readonly Mock<HttpContext> httpContextMock = new Mock<HttpContext>(); |
||||
|
private readonly IFeatureCollection features = new FeatureCollection(); |
||||
|
private readonly IAppEntity appEntity = A.Fake<IAppEntity>(); |
||||
|
private readonly IAppFeature appFeature = A.Fake<IAppFeature>(); |
||||
|
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
||||
|
private readonly Guid appId = Guid.NewGuid(); |
||||
|
private readonly ActionExecutingContext context; |
||||
|
private readonly AppApiFilter sut; |
||||
|
private ActionExecutionDelegate next; |
||||
|
|
||||
|
public AppApiTests() |
||||
|
{ |
||||
|
var actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
actionContextAccessor.Setup(x => x.ActionContext).Returns(actionContext); |
||||
|
context = new ActionExecutingContext(actionContext, new List<IFilterMetadata>(), new Dictionary<string, object>(), null); |
||||
|
context.Filters.Add(new AppApiAttribute()); |
||||
|
context.RouteData.Values.Add("app", "appName"); |
||||
|
|
||||
|
httpContextMock.Setup(x => x.Features).Returns(features); |
||||
|
A.CallTo(() => appProvider.GetAppAsync("appName")).Returns(appEntity); |
||||
|
|
||||
|
sut = new AppApiFilter(appProvider); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_set_features_if_app_found() |
||||
|
{ |
||||
|
next = new ActionExecutionDelegate(async () => |
||||
|
{ |
||||
|
return null; |
||||
|
}); |
||||
|
await sut.OnActionExecutionAsync(context, next); |
||||
|
|
||||
|
Assert.NotEmpty(context.HttpContext.Features); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_return_not_found_result_if_app_not_found() |
||||
|
{ |
||||
|
next = new ActionExecutionDelegate(async () => |
||||
|
{ |
||||
|
return null; |
||||
|
}); |
||||
|
|
||||
|
A.CallTo(() => appProvider.GetAppAsync("appName")).Returns((IAppEntity)null); |
||||
|
await sut.OnActionExecutionAsync(context, next); |
||||
|
|
||||
|
var result = context.Result as NotFoundResult; |
||||
|
Assert.NotNull(result); |
||||
|
Assert.Equal((int)HttpStatusCode.NotFound, result.StatusCode); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,130 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
using System.Linq; |
||||
|
using System.Net; |
||||
|
using System.Security.Claims; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Http.Features; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Abstractions; |
||||
|
using Microsoft.AspNetCore.Mvc.Filters; |
||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Moq; |
||||
|
using Squidex.Domain.Apps.Core.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps; |
||||
|
using Squidex.Infrastructure.Security; |
||||
|
using Squidex.Pipeline; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline |
||||
|
{ |
||||
|
public class AppPermissionAttributeTests |
||||
|
{ |
||||
|
private readonly Mock<HttpContext> httpContextMock = new Mock<HttpContext>(); |
||||
|
private readonly Mock<ClaimsPrincipal> mockUser = new Mock<ClaimsPrincipal>(); |
||||
|
private readonly Mock<ActionDescriptor> actionDescriptor = new Mock<ActionDescriptor>(); |
||||
|
private readonly Mock<IActionContextAccessor> actionContextAccessor = new Mock<IActionContextAccessor>(); |
||||
|
private readonly IAppEntity appEntity = A.Fake<IAppEntity>(); |
||||
|
private readonly ClaimsIdentity identity = new ClaimsIdentity(); |
||||
|
private readonly AppClient client = new AppClient("clientId", "secret", AppClientPermission.Reader); |
||||
|
private readonly IAppFeature appFeature = A.Fake<IAppFeature>(); |
||||
|
private readonly IFeatureCollection features = new FeatureCollection(); |
||||
|
private readonly RouteData routeData = new RouteData(); |
||||
|
private readonly ActionExecutingContext context; |
||||
|
private ActionContext actionContext; |
||||
|
private Claim clientClaim; |
||||
|
private Claim subjectClaim; |
||||
|
private AppPermissionAttribute sut = new MustBeAppReaderAttribute(); |
||||
|
|
||||
|
public AppPermissionAttributeTests() |
||||
|
{ |
||||
|
actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
actionContextAccessor.Setup(x => x.ActionContext).Returns(actionContext); |
||||
|
clientClaim = new Claim("client_id", $"test:clientId"); |
||||
|
subjectClaim = new Claim("sub", "user"); |
||||
|
|
||||
|
var clients = ImmutableDictionary.CreateBuilder<string, AppClient>(); |
||||
|
clients.Add("clientId", client); |
||||
|
var contributors = ImmutableDictionary.CreateBuilder<string, AppContributorPermission>(); |
||||
|
contributors.Add("user", AppContributorPermission.Owner); |
||||
|
|
||||
|
A.CallTo(() => appFeature.App).Returns(appEntity); |
||||
|
A.CallTo(() => appEntity.Clients).Returns(new AppClients(clients.ToImmutable())); |
||||
|
A.CallTo(() => appEntity.Contributors).Returns(new AppContributors(contributors.ToImmutable())); |
||||
|
features.Set<IAppFeature>(appFeature); |
||||
|
mockUser.Setup(x => x.Identities).Returns(new List<ClaimsIdentity> { identity }); |
||||
|
|
||||
|
httpContextMock.Setup(x => x.Features).Returns(features); |
||||
|
httpContextMock.Setup(x => x.User).Returns(mockUser.Object); |
||||
|
|
||||
|
context = new ActionExecutingContext(actionContext, new List<IFilterMetadata>(), new Dictionary<string, object>(), null); |
||||
|
context.Filters.Clear(); |
||||
|
sut = new MustBeAppDeveloperAttribute(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Null_Permission_Returns_Not_Found() |
||||
|
{ |
||||
|
// Arrange
|
||||
|
sut = new MustBeAppReaderAttribute(); |
||||
|
context.Filters.Add(sut); |
||||
|
mockUser.Setup(x => x.FindFirst(OpenIdClaims.Subject)).Returns((Claim)null); |
||||
|
clientClaim = new Claim("client_id", "test"); |
||||
|
mockUser.Setup(x => x.FindFirst(OpenIdClaims.ClientId)).Returns(clientClaim); |
||||
|
|
||||
|
// Act
|
||||
|
sut.OnActionExecuting(context); |
||||
|
|
||||
|
// Assert
|
||||
|
var result = context.Result as NotFoundResult; |
||||
|
Assert.NotNull(result); |
||||
|
Assert.Equal((int)HttpStatusCode.NotFound, result.StatusCode); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Lower_Permission_Returns_Forbidden() |
||||
|
{ |
||||
|
// Arrange
|
||||
|
sut = new MustBeAppEditorAttribute(); |
||||
|
context.Filters.Add(sut); |
||||
|
mockUser.Setup(x => x.FindFirst(OpenIdClaims.Subject)).Returns((Claim)null); |
||||
|
mockUser.Setup(x => x.FindFirst(OpenIdClaims.ClientId)).Returns(clientClaim); |
||||
|
|
||||
|
// Act
|
||||
|
sut.OnActionExecuting(context); |
||||
|
|
||||
|
// Assert
|
||||
|
var result = context.Result as StatusCodeResult; |
||||
|
Assert.NotNull(result); |
||||
|
Assert.Equal((int)HttpStatusCode.Forbidden, result.StatusCode); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Higher_Permission_Should_Get_All_Lesser_Permissions() |
||||
|
{ |
||||
|
// Arrange
|
||||
|
sut = new MustBeAppOwnerAttribute(); |
||||
|
context.Filters.Add(sut); |
||||
|
mockUser.Setup(x => x.FindFirst(OpenIdClaims.Subject)).Returns(subjectClaim); |
||||
|
|
||||
|
// Act
|
||||
|
sut.OnActionExecuting(context); |
||||
|
|
||||
|
// Assert
|
||||
|
var result = context.HttpContext.User.Identities.First()?.Claims; |
||||
|
Assert.NotNull(result); |
||||
|
Assert.NotEmpty(result); |
||||
|
Assert.Equal(Enum.GetNames(typeof(AppPermission)).Length, result.Count()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.Extensions.Primitives; |
||||
|
using Squidex.Domain.Apps.Entities.Assets.Commands; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
using Squidex.Pipeline.CommandMiddlewares; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline.CommandMiddlewares |
||||
|
{ |
||||
|
public class ETagCommandMiddlewareTests |
||||
|
{ |
||||
|
private readonly IHttpContextAccessor httpContextAccessor = A.Fake<IHttpContextAccessor>(); |
||||
|
private readonly ICommandBus commandBus = A.Fake<ICommandBus>(); |
||||
|
private readonly IHeaderDictionary headers = new HeaderDictionary { { "If-Match", "1" } }; |
||||
|
private readonly UpdateAsset command = new UpdateAsset(); |
||||
|
private readonly EntitySavedResult entitySavedResult = new EntitySavedResult(1); |
||||
|
private readonly ETagCommandMiddleware sut; |
||||
|
|
||||
|
public ETagCommandMiddlewareTests() |
||||
|
{ |
||||
|
A.CallTo(() => httpContextAccessor.HttpContext.Request.Headers).Returns(headers); |
||||
|
sut = new ETagCommandMiddleware(httpContextAccessor); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_add_etag_header_and_expected_version() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
context.Complete(entitySavedResult); |
||||
|
|
||||
|
await sut.HandleAsync(context); |
||||
|
|
||||
|
Assert.Equal(1, context.Command.ExpectedVersion); |
||||
|
Assert.Equal(new StringValues("1"), httpContextAccessor.HttpContext.Response.Headers["ETag"]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Security; |
||||
|
using System.Security.Claims; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Squidex.Domain.Apps.Entities.Contents.Commands; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
using Squidex.Infrastructure.Security; |
||||
|
using Squidex.Pipeline.CommandMiddlewares; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline.CommandMiddlewares |
||||
|
{ |
||||
|
public class EnrichWithActorCommandMiddlewareTests |
||||
|
{ |
||||
|
private readonly IHttpContextAccessor httpContextAccessor = A.Fake<IHttpContextAccessor>(); |
||||
|
private readonly ICommandBus commandBus = A.Fake<ICommandBus>(); |
||||
|
private readonly CreateContent command = new CreateContent { Actor = null }; |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_throw_security_exception() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
var sut = SetupSystem(null, out string claimValue); |
||||
|
|
||||
|
await Assert.ThrowsAsync<SecurityException>(() => |
||||
|
{ |
||||
|
return sut.HandleAsync(context); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_find_actor_from_subject() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
var sut = SetupSystem("subject", out string claimValue); |
||||
|
|
||||
|
await sut.HandleAsync(context); |
||||
|
|
||||
|
Assert.Equal(claimValue, command.Actor.Identifier); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_find_actor_from_client() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
var sut = SetupSystem("client", out string claimValue); |
||||
|
|
||||
|
await sut.HandleAsync(context); |
||||
|
|
||||
|
Assert.Equal(claimValue, command.Actor.Identifier); |
||||
|
} |
||||
|
|
||||
|
private EnrichWithActorCommandMiddleware SetupSystem(string refTokenType, out string claimValue) |
||||
|
{ |
||||
|
Claim actorClaim; |
||||
|
claimValue = Guid.NewGuid().ToString(); |
||||
|
var user = new ClaimsPrincipal(); |
||||
|
var claimsIdentity = new ClaimsIdentity(); |
||||
|
switch (refTokenType) |
||||
|
{ |
||||
|
case "subject": |
||||
|
actorClaim = new Claim(OpenIdClaims.Subject, claimValue); |
||||
|
claimsIdentity.AddClaim(actorClaim); |
||||
|
break; |
||||
|
case "client": |
||||
|
actorClaim = new Claim(OpenIdClaims.ClientId, claimValue); |
||||
|
claimsIdentity.AddClaim(actorClaim); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
user.AddIdentity(claimsIdentity); |
||||
|
A.CallTo(() => httpContextAccessor.HttpContext.User).Returns(user); |
||||
|
return new EnrichWithActorCommandMiddleware(httpContextAccessor); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Squidex.Domain.Apps.Entities.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.State; |
||||
|
using Squidex.Domain.Apps.Entities.Contents.Commands; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
using Squidex.Pipeline; |
||||
|
using Squidex.Pipeline.CommandMiddlewares; |
||||
|
using Xunit; |
||||
|
using static Squidex.Pipeline.AppApiFilter; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline.CommandMiddlewares |
||||
|
{ |
||||
|
public class EnrichWithAppIdCommandMiddlewareTests |
||||
|
{ |
||||
|
private readonly IHttpContextAccessor httpContextAccessor = A.Fake<IHttpContextAccessor>(); |
||||
|
private readonly ICommandBus commandBus = A.Fake<ICommandBus>(); |
||||
|
private readonly CreateContent command = new CreateContent { AppId = null }; |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_throw_exception_if_app_id_not_found() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
var sut = SetupSystem(null); |
||||
|
|
||||
|
await Assert.ThrowsAsync<InvalidOperationException>(() => |
||||
|
{ |
||||
|
return sut.HandleAsync(context); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_find_app_id_from_features() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
var app = new AppState |
||||
|
{ |
||||
|
Name = "app", |
||||
|
Id = Guid.NewGuid() |
||||
|
}; |
||||
|
var sut = SetupSystem(app); |
||||
|
|
||||
|
await sut.HandleAsync(context); |
||||
|
|
||||
|
Assert.Equal(new NamedId<Guid>(app.Id, app.Name), command.AppId); |
||||
|
} |
||||
|
|
||||
|
private EnrichWithAppIdCommandMiddleware SetupSystem(IAppEntity app) |
||||
|
{ |
||||
|
var appFeature = app == null ? null : new AppFeature(app); |
||||
|
A.CallTo(() => httpContextAccessor.HttpContext.Features.Get<IAppFeature>()).Returns(appFeature); |
||||
|
|
||||
|
return new EnrichWithAppIdCommandMiddleware(httpContextAccessor); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,124 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.Abstractions; |
||||
|
using Microsoft.AspNetCore.Mvc.Infrastructure; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Moq; |
||||
|
using Squidex.Domain.Apps.Core; |
||||
|
using Squidex.Domain.Apps.Core.Schemas; |
||||
|
using Squidex.Domain.Apps.Entities; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Domain.Apps.Entities.Contents.Commands; |
||||
|
using Squidex.Domain.Apps.Entities.Schemas; |
||||
|
using Squidex.Domain.Apps.Entities.Schemas.State; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
using Squidex.Pipeline.CommandMiddlewares; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline.CommandMiddlewares |
||||
|
{ |
||||
|
public class EnrichWithSchemaIdCommandMiddlewareTests |
||||
|
{ |
||||
|
private readonly Mock<IActionContextAccessor> actionContextAccessor = new Mock<IActionContextAccessor>(); |
||||
|
private readonly ICommandBus commandBus = A.Fake<ICommandBus>(); |
||||
|
private readonly Mock<HttpContext> httpContextMock = new Mock<HttpContext>(); |
||||
|
private readonly Mock<ActionDescriptor> actionDescriptor = new Mock<ActionDescriptor>(); |
||||
|
private readonly IAppProvider appProvider = A.Fake<IAppProvider>(); |
||||
|
private readonly Guid appId = Guid.NewGuid(); |
||||
|
private readonly string appName = "app"; |
||||
|
private readonly Guid schemaId = Guid.NewGuid(); |
||||
|
private readonly string schemaName = "schema"; |
||||
|
private readonly CreateContent command = new CreateContent(); |
||||
|
private readonly RouteData routeData = new RouteData(); |
||||
|
private ISchemaEntity schema; |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_throw_exception_if_schema_not_found() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
var sut = SetupSchemaCommand(false); |
||||
|
|
||||
|
await Assert.ThrowsAsync<DomainObjectNotFoundException>(() => |
||||
|
{ |
||||
|
return sut.HandleAsync(context); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_find_schema_id_by_name() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
SetupSchema(); |
||||
|
|
||||
|
var sut = SetupSchemaCommand(false); |
||||
|
|
||||
|
await sut.HandleAsync(context); |
||||
|
|
||||
|
Assert.Equal(new NamedId<Guid>(schemaId, schemaName), command.SchemaId); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task HandleAsync_should_find_schema_id_by_id() |
||||
|
{ |
||||
|
var context = new CommandContext(command, commandBus); |
||||
|
SetupSchema(); |
||||
|
|
||||
|
var sut = SetupSchemaCommand(true); |
||||
|
|
||||
|
await sut.HandleAsync(context); |
||||
|
|
||||
|
Assert.Equal(new NamedId<Guid>(schemaId, schemaName), command.SchemaId); |
||||
|
} |
||||
|
|
||||
|
private void SetupSchema() |
||||
|
{ |
||||
|
var schemaDef = new Schema(schemaName); |
||||
|
var stringValidatorProperties = new StringFieldProperties |
||||
|
{ |
||||
|
Pattern = "A-Z" |
||||
|
}; |
||||
|
var stringFieldWithValidator = new StringField(1, "validator", Partitioning.Invariant, stringValidatorProperties); |
||||
|
|
||||
|
schemaDef = schemaDef.AddField(stringFieldWithValidator); |
||||
|
|
||||
|
schema = new SchemaState |
||||
|
{ |
||||
|
Name = schemaName, |
||||
|
Id = schemaId, |
||||
|
AppId = new NamedId<Guid>(appId, appName), |
||||
|
SchemaDef = schemaDef |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private EnrichWithSchemaIdCommandMiddleware SetupSchemaCommand(bool byId) |
||||
|
{ |
||||
|
command.AppId = new NamedId<Guid>(appId, appName); |
||||
|
|
||||
|
if (byId) |
||||
|
{ |
||||
|
routeData.Values.Add("name", schemaId.ToString()); |
||||
|
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false)).Returns(schema); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
routeData.Values.Add("name", "schema"); |
||||
|
A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaName)).Returns(schema); |
||||
|
} |
||||
|
|
||||
|
var actionContext = new ActionContext(httpContextMock.Object, routeData, actionDescriptor.Object); |
||||
|
actionContextAccessor.Setup(x => x.ActionContext).Returns(actionContext); |
||||
|
return new EnrichWithSchemaIdCommandMiddleware(appProvider, actionContextAccessor.Object); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,120 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using FakeItEasy; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using NJsonSchema; |
||||
|
using NSwag; |
||||
|
using NSwag.AspNetCore; |
||||
|
using NSwag.SwaggerGeneration; |
||||
|
using Squidex.Config; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Pipeline.Swagger; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Tests.Pipeline.Swagger |
||||
|
{ |
||||
|
public class SwaggerHelperTests |
||||
|
{ |
||||
|
private readonly IHttpContextAccessor contextAccessor = A.Fake<IHttpContextAccessor>(); |
||||
|
private readonly string appName = "app"; |
||||
|
private readonly string host = "kraken"; |
||||
|
private readonly MyUrlsOptions myUrlsOptions = new MyUrlsOptions { BaseUrl = "www.test.com" }; |
||||
|
private readonly SwaggerOperation operation = new SwaggerOperation(); |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_load_docs() |
||||
|
{ |
||||
|
var doc = SwaggerHelper.LoadDocs("security"); |
||||
|
Assert.StartsWith("Squidex", doc); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_throw_exception_when_base_url_is_empty() |
||||
|
{ |
||||
|
var testUrlOptions = new MyUrlsOptions(); |
||||
|
Assert.Throws<ConfigurationException>(() => testUrlOptions.BuildUrl("/api")); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_create_swagger_document() |
||||
|
{ |
||||
|
var swaggerDoc = CreateSwaggerDocument(); |
||||
|
|
||||
|
Assert.NotNull(swaggerDoc.Tags); |
||||
|
Assert.Contains("application/json", swaggerDoc.Consumes); |
||||
|
Assert.Contains("application/json", swaggerDoc.Produces); |
||||
|
Assert.NotNull(swaggerDoc.Info.ExtensionData["x-logo"]); |
||||
|
Assert.Equal($"Squidex API for {appName} App", swaggerDoc.Info.Title); |
||||
|
Assert.Equal("/api", swaggerDoc.BasePath); |
||||
|
Assert.Equal(host, swaggerDoc.Host); |
||||
|
Assert.NotEmpty(swaggerDoc.SecurityDefinitions); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_create_OAuth_schema() |
||||
|
{ |
||||
|
var oauthSchema = SwaggerHelper.CreateOAuthSchema(myUrlsOptions); |
||||
|
|
||||
|
Assert.Equal(myUrlsOptions.BuildUrl($"{Constants.IdentityServerPrefix}/connect/token"), oauthSchema.TokenUrl); |
||||
|
Assert.Equal(SwaggerSecuritySchemeType.OAuth2, oauthSchema.Type); |
||||
|
Assert.Equal(SwaggerOAuth2Flow.Application, oauthSchema.Flow); |
||||
|
Assert.NotEmpty(oauthSchema.Scopes); |
||||
|
Assert.Contains(myUrlsOptions.BuildUrl($"{Constants.IdentityServerPrefix}/connect/token"), |
||||
|
oauthSchema.Description); |
||||
|
Assert.DoesNotContain("<TOKEN_URL>", oauthSchema.Description); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_get_error_dto_schema() |
||||
|
{ |
||||
|
var swaggerDoc = CreateSwaggerDocument(); |
||||
|
|
||||
|
var schemaGenerator = new SwaggerJsonSchemaGenerator(new SwaggerSettings()); |
||||
|
var schemaResolver = new SwaggerSchemaResolver(swaggerDoc, new SwaggerSettings()); |
||||
|
var errorDto = await schemaGenerator.GetErrorDtoSchemaAsync(schemaResolver); |
||||
|
|
||||
|
Assert.NotNull(errorDto); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_query_parameter() |
||||
|
{ |
||||
|
operation.AddQueryParameter("test", JsonObjectType.String, "Test parameter"); |
||||
|
Assert.Contains(operation.Parameters, p => p.Kind == SwaggerParameterKind.Query); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_path_parameter() |
||||
|
{ |
||||
|
operation.AddPathParameter("test", JsonObjectType.String, "Test parameter"); |
||||
|
Assert.Contains(operation.Parameters, p => p.Kind == SwaggerParameterKind.Path); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_body_parameter() |
||||
|
{ |
||||
|
operation.AddBodyParameter("test", null, "Test parameter"); |
||||
|
Assert.Contains(operation.Parameters, p => p.Kind == SwaggerParameterKind.Body); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_add_response_parameter() |
||||
|
{ |
||||
|
operation.AddResponse("200", "Test is ok"); |
||||
|
Assert.Contains(operation.Responses, r => r.Key == "200"); |
||||
|
} |
||||
|
|
||||
|
private SwaggerDocument CreateSwaggerDocument() |
||||
|
{ |
||||
|
A.CallTo(() => contextAccessor.HttpContext.Request.Scheme).Returns("http"); |
||||
|
A.CallTo(() => contextAccessor.HttpContext.Request.Host).Returns(new HostString(host)); |
||||
|
return SwaggerHelper.CreateApiDocument(contextAccessor.HttpContext, myUrlsOptions, appName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.0</TargetFramework> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="FakeItEasy" Version="4.3.0" /> |
||||
|
<PackageReference Include="IdentityServer4" Version="2.1.1" /> |
||||
|
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.1.0" /> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" /> |
||||
|
<PackageReference Include="Moq" Version="4.7.145" /> |
||||
|
<PackageReference Include="NJsonSchema" Version="9.10.19" /> |
||||
|
<PackageReference Include="xunit" Version="2.3.1" /> |
||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Squidex.Domain.Users\Squidex.Domain.Users.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Squidex\Squidex.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Reference Include="CivicPlusIdentityServer.SDK.NetCore"> |
||||
|
<HintPath>..\..\..\identityserver\CivicPlusIdentityServer.SDK.NetCore\bin\Debug\netcoreapp2.0\CivicPlusIdentityServer.SDK.NetCore.dll</HintPath> |
||||
|
</Reference> |
||||
|
<Reference Include="RestSharp"> |
||||
|
<HintPath>..\..\..\restsharp_core\RestSharp\bin\Debug\netstandard2.0\RestSharp.dll</HintPath> |
||||
|
</Reference> |
||||
|
<Reference Include="RestSharp.NetCore"> |
||||
|
<HintPath>..\..\..\..\Desktop\RestSharp.NetCore.dll</HintPath> |
||||
|
</Reference> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
Loading…
Reference in new issue