mirror of https://github.com/Squidex/squidex.git
27 changed files with 800 additions and 533 deletions
@ -1,44 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using NJsonSchema; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.GenerateJsonSchema |
|||
{ |
|||
public static class ContentSchemaBuilder |
|||
{ |
|||
public static JsonSchema CreateContentSchema(Schema schema, JsonSchema dataSchema) |
|||
{ |
|||
Guard.NotNull(schema, nameof(schema)); |
|||
Guard.NotNull(dataSchema, nameof(dataSchema)); |
|||
|
|||
var schemaName = schema.Properties.Label.Or(schema.Name); |
|||
|
|||
var contentSchema = new JsonSchema |
|||
{ |
|||
Properties = |
|||
{ |
|||
["id"] = SchemaBuilder.StringProperty($"The id of the {schemaName} content.", true), |
|||
["data"] = SchemaBuilder.ObjectProperty(dataSchema, $"The data of the {schemaName}.", true), |
|||
["dataDraft"] = SchemaBuilder.ObjectProperty(dataSchema, $"The draft data of the {schemaName}."), |
|||
["version"] = SchemaBuilder.NumberProperty($"The version of the {schemaName}.", true), |
|||
["created"] = SchemaBuilder.DateTimeProperty($"The date and time when the {schemaName} content has been created.", true), |
|||
["createdBy"] = SchemaBuilder.StringProperty($"The user that has created the {schemaName} content.", true), |
|||
["lastModified"] = SchemaBuilder.DateTimeProperty($"The date and time when the {schemaName} content has been modified last.", true), |
|||
["lastModifiedBy"] = SchemaBuilder.StringProperty($"The user that has updated the {schemaName} content last.", true), |
|||
["newStatus"] = SchemaBuilder.StringProperty("The new status of the content."), |
|||
["status"] = SchemaBuilder.StringProperty("The status of the content.", true) |
|||
}, |
|||
Type = JsonObjectType.Object |
|||
}; |
|||
|
|||
return contentSchema; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using NJsonSchema; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.GenerateJsonSchema |
|||
{ |
|||
public static class ContentJsonSchemaBuilder |
|||
{ |
|||
public static JsonSchema BuildSchema(string name, JsonSchema? dataSchema, bool extended = false) |
|||
{ |
|||
var jsonSchema = new JsonSchema |
|||
{ |
|||
Properties = |
|||
{ |
|||
["id"] = SchemaBuilder.StringProperty($"The id of the {name} content.", true), |
|||
["created"] = SchemaBuilder.DateTimeProperty($"The date and time when the {name} content has been created.", true), |
|||
["createdBy"] = SchemaBuilder.StringProperty($"The user that has created the {name} content.", true), |
|||
["lastModified"] = SchemaBuilder.DateTimeProperty($"The date and time when the {name} content has been modified last.", true), |
|||
["lastModifiedBy"] = SchemaBuilder.StringProperty($"The user that has updated the {name} content last.", true), |
|||
["newStatus"] = SchemaBuilder.StringProperty("The new status of the content."), |
|||
["status"] = SchemaBuilder.StringProperty("The status of the content.", true), |
|||
}, |
|||
Type = JsonObjectType.Object |
|||
}; |
|||
|
|||
if (extended) |
|||
{ |
|||
jsonSchema.Properties["newStatusColor"] = SchemaBuilder.StringProperty("The color of the new status.", false); |
|||
jsonSchema.Properties["schema"] = SchemaBuilder.StringProperty("The name of the schema.", true); |
|||
jsonSchema.Properties["SchemaName"] = SchemaBuilder.StringProperty("The display name of the schema.", true); |
|||
jsonSchema.Properties["statusColor"] = SchemaBuilder.StringProperty("The color of the status.", true); |
|||
} |
|||
|
|||
if (dataSchema != null) |
|||
{ |
|||
jsonSchema.Properties["data"] = SchemaBuilder.ObjectProperty(dataSchema, $"The data of the {name}.", true); |
|||
jsonSchema.Properties["dataDraft"] = SchemaBuilder.ObjectProperty(dataSchema, $"The draft data of the {name}."); |
|||
} |
|||
|
|||
return jsonSchema; |
|||
} |
|||
} |
|||
} |
|||
@ -1,29 +0,0 @@ |
|||
// ==========================================================================
|
|||
// 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.AddQuery("$search", JsonObjectType.String, "Optional OData full text search."); |
|||
} |
|||
|
|||
operation.AddQuery("$top", JsonObjectType.Integer, $"Optional number of {entity} to take."); |
|||
operation.AddQuery("$skip", JsonObjectType.Integer, $"Optional number of {entity} to skip."); |
|||
operation.AddQuery("$orderby", JsonObjectType.String, "Optional OData order definition."); |
|||
operation.AddQuery("$filter", JsonObjectType.String, "Optional OData filter definition."); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using NJsonSchema; |
|||
using NSwag; |
|||
|
|||
namespace Squidex.Areas.Api.Config.OpenApi |
|||
{ |
|||
public static class QueryExtensions |
|||
{ |
|||
public static void AddQuery(this OpenApiOperation operation, bool supportSearch) |
|||
{ |
|||
var @string = new JsonSchema |
|||
{ |
|||
Type = JsonObjectType.String |
|||
}; |
|||
|
|||
var number = new JsonSchema |
|||
{ |
|||
Type = JsonObjectType.String |
|||
}; |
|||
|
|||
if (supportSearch) |
|||
{ |
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = @string, |
|||
Name = "$search", |
|||
Description = "Optional OData full text search.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
} |
|||
|
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = number, |
|||
Name = "$top", |
|||
Description = "Optional OData parameter to define the number of items to retrieve.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
|
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = number, |
|||
Name = "$skip", |
|||
Description = "Optional OData parameter to skip items.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
|
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = @string, |
|||
Name = "$orderby", |
|||
Description = "Optional OData order definition to sort the result set.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
|
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = @string, |
|||
Name = "$filter", |
|||
Description = "Optional OData order definition to filter the result set.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
|
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = @string, |
|||
Name = "q", |
|||
Description = "JSON query as well formatted json string. Overrides all other query parameters, except 'ids'.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
|
|||
operation.Parameters.Add(new OpenApiParameter |
|||
{ |
|||
Schema = @string, |
|||
Name = "ids", |
|||
Description = "Comma separated list of content items. Overrides all other query parameters.", |
|||
Kind = OpenApiParameterKind.Query |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Namotion.Reflection; |
|||
using NJsonSchema; |
|||
using NSwag; |
|||
using NSwag.Generation; |
|||
using Squidex.Areas.Api.Controllers.Contents.Models; |
|||
using Squidex.Domain.Apps.Core; |
|||
using Squidex.Domain.Apps.Core.GenerateJsonSchema; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Entities.Apps; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Contents.Generator |
|||
{ |
|||
internal sealed class Builder |
|||
{ |
|||
private readonly PartitionResolver partitionResolver; |
|||
|
|||
public string AppName { get; } |
|||
|
|||
public JsonSchema ChangeStatusSchema { get; } |
|||
|
|||
public OpenApiDocument Document { get; } |
|||
|
|||
internal Builder(IAppEntity app, |
|||
OpenApiDocument document, |
|||
OpenApiSchemaResolver schemaResolver, |
|||
OpenApiSchemaGenerator schemaGenerator) |
|||
{ |
|||
this.partitionResolver = app.PartitionResolver(); |
|||
|
|||
Document = document; |
|||
|
|||
AppName = app.Name; |
|||
|
|||
ChangeStatusSchema = schemaGenerator.GenerateWithReference<JsonSchema>(typeof(ChangeStatusDto).ToContextualType(), schemaResolver); |
|||
} |
|||
|
|||
public OperationsBuilder Shared() |
|||
{ |
|||
var dataSchema = ResolveSchema("DataDto", () => |
|||
{ |
|||
return JsonSchema.CreateAnySchema(); |
|||
}); |
|||
|
|||
var contentSchema = ResolveSchema($"ContentDto", () => |
|||
{ |
|||
return ContentJsonSchemaBuilder.BuildSchema("Shared", dataSchema, true); |
|||
}); |
|||
|
|||
var path = $"/content/{AppName}"; |
|||
|
|||
var builder = new OperationsBuilder |
|||
{ |
|||
ContentSchema = contentSchema, |
|||
DataSchema = dataSchema, |
|||
Path = path, |
|||
Parent = this, |
|||
SchemaDisplayName = "__Shared", |
|||
SchemaName = "__Shared", |
|||
SchemaTypeName = "__Shared", |
|||
}; |
|||
|
|||
var description = "API endpoints for operations across all schemas."; |
|||
|
|||
Document.Tags.Add(new OpenApiTag { Name = "__Shared", Description = description }); |
|||
|
|||
return builder; |
|||
} |
|||
|
|||
public OperationsBuilder Schema(Schema schema, bool flat) |
|||
{ |
|||
var typeName = schema.TypeName(); |
|||
|
|||
var displayName = schema.DisplayName(); |
|||
|
|||
var dataSchema = ResolveSchema($"{typeName}DataDto", () => |
|||
{ |
|||
return schema.BuildJsonSchema(partitionResolver, ResolveSchema); |
|||
}); |
|||
|
|||
var dataFlatSchema = ResolveSchema($"{typeName}FlatDataDto", () => |
|||
{ |
|||
return schema.BuildFlatJsonSchema(ResolveSchema); |
|||
}); |
|||
|
|||
var contentSchema = ResolveSchema($"{typeName}ContentDto", () => |
|||
{ |
|||
var data = flat ? dataFlatSchema : dataSchema; |
|||
|
|||
return ContentJsonSchemaBuilder.BuildSchema(displayName, dataFlatSchema, true); |
|||
}); |
|||
|
|||
var path = $"/content/{AppName}/{schema.Name}"; |
|||
|
|||
var builder = new OperationsBuilder |
|||
{ |
|||
ContentSchema = contentSchema, |
|||
DataSchema = dataSchema, |
|||
Path = path, |
|||
Parent = this, |
|||
SchemaDisplayName = displayName, |
|||
SchemaName = schema.Name, |
|||
SchemaTypeName = typeName |
|||
}; |
|||
|
|||
var description = builder.FormatText("API endpoints for schema content items."); |
|||
|
|||
Document.Tags.Add(new OpenApiTag { Name = displayName, Description = description }); |
|||
|
|||
return builder; |
|||
} |
|||
|
|||
private JsonSchema ResolveSchema(string name, Func<JsonSchema> factory) |
|||
{ |
|||
name = char.ToUpperInvariant(name[0]) + name[1..]; |
|||
|
|||
return new JsonSchema |
|||
{ |
|||
Reference = Document.Definitions.GetOrAdd(name, x => factory()) |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using NJsonSchema; |
|||
using NSwag; |
|||
using Squidex.Areas.Api.Config.OpenApi; |
|||
using Squidex.Shared; |
|||
using Squidex.Web; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Contents.Generator |
|||
{ |
|||
internal sealed class OperationBuilder |
|||
{ |
|||
private readonly OpenApiOperation operation = new OpenApiOperation(); |
|||
private readonly OperationsBuilder operations; |
|||
|
|||
public OperationBuilder(OperationsBuilder operations, OpenApiOperation operation) |
|||
{ |
|||
this.operations = operations; |
|||
this.operation = operation; |
|||
} |
|||
|
|||
public OperationBuilder Operation(string name) |
|||
{ |
|||
operation.OperationId = $"{name}{operations.SchemaTypeName}Content"; |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public OperationBuilder OperationSummary(string summary) |
|||
{ |
|||
if (!string.IsNullOrWhiteSpace(summary)) |
|||
{ |
|||
operation.Summary = operations.FormatText(summary); |
|||
} |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public OperationBuilder Describe(string description) |
|||
{ |
|||
if (!string.IsNullOrWhiteSpace(description)) |
|||
{ |
|||
operation.Description = description; |
|||
} |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public OperationBuilder HasId() |
|||
{ |
|||
HasPath("id", JsonObjectType.String, $"The id of the schema content item."); |
|||
|
|||
Responds(404, "Content item not found."); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
private OperationBuilder AddParameter(string name, JsonSchema schema, OpenApiParameterKind kind, string description) |
|||
{ |
|||
var parameter = new OpenApiParameter { Schema = schema, Name = name, Kind = kind }; |
|||
|
|||
if (!string.IsNullOrWhiteSpace(description)) |
|||
{ |
|||
parameter.Description = operations.FormatText(description); |
|||
} |
|||
|
|||
parameter.IsRequired = kind != OpenApiParameterKind.Query; |
|||
|
|||
operation.Parameters.Add(parameter); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public OperationBuilder HasQueryOptions(bool supportSearch) |
|||
{ |
|||
operation.AddQuery(true); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public OperationBuilder HasQuery(string name, JsonObjectType type, string description) |
|||
{ |
|||
var jsonSchema = new JsonSchema { Type = type }; |
|||
|
|||
return AddParameter(name, jsonSchema, OpenApiParameterKind.Query, description); |
|||
} |
|||
|
|||
public OperationBuilder HasPath(string name, JsonObjectType type, string description, string? format = null) |
|||
{ |
|||
var jsonSchema = new JsonSchema { Type = type, Format = format }; |
|||
|
|||
return AddParameter(name, jsonSchema, OpenApiParameterKind.Path, description); |
|||
} |
|||
|
|||
public OperationBuilder HasBody(string name, JsonSchema jsonSchema, string description) |
|||
{ |
|||
return AddParameter(name, jsonSchema, OpenApiParameterKind.Body, description); |
|||
} |
|||
|
|||
public OperationBuilder Responds(int statusCode, string description, JsonSchema? schema = null) |
|||
{ |
|||
var response = new OpenApiResponse { Description = description, Schema = schema }; |
|||
|
|||
operation.Responses.Add(statusCode.ToString(), response); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public OperationBuilder RequirePermission(string permissionId) |
|||
{ |
|||
operation.Security = new List<OpenApiSecurityRequirement> |
|||
{ |
|||
new OpenApiSecurityRequirement |
|||
{ |
|||
[Constants.SecurityDefinition] = new[] |
|||
{ |
|||
Permissions.ForApp(permissionId, operations.Parent.AppName, operations.SchemaName).Id |
|||
} |
|||
} |
|||
}; |
|||
|
|||
return this; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using NJsonSchema; |
|||
using NSwag; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Contents.Generator |
|||
{ |
|||
internal sealed class OperationsBuilder |
|||
{ |
|||
public Builder Parent { get; init; } |
|||
|
|||
public string Path { get; init; } |
|||
|
|||
public string SchemaName { get; init; } |
|||
|
|||
public string SchemaTypeName { get; init; } |
|||
|
|||
public string SchemaDisplayName { get; init; } |
|||
|
|||
public JsonSchema ContentSchema { get; init; } |
|||
|
|||
public JsonSchema DataSchema { get; init; } |
|||
|
|||
public string FormatText(string text) |
|||
{ |
|||
return text?.Replace("schema ", $"'{SchemaDisplayName}' ", StringComparison.OrdinalIgnoreCase)!; |
|||
} |
|||
|
|||
public OperationBuilder AddOperation(string method, string path) |
|||
{ |
|||
var operation = new OpenApiOperation |
|||
{ |
|||
Tags = new List<string> |
|||
{ |
|||
SchemaDisplayName |
|||
} |
|||
}; |
|||
|
|||
var operations = Parent.Document.Paths.GetOrAddNew($"{Path}{path}"); |
|||
|
|||
operations[method] = operation; |
|||
|
|||
return new OperationBuilder(this, operation); |
|||
} |
|||
} |
|||
} |
|||
@ -1,241 +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.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; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Pipeline.OpenApi; |
|||
using Squidex.Shared; |
|||
using Squidex.Web; |
|||
|
|||
namespace Squidex.Areas.Api.Controllers.Contents.Generator |
|||
{ |
|||
public sealed class SchemaOpenApiGenerator |
|||
{ |
|||
private readonly OpenApiDocument document; |
|||
private readonly JsonSchema contentSchema; |
|||
private readonly JsonSchema dataSchema; |
|||
private readonly string schemaPath; |
|||
private readonly string schemaName; |
|||
private readonly string schemaType; |
|||
private readonly string appPath; |
|||
private readonly JsonSchema statusSchema; |
|||
private readonly string appName; |
|||
|
|||
public SchemaOpenApiGenerator( |
|||
OpenApiDocument document, |
|||
string appName, |
|||
string appPath, |
|||
Schema schema, |
|||
SchemaResolver schemaResolver, |
|||
JsonSchema statusSchema, |
|||
PartitionResolver partitionResolver) |
|||
{ |
|||
this.document = document; |
|||
|
|||
this.appName = appName; |
|||
this.appPath = appPath; |
|||
|
|||
this.statusSchema = statusSchema; |
|||
|
|||
schemaPath = schema.Name; |
|||
schemaName = schema.DisplayName(); |
|||
schemaType = schema.TypeName(); |
|||
|
|||
dataSchema = schemaResolver($"{schemaType}Dto", schema.BuildJsonSchema(partitionResolver, schemaResolver)); |
|||
|
|||
contentSchema = schemaResolver($"{schemaType}ContentDto", ContentSchemaBuilder.CreateContentSchema(schema, dataSchema)); |
|||
} |
|||
|
|||
public void GenerateSchemaOperations() |
|||
{ |
|||
document.Tags.Add( |
|||
new OpenApiTag |
|||
{ |
|||
Name = schemaName, Description = $"API to manage {schemaName} contents." |
|||
}); |
|||
|
|||
var schemaOperations = new[] |
|||
{ |
|||
GenerateSchemaGetsOperation(), |
|||
GenerateSchemaGetOperation(), |
|||
GenerateSchemaCreateOperation(), |
|||
GenerateSchemaUpdateOperation(), |
|||
GenerateSchemaUpdatePatchOperation(), |
|||
GenerateSchemaStatusOperation(), |
|||
GenerateSchemaDeleteOperation() |
|||
}; |
|||
|
|||
foreach (var operation in schemaOperations.SelectMany(x => x.Values).Distinct()) |
|||
{ |
|||
operation.Tags = new List<string> { schemaName }; |
|||
} |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaGetsOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Get, Permissions.AppContentsReadOwn, "/", |
|||
operation => |
|||
{ |
|||
operation.OperationId = $"Query{schemaType}Contents"; |
|||
|
|||
operation.Summary = $"Queries {schemaName} contents."; |
|||
|
|||
operation.Description = NSwagHelper.SchemaQueryDocs; |
|||
|
|||
operation.AddOData("contents", true); |
|||
|
|||
operation.AddResponse("200", $"{schemaName} contents retrieved.", CreateContentsSchema(schemaName, contentSchema)); |
|||
operation.AddResponse("400", $"{schemaName} query not valid."); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaGetOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Get, Permissions.AppContentsReadOwn, "/{id}", operation => |
|||
{ |
|||
operation.OperationId = $"Get{schemaType}Content"; |
|||
|
|||
operation.Summary = $"Get a {schemaName} content."; |
|||
|
|||
operation.AddResponse("200", $"{schemaName} content found.", contentSchema); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaCreateOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Post, Permissions.AppContentsCreate, "/", |
|||
operation => |
|||
{ |
|||
operation.OperationId = $"Create{schemaType}Content"; |
|||
|
|||
operation.Summary = $"Create a {schemaName} content."; |
|||
|
|||
operation.AddBody("data", dataSchema, NSwagHelper.SchemaBodyDocs); |
|||
operation.AddQuery("publish", JsonObjectType.Boolean, "True to automatically publish the content."); |
|||
operation.AddQuery("id", JsonObjectType.String, "The optional custom content id."); |
|||
|
|||
operation.AddResponse("201", $"{schemaName} content created.", contentSchema); |
|||
operation.AddResponse("400", $"{schemaName} content not valid."); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaUpdateOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Put, Permissions.AppContentsUpdateOwn, "/{id}", |
|||
operation => |
|||
{ |
|||
operation.OperationId = $"Update{schemaType}Content"; |
|||
|
|||
operation.Summary = $"Update a {schemaName} content."; |
|||
|
|||
operation.AddBody("data", dataSchema, NSwagHelper.SchemaBodyDocs); |
|||
|
|||
operation.AddResponse("200", $"{schemaName} content updated.", contentSchema); |
|||
operation.AddResponse("400", $"{schemaName} content not valid."); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaUpdatePatchOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Patch, Permissions.AppContentsUpdateOwn, "/{id}", |
|||
operation => |
|||
{ |
|||
operation.OperationId = $"Path{schemaType}Content"; |
|||
|
|||
operation.Summary = $"Patch a {schemaName} content."; |
|||
|
|||
operation.AddBody("data", dataSchema, NSwagHelper.SchemaBodyDocs); |
|||
|
|||
operation.AddResponse("200", $"{schemaName} content patched.", contentSchema); |
|||
operation.AddResponse("400", $"{schemaName} status not valid."); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaStatusOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Put, Permissions.AppContentsUpdateOwn, "/{id}/status", |
|||
operation => |
|||
{ |
|||
operation.OperationId = $"Change{schemaType}ContentStatus"; |
|||
|
|||
operation.Summary = $"Change status of {schemaName} content."; |
|||
|
|||
operation.AddBody("request", statusSchema, "The request to change content status."); |
|||
|
|||
operation.AddResponse("200", $"{schemaName} content status changed.", contentSchema); |
|||
operation.AddResponse("400", $"{schemaName} content not valid."); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem GenerateSchemaDeleteOperation() |
|||
{ |
|||
return Add(OpenApiOperationMethod.Delete, Permissions.AppContentsDeleteOwn, "/{id}", |
|||
operation => |
|||
{ |
|||
operation.OperationId = $"Delete{schemaType}Content"; |
|||
|
|||
operation.Summary = $"Delete a {schemaName} content."; |
|||
|
|||
operation.AddResponse("204", $"{schemaName} content deleted."); |
|||
}); |
|||
} |
|||
|
|||
private OpenApiPathItem Add(string method, string permission, string path, Action<OpenApiOperation> updater) |
|||
{ |
|||
var operations = document.Paths.GetOrAddNew($"{appPath}/{schemaPath}{path}"); |
|||
var operation = new OpenApiOperation |
|||
{ |
|||
Security = new List<OpenApiSecurityRequirement> |
|||
{ |
|||
new OpenApiSecurityRequirement |
|||
{ |
|||
[Constants.SecurityDefinition] = new[] |
|||
{ |
|||
Permissions.ForApp(permission, appName, schemaPath).Id |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
updater(operation); |
|||
|
|||
operations[method] = operation; |
|||
|
|||
if (path.StartsWith("/{id}", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
operation.AddPathParameter("id", JsonObjectType.String, $"The id of the {schemaName} content."); |
|||
|
|||
operation.AddResponse("404", $"App, schema or {schemaName} content not found."); |
|||
} |
|||
|
|||
return operations; |
|||
} |
|||
|
|||
private static JsonSchema CreateContentsSchema(string schemaName, JsonSchema contentSchema) |
|||
{ |
|||
var schema = new JsonSchema |
|||
{ |
|||
Properties = |
|||
{ |
|||
["total"] = SchemaBuilder.NumberProperty($"The total number of {schemaName} contents.", true), |
|||
["items"] = SchemaBuilder.ArrayProperty(contentSchema, $"The {schemaName} contents.", true) |
|||
}, |
|||
Type = JsonObjectType.Object |
|||
}; |
|||
|
|||
return schema; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
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. |
|||
@ -1,11 +0,0 @@ |
|||
The squidex API the OData url convention to query data. |
|||
|
|||
We support 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. |
|||
* **$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 a single field in the database and use this combined field to implement the full text search. |
|||
* **$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. |
|||
|
|||
Read more about it at: https://docs.squidex.io/04-guides/02-api.html |
|||
Loading…
Reference in new issue