diff --git a/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/Builder.cs b/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/Builder.cs index 2b1a4a773..f7f5fcd7b 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/Builder.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/GenerateJsonSchema/Builder.cs @@ -13,7 +13,7 @@ namespace Squidex.Domain.Apps.Core.GenerateJsonSchema { public static JsonSchema Object() { - return new JsonSchema { Type = JsonObjectType.Object, AllowAdditionalItems = false }; + return new JsonSchema { Type = JsonObjectType.Object }; } public static JsonSchema Guid() diff --git a/src/Squidex/Areas/Api/Config/OpenApi/ODataExtensions.cs b/src/Squidex/Areas/Api/Config/OpenApi/ODataExtensions.cs new file mode 100644 index 000000000..839a973f4 --- /dev/null +++ b/src/Squidex/Areas/Api/Config/OpenApi/ODataExtensions.cs @@ -0,0 +1,29 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using NJsonSchema; +using NSwag; +using Squidex.Pipeline.OpenApi; + +namespace Squidex.Areas.Api.Config.OpenApi +{ + public static class ODataExtensions + { + public static void AddOData(this OpenApiOperation operation, string entity, bool supportSearch) + { + if (supportSearch) + { + operation.AddQueryParameter("$search", JsonObjectType.String, "Optional OData full text search."); + } + + operation.AddQueryParameter("$top", JsonObjectType.Number, $"Optional number of {entity} to take."); + operation.AddQueryParameter("$skip", JsonObjectType.Number, $"Optional number of {entity} to skip."); + operation.AddQueryParameter("$orderby", JsonObjectType.String, "Optional OData order definition."); + operation.AddQueryParameter("$filter", JsonObjectType.String, "Optional OData filter definition."); + } + } +} diff --git a/src/Squidex/Areas/Api/Config/OpenApi/ODataQueryParamsProcessor.cs b/src/Squidex/Areas/Api/Config/OpenApi/ODataQueryParamsProcessor.cs index 98d17875b..5fdd3fe8e 100644 --- a/src/Squidex/Areas/Api/Config/OpenApi/ODataQueryParamsProcessor.cs +++ b/src/Squidex/Areas/Api/Config/OpenApi/ODataQueryParamsProcessor.cs @@ -32,15 +32,7 @@ namespace Squidex.Areas.Api.Config.OpenApi { var operation = context.OperationDescription.Operation; - if (supportSearch) - { - operation.AddQueryParameter("$search", JsonObjectType.String, "Optional OData full text search."); - } - - operation.AddQueryParameter("$top", JsonObjectType.Number, $"Optional number of {entity} to take."); - operation.AddQueryParameter("$skip", JsonObjectType.Number, $"Optional number of {entity} to skip."); - operation.AddQueryParameter("$orderby", JsonObjectType.String, "Optional OData order definition."); - operation.AddQueryParameter("$filter", JsonObjectType.String, "Optional OData filter definition."); + operation.AddOData(entity, supportSearch); } return true; diff --git a/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs b/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs index c639a21e5..458f81594 100644 --- a/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs +++ b/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs @@ -34,15 +34,23 @@ namespace Squidex.Areas.Api.Config.OpenApi security.TokenUrl = tokenUrl; SetupDescription(security, tokenUrl); + SetupFlow(security); + SetupScropes(security); + return security; + } + + private static void SetupFlow(OpenApiSecurityScheme security) + { security.Flow = OpenApiOAuth2Flow.Application; + } + private static void SetupScropes(OpenApiSecurityScheme security) + { security.Scopes = new Dictionary { [Constants.ApiScope] = "Read and write access to the API" }; - - return security; } private static void SetupDescription(OpenApiSecurityScheme securityScheme, string tokenUrl) diff --git a/src/Squidex/Areas/Api/Config/OpenApi/ThemeProcessor.cs b/src/Squidex/Areas/Api/Config/OpenApi/ThemeProcessor.cs index eda3eb2f3..62cb20c48 100644 --- a/src/Squidex/Areas/Api/Config/OpenApi/ThemeProcessor.cs +++ b/src/Squidex/Areas/Api/Config/OpenApi/ThemeProcessor.cs @@ -26,7 +26,7 @@ namespace Squidex.Areas.Api.Config.OpenApi public void Process(DocumentProcessorContext context) { - context.Document.BasePath = Constants.ApiPrefix; + context.Document.BasePath = $"{Constants.ApiPrefix}/"; context.Document.Info.ExtensionData = new Dictionary { diff --git a/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaOpenApiGenerator.cs b/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaOpenApiGenerator.cs index 7283b68f6..433b27c0b 100644 --- a/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaOpenApiGenerator.cs +++ b/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaOpenApiGenerator.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; using NJsonSchema; using NSwag; +using Squidex.Areas.Api.Config.OpenApi; using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Core.Schemas; @@ -102,14 +103,10 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator operation.Description = SchemaQueryDescription; - operation.AddQueryParameter("$top", JsonObjectType.Number, "Optional number of contents to take (Default: 20)."); - operation.AddQueryParameter("$skip", JsonObjectType.Number, "Optional number of contents to skip."); - operation.AddQueryParameter("$filter", JsonObjectType.String, "Optional OData filter."); - operation.AddQueryParameter("$search", JsonObjectType.String, "Optional OData full text search."); - operation.AddQueryParameter("$orderby", JsonObjectType.String, "Optional OData order definition."); - operation.AddQueryParameter("$orderby", JsonObjectType.String, "Optional OData order definition."); + operation.AddOData("contents", true); - operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema)); + operation.AddResponse("200", $"{schemaName} contents retrieved.", CreateContentsSchema(schemaName, contentSchema)); + operation.AddResponse("400", $"{schemaName} query not valid."); AddSecurity(operation, Permissions.AppContentsRead); }); diff --git a/src/Squidex/Pipeline/OpenApi/NSwagHelper.cs b/src/Squidex/Pipeline/OpenApi/NSwagHelper.cs index d6ce82c84..3aa04f1d3 100644 --- a/src/Squidex/Pipeline/OpenApi/NSwagHelper.cs +++ b/src/Squidex/Pipeline/OpenApi/NSwagHelper.cs @@ -55,7 +55,7 @@ namespace Squidex.Pipeline.OpenApi { Title = $"Squidex API for {appName} App" }, - BasePath = Constants.ApiPrefix + SchemaType = SchemaType.OpenApi3 }; if (!string.IsNullOrWhiteSpace(context.Request.Host.Value)) @@ -68,42 +68,36 @@ namespace Squidex.Pipeline.OpenApi public static void AddQueryParameter(this OpenApiOperation operation, string name, JsonObjectType type, string description = null) { - var parameter = new OpenApiParameter { Type = type, Name = name, Kind = OpenApiParameterKind.Query }; + var schema = new JsonSchema { Type = type }; - if (!string.IsNullOrWhiteSpace(description)) - { - parameter.Description = description; - } - - operation.Parameters.Add(parameter); + operation.AddParameter(name, schema, OpenApiParameterKind.Query, description, false); } public static void AddPathParameter(this OpenApiOperation operation, string name, JsonObjectType type, string description = null) { - var parameter = new OpenApiParameter { Type = type, Name = name, Kind = OpenApiParameterKind.Path }; - - if (!string.IsNullOrWhiteSpace(description)) - { - parameter.Description = description; - } - - parameter.IsRequired = true; - parameter.IsNullableRaw = false; + var schema = new JsonSchema { Type = type }; - operation.Parameters.Add(parameter); + operation.AddParameter(name, schema, OpenApiParameterKind.Path, description, true); } public static void AddBodyParameter(this OpenApiOperation operation, string name, JsonSchema schema, string description) { - var parameter = new OpenApiParameter { Schema = schema, Name = name, Kind = OpenApiParameterKind.Body }; + operation.AddParameter(name, schema, OpenApiParameterKind.Body, description, true); + } + + private static void AddParameter(this OpenApiOperation operation, string name, JsonSchema schema, OpenApiParameterKind kind, string description, bool isRequired) + { + var parameter = new OpenApiParameter { Schema = schema, Name = name, Kind = kind }; if (!string.IsNullOrWhiteSpace(description)) { parameter.Description = description; } - parameter.IsRequired = true; - parameter.IsNullableRaw = false; + if (isRequired) + { + parameter.IsRequired = true; + } operation.Parameters.Add(parameter); }