From c06f8211347dfd5c4c4836f74925062d202266e6 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Sun, 7 Feb 2021 12:57:31 +0100 Subject: [PATCH] Fix/json schema (#648) * #639 Create JSON schemas for all rule events * Fixes the OpenAPI schema and simplifies the code. Closes #644 --- .../Api/Config/OpenApi/CommonProcessor.cs | 4 +- .../Api/Config/OpenApi/OpenApiServices.cs | 49 +++-- .../Api/Config/OpenApi/SecurityProcessor.cs | 3 +- .../Generator/SchemasOpenApiGenerator.cs | 87 +++++--- backend/src/Squidex/Docs/schema-body.md | 6 - backend/src/Squidex/Docs/schema-query.md | 27 --- backend/src/Squidex/Docs/security.md | 15 -- .../Squidex/Pipeline/OpenApi/OpenApiHelper.cs | 74 ------- .../Squidex/Properties/Resources.Designer.cs | 132 ++++++++++++ backend/src/Squidex/Properties/Resources.resx | 195 ++++++++++++++++++ backend/src/Squidex/Squidex.csproj | 21 +- 11 files changed, 442 insertions(+), 171 deletions(-) delete mode 100644 backend/src/Squidex/Docs/schema-body.md delete mode 100644 backend/src/Squidex/Docs/schema-query.md delete mode 100644 backend/src/Squidex/Docs/security.md delete mode 100644 backend/src/Squidex/Pipeline/OpenApi/OpenApiHelper.cs create mode 100644 backend/src/Squidex/Properties/Resources.Designer.cs create mode 100644 backend/src/Squidex/Properties/Resources.resx diff --git a/backend/src/Squidex/Areas/Api/Config/OpenApi/CommonProcessor.cs b/backend/src/Squidex/Areas/Api/Config/OpenApi/CommonProcessor.cs index 11ca1ca70..23a53cf83 100644 --- a/backend/src/Squidex/Areas/Api/Config/OpenApi/CommonProcessor.cs +++ b/backend/src/Squidex/Areas/Api/Config/OpenApi/CommonProcessor.cs @@ -17,7 +17,7 @@ namespace Squidex.Areas.Api.Config.OpenApi public sealed class CommonProcessor : IDocumentProcessor { private readonly string version; - private readonly string backgroundColor = "#3f83df"; + private readonly string logoBackground = "#3f83df"; private readonly string logoUrl; private readonly OpenApiExternalDocumentation documentation = new OpenApiExternalDocumentation @@ -42,7 +42,7 @@ namespace Squidex.Areas.Api.Config.OpenApi context.Document.Info.Version = version; context.Document.Info.ExtensionData = new Dictionary { - ["x-logo"] = new { url = logoUrl, backgroundColor } + ["x-logo"] = new { url = logoUrl, backgroundColor = logoBackground } }; context.Document.ExternalDocumentation = documentation; diff --git a/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs b/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs index 2dbe5e813..44a529b96 100644 --- a/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs +++ b/backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs @@ -54,33 +54,52 @@ namespace Squidex.Areas.Api.Config.OpenApi services.AddSingletonAs() .As(); + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs() + .AsSelf(); + services.AddSingleton(c => { - var settings = ConfigureSchemaSettings(new JsonSchemaGeneratorSettings + var settings = new JsonSchemaGeneratorSettings { - FlattenInheritanceHierarchy = true, - SerializerOptions = null, SerializerSettings = c.GetRequiredService() - }); + }; - return new JsonSchemaGenerator(settings); + ConfigureSchemaSettings(settings, true); + + return settings; + }); + + services.AddSingleton(c => + { + var settings = new OpenApiDocumentGeneratorSettings + { + SerializerSettings = c.GetRequiredService() + }; + + ConfigureSchemaSettings(settings, true); + + foreach (var processor in c.GetRequiredService>()) + { + settings.DocumentProcessors.Add(processor); + } + + return settings; }); services.AddOpenApiDocument(settings => { - settings.ConfigureName(); - settings.ConfigureSchemaSettings(); + settings.Title = "Squidex API"; + + ConfigureSchemaSettings(settings); settings.OperationProcessors.Add(new QueryParamsProcessor("/apps/{app}/assets")); }); } - private static void ConfigureName(this T settings) where T : OpenApiDocumentGeneratorSettings - { - settings.Title = "Squidex API"; - } - - public static T ConfigureSchemaSettings(this T settings) where T : JsonSchemaGeneratorSettings + private static void ConfigureSchemaSettings(JsonSchemaGeneratorSettings settings, bool flatten = false) { settings.AllowReferencesWithProperties = true; @@ -99,7 +118,7 @@ namespace Squidex.Areas.Api.Config.OpenApi CreateObjectMap() }; - return settings; + settings.FlattenInheritanceHierarchy = true; } private static ITypeMapper CreateObjectMap() @@ -110,7 +129,7 @@ namespace Squidex.Areas.Api.Config.OpenApi schema.AdditionalPropertiesSchema = new JsonSchema { - Description = "Any JSON type" + Description = "Any" }; }); } diff --git a/backend/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs b/backend/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs index f3c622db4..2e0acd454 100644 --- a/backend/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs +++ b/backend/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs @@ -10,7 +10,6 @@ using System.Linq; using NSwag; using NSwag.Generation.Processors.Security; using Squidex.Hosting; -using Squidex.Pipeline.OpenApi; using Squidex.Web; namespace Squidex.Areas.Api.Config.OpenApi @@ -55,7 +54,7 @@ namespace Squidex.Areas.Api.Config.OpenApi private static void SetupDescription(OpenApiSecurityScheme securityScheme, string tokenUrl) { - var securityText = OpenApiHelper.SecurityDocs.Replace("", tokenUrl); + var securityText = Properties.Resources.OpenApiSecurity.Replace("", tokenUrl); securityScheme.Description = securityText; } diff --git a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs index 8c7c51d4a..7bc15e97e 100644 --- a/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs +++ b/backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs @@ -12,43 +12,40 @@ using Microsoft.AspNetCore.Http; using NJsonSchema; using NSwag; using NSwag.Generation; -using NSwag.Generation.Processors; using NSwag.Generation.Processors.Contexts; -using Squidex.Areas.Api.Config.OpenApi; using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Hosting; using Squidex.Infrastructure.Caching; -using Squidex.Pipeline.OpenApi; using Squidex.Shared; namespace Squidex.Areas.Api.Controllers.Contents.Generator { public sealed class SchemasOpenApiGenerator { - private readonly OpenApiDocumentGeneratorSettings settings = new OpenApiDocumentGeneratorSettings(); + private readonly IUrlGenerator urlGenerator; + private readonly OpenApiDocumentGeneratorSettings schemaSettings; private readonly OpenApiSchemaGenerator schemaGenerator; private readonly IRequestCache requestCache; - public SchemasOpenApiGenerator(IEnumerable documentProcessors, IRequestCache requestCache) + public SchemasOpenApiGenerator( + IUrlGenerator urlGenerator, + OpenApiDocumentGeneratorSettings schemaSettings, + OpenApiSchemaGenerator schemaGenerator, + IRequestCache requestCache) { - settings.ConfigureSchemaSettings(); - - foreach (var processor in documentProcessors) - { - settings.DocumentProcessors.Add(processor); - } - - schemaGenerator = new OpenApiSchemaGenerator(settings); - + this.urlGenerator = urlGenerator; + this.schemaSettings = schemaSettings; + this.schemaGenerator = schemaGenerator; this.requestCache = requestCache; } public OpenApiDocument Generate(HttpContext httpContext, IAppEntity app, IEnumerable schemas, bool flat = false) { - var document = OpenApiHelper.CreateApiDocument(httpContext, app.Name); + var document = CreateApiDocument(httpContext, app); - var schemaResolver = new OpenApiSchemaResolver(document, settings); + var schemaResolver = new OpenApiSchemaResolver(document, schemaSettings); requestCache.AddDependency(app.UniqueId, app.Version); @@ -73,9 +70,9 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator Enumerable.Empty(), schemaResolver, schemaGenerator, - settings); + schemaSettings); - foreach (var processor in settings.DocumentProcessors) + foreach (var processor in schemaSettings.DocumentProcessors) { processor.Process(context); } @@ -104,7 +101,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .RequirePermission(Permissions.AppContentsReadOwn) .Operation("Query") .OperationSummary("Query schema contents items.") - .Describe(OpenApiHelper.SchemaQueryDocs) + .Describe(Properties.Resources.OpenApiSchemaQuery) .HasQueryOptions(true) .Responds(200, "Content items retrieved.", contentsSchema) .Responds(400, "Query not valid."); @@ -138,7 +135,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .OperationSummary("Create a schema content item.") .HasQuery("publish", JsonObjectType.Boolean, "True to automatically publish the content.") .HasQuery("id", JsonObjectType.String, "The optional custom content id.") - .HasBody("data", builder.DataSchema, OpenApiHelper.SchemaBodyDocs) + .HasBody("data", builder.DataSchema, Properties.Resources.OpenApiSchemaBody) .Responds(201, "Content item created", builder.ContentSchema) .Responds(400, "Content data not valid."); @@ -148,7 +145,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .OperationSummary("Upsert a schema content item.") .HasQuery("publish", JsonObjectType.Boolean, "True to automatically publish the content.") .HasId() - .HasBody("data", builder.DataSchema, OpenApiHelper.SchemaBodyDocs) + .HasBody("data", builder.DataSchema, Properties.Resources.OpenApiSchemaBody) .Responds(200, "Content item created or updated.", builder.ContentSchema) .Responds(400, "Content data not valid."); @@ -157,7 +154,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .Operation("Update") .OperationSummary("Update a schema content item.") .HasId() - .HasBody("data", builder.DataSchema, OpenApiHelper.SchemaBodyDocs) + .HasBody("data", builder.DataSchema, Properties.Resources.OpenApiSchemaBody) .Responds(200, "Content item updated.", builder.ContentSchema) .Responds(400, "Content data not valid."); @@ -166,7 +163,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .Operation("Patch") .OperationSummary("Patch a schema content item.") .HasId() - .HasBody("data", builder.DataSchema, OpenApiHelper.SchemaBodyDocs) + .HasBody("data", builder.DataSchema, Properties.Resources.OpenApiSchemaBody) .Responds(200, "Content item updated.", builder.ContentSchema) .Responds(400, "Content data not valid."); @@ -175,7 +172,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator .Operation("Patch") .OperationSummary("Patch a schema content item.") .HasId() - .HasBody("data", builder.DataSchema, OpenApiHelper.SchemaBodyDocs) + .HasBody("data", builder.DataSchema, Properties.Resources.OpenApiSchemaBody) .Responds(200, "Content item updated.", builder.ContentSchema) .Responds(400, "Content data not valid."); @@ -207,5 +204,47 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator Type = JsonObjectType.Object }; } + + private OpenApiDocument CreateApiDocument(HttpContext context, IAppEntity app) + { + var appName = app.Name; + + var scheme = + string.Equals(context.Request.Scheme, "http", StringComparison.OrdinalIgnoreCase) ? + OpenApiSchema.Http : + OpenApiSchema.Https; + + var document = new OpenApiDocument + { + Schemes = new List + { + scheme + }, + Consumes = new List + { + "application/json" + }, + Produces = new List + { + "application/json" + }, + Info = new OpenApiInfo + { + Title = $"Squidex Content API for '{appName}' App", + Description = + Properties.Resources.OpenApiContentDescription + .Replace("[REDOC_LINK_NORMAL]", urlGenerator.BuildUrl($"api/content/{app.Name}/docs")) + .Replace("[REDOC_LINK_SIMPLE]", urlGenerator.BuildUrl($"api/content/{app.Name}/docs/flat")) + }, + SchemaType = SchemaType.OpenApi3 + }; + + if (!string.IsNullOrWhiteSpace(context.Request.Host.Value)) + { + document.Host = context.Request.Host.Value; + } + + return document; + } } } diff --git a/backend/src/Squidex/Docs/schema-body.md b/backend/src/Squidex/Docs/schema-body.md deleted file mode 100644 index b7141345d..000000000 --- a/backend/src/Squidex/Docs/schema-body.md +++ /dev/null @@ -1,6 +0,0 @@ -The data of the content to be created or updated. - -Please note that each field is an object with one entry per language. -If the field is not localizable you must use `iv` (invariant language) as a key. - -Read more about it at: https://docs.squidex.io/04-guides/02-api.html \ No newline at end of file diff --git a/backend/src/Squidex/Docs/schema-query.md b/backend/src/Squidex/Docs/schema-query.md deleted file mode 100644 index 87cc75e27..000000000 --- a/backend/src/Squidex/Docs/schema-query.md +++ /dev/null @@ -1,27 +0,0 @@ -How to make queries? - -Read more about it at: https://docs.squidex.io/04-guides/02-api.html - -The query endpoints support three options: - -### Query with OData - -Squidex supports a subset of the OData (https://www.odata.org/) syntax with with the following query options: - -* **$top**: The $top query option requests the number of items in the queried collection to be included in the result. The default value is 20 and the maximum allowed value is 200. You can change the maximum in the app settings, when you host Squidex yourself. -* **$skip**: The $skip query option requests the number of items in the queried collection that are to be skipped and not included in the result. Use it together with $top to read the all your data page by page. -* **$search**: The $search query option allows clients to request entities matching a free-text search expression. We add the data of all fields for all languages to our full text engine. -* **$filter**: The $filter query option allows clients to filter a collection of resources that are addressed by a request URL. -* **$orderby**: The $orderby query option allows clients to request resources in a particular order. - -### Query with JSON query - -Squidex also supports a query syntax based on JSON. You have to pass in the query object as query parameter: - -* **q**: A json text that represents the same query options as with OData, but is more performant to parse. - -### Query by IDs - -Query your items by passing in one or many IDs with the following query parameter: - -* **ids**: A comma-separated list of ids. If you define this option all other settings are ignored. diff --git a/backend/src/Squidex/Docs/security.md b/backend/src/Squidex/Docs/security.md deleted file mode 100644 index b58a51275..000000000 --- a/backend/src/Squidex/Docs/security.md +++ /dev/null @@ -1,15 +0,0 @@ -Squidex uses oauth2 client authentication. Read more about it at: https://oauth.net/2/ and https://tools.ietf.org/html/rfc6750. - -To retrieve an access token, the client id must make a request to the token url. For example: - - $ curl - -X POST '' - -H 'Content-Type: application/x-www-form-urlencoded' - -d 'grant_type=client_credentials& - client_id=[CLIENT_ID]& - client_secret=[CLIENT_SECRET]& - scope=squidex-api' - -You must send this token in the `Authorization` header when making requests to the API: - - Authorization: Bearer \ No newline at end of file diff --git a/backend/src/Squidex/Pipeline/OpenApi/OpenApiHelper.cs b/backend/src/Squidex/Pipeline/OpenApi/OpenApiHelper.cs deleted file mode 100644 index ddf4ab0c0..000000000 --- a/backend/src/Squidex/Pipeline/OpenApi/OpenApiHelper.cs +++ /dev/null @@ -1,74 +0,0 @@ -// ========================================================================== -// 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.IO; -using Microsoft.AspNetCore.Http; -using NJsonSchema; -using NSwag; - -namespace Squidex.Pipeline.OpenApi -{ - public static class OpenApiHelper - { - public static readonly string SecurityDocs = LoadDocs("security"); - - public static readonly string SchemaBodyDocs = LoadDocs("schema-body"); - - public static readonly string SchemaQueryDocs = LoadDocs("schema-query"); - - private static string LoadDocs(string name) - { - var assembly = typeof(OpenApiHelper).Assembly; - - using (var resourceStream = assembly.GetManifestResourceStream($"Squidex.Docs.{name}.md")) - { - using (var streamReader = new StreamReader(resourceStream!)) - { - return streamReader.ReadToEnd(); - } - } - } - - public static OpenApiDocument CreateApiDocument(HttpContext context, string appName) - { - var scheme = - string.Equals(context.Request.Scheme, "http", StringComparison.OrdinalIgnoreCase) ? - OpenApiSchema.Http : - OpenApiSchema.Https; - - var document = new OpenApiDocument - { - Schemes = new List - { - scheme - }, - Consumes = new List - { - "application/json" - }, - Produces = new List - { - "application/json" - }, - Info = new OpenApiInfo - { - Title = $"Squidex API for {appName} App" - }, - SchemaType = SchemaType.OpenApi3 - }; - - if (!string.IsNullOrWhiteSpace(context.Request.Host.Value)) - { - document.Host = context.Request.Host.Value; - } - - return document; - } - } -} diff --git a/backend/src/Squidex/Properties/Resources.Designer.cs b/backend/src/Squidex/Properties/Resources.Designer.cs new file mode 100644 index 000000000..68bfe9004 --- /dev/null +++ b/backend/src/Squidex/Properties/Resources.Designer.cs @@ -0,0 +1,132 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Squidex.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Squidex.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to # Introduction + /// + ///The API provides two specifications. The Content API usually returns one object per schema field where the keys are the languages (or `iv` for non-localized) fields and the values are the actual field values. + /// + ///You can use the `X-Flatten` header to return a flat structure when you query content items. This is more performant and easier for code generation. Unfortunantely it cannot be modelled with OpenAPI. Therefore we provide two different documents for your API. + /// + ///Read more about this [rest of string was truncated]";. + /// + internal static string OpenApiContentDescription { + get { + return ResourceManager.GetString("OpenApiContentDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The data of the content to be created or updated. + /// + ///Please note that each field is an object with one entry per language. + ///If the field is not localizable you must use `iv` (invariant language) as a key. + /// + ///Read more about it at: https://docs.squidex.io/04-guides/02-api.html. + /// + internal static string OpenApiSchemaBody { + get { + return ResourceManager.GetString("OpenApiSchemaBody", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to How to make queries? + /// + ///Read more about it at: https://docs.squidex.io/04-guides/02-api.html + /// + ///The query endpoints support three options: + /// + ///### Query with OData + /// + ///Squidex supports a subset of the OData (https://www.odata.org/) syntax with with the following query options: + /// + ///* **$top**: The $top query option requests the number of items in the queried collection to be included in the result. The default value is 20 and the maximum allowed value is 200. You can change the maximum in the app settings, when [rest of string was truncated]";. + /// + internal static string OpenApiSchemaQuery { + get { + return ResourceManager.GetString("OpenApiSchemaQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Squidex uses oauth2 client authentication. Read more about it at: https://oauth.net/2/ and https://tools.ietf.org/html/rfc6750. + /// + ///To retrieve an access token, the client id must make a request to the token url. For example: + /// + /// $ curl + /// -X POST '<TOKEN_URL>' + /// -H 'Content-Type: application/x-www-form-urlencoded' + /// -d 'grant_type=client_credentials& + /// client_id=[CLIENT_ID]& + /// client_secret=[CLIENT_SECRET]& + /// scope=squidex-api' + /// + ///You must send this token in [rest of string was truncated]";. + /// + internal static string OpenApiSecurity { + get { + return ResourceManager.GetString("OpenApiSecurity", resourceCulture); + } + } + } +} diff --git a/backend/src/Squidex/Properties/Resources.resx b/backend/src/Squidex/Properties/Resources.resx new file mode 100644 index 000000000..f114852a4 --- /dev/null +++ b/backend/src/Squidex/Properties/Resources.resx @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + # Introduction + +The API provides two specifications. The Content API usually returns one object per schema field where the keys are the languages (or `iv` for non-localized) fields and the values are the actual field values. + +You can use the `X-Flatten` header to return a flat structure when you query content items. This is more performant and easier for code generation. Unfortunantely it cannot be modelled with OpenAPI. Therefore we provide two different documents for your API. + +Read more about this here: https://docs.squidex.io/02-documentation/concepts/localization#how-to-use-the-api + +## Normal Content API + +All content fields are objects in the response. + +Go to: [REDOC_LINK_NORMAL] + +## Flat Content API + +All content fields are single values. + +Go to: [REDOC_LINK_SIMPLE] + + + The data of the content to be created or updated. + +Please note that each field is an object with one entry per language. +If the field is not localizable you must use `iv` (invariant language) as a key. + +Read more about it at: https://docs.squidex.io/04-guides/02-api.html + + + How to make queries? + +Read more about it at: https://docs.squidex.io/04-guides/02-api.html + +The query endpoints support three options: + +### Query with OData + +Squidex supports a subset of the OData (https://www.odata.org/) syntax with with the following query options: + +* **$top**: The $top query option requests the number of items in the queried collection to be included in the result. The default value is 20 and the maximum allowed value is 200. You can change the maximum in the app settings, when you host Squidex yourself. +* **$skip**: The $skip query option requests the number of items in the queried collection that are to be skipped and not included in the result. Use it together with $top to read the all your data page by page. +* **$search**: The $search query option allows clients to request entities matching a free-text search expression. We add the data of all fields for all languages to our full text engine. +* **$filter**: The $filter query option allows clients to filter a collection of resources that are addressed by a request URL. +* **$orderby**: The $orderby query option allows clients to request resources in a particular order. + +### Query with JSON query + +Squidex also supports a query syntax based on JSON. You have to pass in the query object as query parameter: + +* **q**: A json text that represents the same query options as with OData, but is more performant to parse. + +### Query by IDs + +Query your items by passing in one or many IDs with the following query parameter: + +* **ids**: A comma-separated list of ids. If you define this option all other settings are ignored. + + + Squidex uses oauth2 client authentication. Read more about it at: https://oauth.net/2/ and https://tools.ietf.org/html/rfc6750. + +To retrieve an access token, the client id must make a request to the token url. For example: + + $ curl + -X POST '<TOKEN_URL>' + -H 'Content-Type: application/x-www-form-urlencoded' + -d 'grant_type=client_credentials& + client_id=[CLIENT_ID]& + client_secret=[CLIENT_SECRET]& + scope=squidex-api' + +You must send this token in the `Authorization` header when making requests to the API: + + Authorization: Bearer <token> + + \ No newline at end of file diff --git a/backend/src/Squidex/Squidex.csproj b/backend/src/Squidex/Squidex.csproj index de4ba5c2e..911a3a009 100644 --- a/backend/src/Squidex/Squidex.csproj +++ b/backend/src/Squidex/Squidex.csproj @@ -93,9 +93,6 @@ - - - @@ -109,9 +106,6 @@ - - - @@ -136,6 +130,21 @@ + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + $(NoWarn);CS1591;1591;1573;1572;NU1605;IDE0060