Browse Source

Fix/json schema (#648)

* #639 Create JSON schemas for all rule events

* Fixes the OpenAPI schema and simplifies the code.

Closes #644
pull/653/head
Sebastian Stehle 5 years ago
committed by GitHub
parent
commit
c06f821134
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      backend/src/Squidex/Areas/Api/Config/OpenApi/CommonProcessor.cs
  2. 49
      backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs
  3. 3
      backend/src/Squidex/Areas/Api/Config/OpenApi/SecurityProcessor.cs
  4. 87
      backend/src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasOpenApiGenerator.cs
  5. 6
      backend/src/Squidex/Docs/schema-body.md
  6. 27
      backend/src/Squidex/Docs/schema-query.md
  7. 15
      backend/src/Squidex/Docs/security.md
  8. 74
      backend/src/Squidex/Pipeline/OpenApi/OpenApiHelper.cs
  9. 132
      backend/src/Squidex/Properties/Resources.Designer.cs
  10. 195
      backend/src/Squidex/Properties/Resources.resx
  11. 21
      backend/src/Squidex/Squidex.csproj

4
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<string, object>
{
["x-logo"] = new { url = logoUrl, backgroundColor }
["x-logo"] = new { url = logoUrl, backgroundColor = logoBackground }
};
context.Document.ExternalDocumentation = documentation;

49
backend/src/Squidex/Areas/Api/Config/OpenApi/OpenApiServices.cs

@ -54,33 +54,52 @@ namespace Squidex.Areas.Api.Config.OpenApi
services.AddSingletonAs<XmlResponseTypesProcessor>()
.As<IOperationProcessor>();
services.AddSingletonAs<JsonSchemaGenerator>()
.AsSelf();
services.AddSingletonAs<OpenApiSchemaGenerator>()
.AsSelf();
services.AddSingleton(c =>
{
var settings = ConfigureSchemaSettings(new JsonSchemaGeneratorSettings
var settings = new JsonSchemaGeneratorSettings
{
FlattenInheritanceHierarchy = true,
SerializerOptions = null,
SerializerSettings = c.GetRequiredService<JsonSerializerSettings>()
});
};
return new JsonSchemaGenerator(settings);
ConfigureSchemaSettings(settings, true);
return settings;
});
services.AddSingleton(c =>
{
var settings = new OpenApiDocumentGeneratorSettings
{
SerializerSettings = c.GetRequiredService<JsonSerializerSettings>()
};
ConfigureSchemaSettings(settings, true);
foreach (var processor in c.GetRequiredService<IEnumerable<IDocumentProcessor>>())
{
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<T>(this T settings) where T : OpenApiDocumentGeneratorSettings
{
settings.Title = "Squidex API";
}
public static T ConfigureSchemaSettings<T>(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<AssetMetadata>()
};
return settings;
settings.FlattenInheritanceHierarchy = true;
}
private static ITypeMapper CreateObjectMap<T>()
@ -110,7 +129,7 @@ namespace Squidex.Areas.Api.Config.OpenApi
schema.AdditionalPropertiesSchema = new JsonSchema
{
Description = "Any JSON type"
Description = "Any"
};
});
}

3
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("<TOKEN_URL>", tokenUrl);
var securityText = Properties.Resources.OpenApiSecurity.Replace("<TOKEN_URL>", tokenUrl);
securityScheme.Description = securityText;
}

87
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<IDocumentProcessor> 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<ISchemaEntity> 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<Type>(),
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<OpenApiSchema>
{
scheme
},
Consumes = new List<string>
{
"application/json"
},
Produces = new List<string>
{
"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;
}
}
}

6
backend/src/Squidex/Docs/schema-body.md

@ -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

27
backend/src/Squidex/Docs/schema-query.md

@ -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.

15
backend/src/Squidex/Docs/security.md

@ -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 '<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>

74
backend/src/Squidex/Pipeline/OpenApi/OpenApiHelper.cs

@ -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<OpenApiSchema>
{
scheme
},
Consumes = new List<string>
{
"application/json"
},
Produces = new List<string>
{
"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;
}
}
}

132
backend/src/Squidex/Properties/Resources.Designer.cs

@ -0,0 +1,132 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Squidex.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string OpenApiContentDescription {
get {
return ResourceManager.GetString("OpenApiContentDescription", resourceCulture);
}
}
/// <summary>
/// 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.
/// </summary>
internal static string OpenApiSchemaBody {
get {
return ResourceManager.GetString("OpenApiSchemaBody", resourceCulture);
}
}
/// <summary>
/// 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]&quot;;.
/// </summary>
internal static string OpenApiSchemaQuery {
get {
return ResourceManager.GetString("OpenApiSchemaQuery", resourceCulture);
}
}
/// <summary>
/// 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 &apos;&lt;TOKEN_URL&gt;&apos;
/// -H &apos;Content-Type: application/x-www-form-urlencoded&apos;
/// -d &apos;grant_type=client_credentials&amp;
/// client_id=[CLIENT_ID]&amp;
/// client_secret=[CLIENT_SECRET]&amp;
/// scope=squidex-api&apos;
///
///You must send this token in [rest of string was truncated]&quot;;.
/// </summary>
internal static string OpenApiSecurity {
get {
return ResourceManager.GetString("OpenApiSecurity", resourceCulture);
}
}
}
}

195
backend/src/Squidex/Properties/Resources.resx

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="OpenApiContentDescription" xml:space="preserve">
<value># 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]</value>
</data>
<data name="OpenApiSchemaBody" xml:space="preserve">
<value>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</value>
</data>
<data name="OpenApiSchemaQuery" xml:space="preserve">
<value>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.</value>
</data>
<data name="OpenApiSecurity" xml:space="preserve">
<value>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 '&lt;TOKEN_URL&gt;'
-H 'Content-Type: application/x-www-form-urlencoded'
-d 'grant_type=client_credentials&amp;
client_id=[CLIENT_ID]&amp;
client_secret=[CLIENT_SECRET]&amp;
scope=squidex-api'
You must send this token in the `Authorization` header when making requests to the API:
Authorization: Bearer &lt;token&gt;</value>
</data>
</root>

21
backend/src/Squidex/Squidex.csproj

@ -93,9 +93,6 @@
<ItemGroup>
<EmbeddedResource Include="Areas\Api\Controllers\Users\Assets\Avatar.png" />
<EmbeddedResource Include="Docs\schema-body.md" />
<EmbeddedResource Include="Docs\schema-query.md" />
<EmbeddedResource Include="Docs\security.md" />
<EmbeddedResource Include="Pipeline\Squid\icon-happy-sm.svg" />
<EmbeddedResource Include="Pipeline\Squid\icon-happy.svg" />
<EmbeddedResource Include="Pipeline\Squid\icon-sad-sm.svg" />
@ -109,9 +106,6 @@
<ItemGroup>
<None Remove="Areas\Api\Controllers\Users\Assets\Avatar.png" />
<None Remove="Docs\schema-body.md" />
<None Remove="Docs\schema-query.md" />
<None Remove="Docs\security.md" />
<None Remove="Pipeline\Squid\icon-happy-sm.svg" />
<None Remove="Pipeline\Squid\icon-happy.svg" />
<None Remove="Pipeline\Squid\icon-sad-sm.svg" />
@ -136,6 +130,21 @@
<EmbeddedResource Include="..\..\i18n\frontend_nl.json" Link="Areas\Frontend\Resources\frontend_nl.json" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<PropertyGroup>
<NoWarn>$(NoWarn);CS1591;1591;1573;1572;NU1605;IDE0060</NoWarn>
</PropertyGroup>

Loading…
Cancel
Save