mirror of https://github.com/Squidex/squidex.git
committed by
GitHub
24 changed files with 256 additions and 801 deletions
@ -0,0 +1,38 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Templates; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; |
||||
|
|
||||
|
namespace Squidex.Extensions.Samples.Middleware |
||||
|
{ |
||||
|
public class TemplateInstance : ITemplate |
||||
|
{ |
||||
|
public string Name { get; } = "custom2"; |
||||
|
|
||||
|
public Task RunAsync(PublishTemplate publish) |
||||
|
{ |
||||
|
var schema = |
||||
|
SchemaBuilder.Create("Blogs") |
||||
|
.AddString("Title", f => f |
||||
|
.Length(100) |
||||
|
.Required()) |
||||
|
.AddString("Slug", f => f |
||||
|
.Length(100) |
||||
|
.Required() |
||||
|
.Disabled()) |
||||
|
.AddString("Text", f => f |
||||
|
.Length(1000) |
||||
|
.Required() |
||||
|
.AsRichText()) |
||||
|
.Build(); |
||||
|
|
||||
|
return publish(schema); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Domain.Apps.Entities; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
|
||||
|
namespace Squidex.Extensions.Samples.Middleware |
||||
|
{ |
||||
|
public sealed class TemplateMiddleware : ICustomCommandMiddleware |
||||
|
{ |
||||
|
public async Task HandleAsync(CommandContext context, NextDelegate next) |
||||
|
{ |
||||
|
await next(context); |
||||
|
|
||||
|
if (context.Command is CreateApp createApp && context.IsCompleted && createApp.Template == "custom") |
||||
|
{ |
||||
|
var appId = NamedId.Of(createApp.AppId, createApp.Name); |
||||
|
|
||||
|
var publish = new Func<IAppCommand, Task>(command => |
||||
|
{ |
||||
|
command.AppId = appId; |
||||
|
|
||||
|
return context.CommandBus.PublishAsync(command); |
||||
|
}); |
||||
|
|
||||
|
var schema = |
||||
|
SchemaBuilder.Create("Pages") |
||||
|
.AddString("Title", f => f |
||||
|
.Length(100) |
||||
|
.Required()) |
||||
|
.AddString("Slug", f => f |
||||
|
.Length(100) |
||||
|
.Required() |
||||
|
.Disabled()) |
||||
|
.AddString("Text", f => f |
||||
|
.Length(1000) |
||||
|
.Required() |
||||
|
.AsRichText()) |
||||
|
.Build(); |
||||
|
|
||||
|
await publish(schema); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Templates; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
using Squidex.Infrastructure.Plugins; |
||||
|
|
||||
|
namespace Squidex.Extensions.Samples.Middleware |
||||
|
{ |
||||
|
public sealed class TemplatePlugin : IPlugin |
||||
|
{ |
||||
|
public void ConfigureServices(IServiceCollection services, IConfiguration config) |
||||
|
{ |
||||
|
services.AddSingleton<ICustomCommandMiddleware, TemplateMiddleware>(); |
||||
|
|
||||
|
services.AddSingleton<ITemplate, TemplateInstance>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,281 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Commands; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps.Templates |
|
||||
{ |
|
||||
public sealed class CreateIdentityCommandMiddleware : ICommandMiddleware |
|
||||
{ |
|
||||
private const string TemplateName = "Identity"; |
|
||||
|
|
||||
public async Task HandleAsync(CommandContext context, NextDelegate next) |
|
||||
{ |
|
||||
if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp)) |
|
||||
{ |
|
||||
var appId = NamedId.Of(createApp.AppId, createApp.Name); |
|
||||
|
|
||||
var publish = new Func<ICommand, Task>(command => |
|
||||
{ |
|
||||
if (command is IAppCommand appCommand) |
|
||||
{ |
|
||||
appCommand.AppId = appId; |
|
||||
} |
|
||||
|
|
||||
return context.CommandBus.PublishAsync(command); |
|
||||
}); |
|
||||
|
|
||||
await Task.WhenAll( |
|
||||
CreateApiResourcesSchemaAsync(publish), |
|
||||
CreateAuthenticationSchemeSchemaAsync(publish), |
|
||||
CreateClientsSchemaAsync(publish), |
|
||||
CreateIdentityResourcesSchemaAsync(publish), |
|
||||
CreateSettingsSchemaAsync(publish), |
|
||||
CreateUsersSchemaAsync(publish)); |
|
||||
} |
|
||||
|
|
||||
await next(context); |
|
||||
} |
|
||||
|
|
||||
private static bool IsRightTemplate(CreateApp createApp) |
|
||||
{ |
|
||||
return string.Equals(createApp.Template, TemplateName, StringComparison.OrdinalIgnoreCase); |
|
||||
} |
|
||||
|
|
||||
private static async Task<NamedId<DomainId>> CreateAuthenticationSchemeSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Authentication Schemes") |
|
||||
.AddString("Provider", f => f |
|
||||
.AsDropDown("Facebook", "Google", "Microsoft", "Twitter") |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The name and type of the provider.")) |
|
||||
.AddString("Client Id", f => f |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The client id that you must configure at the external provider.")) |
|
||||
.AddString("Client Secret", f => f |
|
||||
.Required() |
|
||||
.Hints("The client secret that you must configure at the external provider.")) |
|
||||
.AddTags("Scopes", f => f |
|
||||
.Hints("Additional scopes you want from the provider.")) |
|
||||
.Build(); |
|
||||
|
|
||||
await publish(schema); |
|
||||
|
|
||||
return NamedId.Of(schema.SchemaId, schema.Name); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateClientsSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Clients") |
|
||||
.AddString("Client Id", f => f |
|
||||
.Required() |
|
||||
.Hints("Unique id of the client.")) |
|
||||
.AddString("Client Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("Client display name (used for logging and consent screen).")) |
|
||||
.AddString("Client Uri", f => f |
|
||||
.Localizable() |
|
||||
.Hints("URI to further information about client (used on consent screen).")) |
|
||||
.AddAssets("Logo", f => f |
|
||||
.MustBeImage() |
|
||||
.Hints("URI to client logo (used on consent screen).")) |
|
||||
.AddTags("Client Secrets", f => f |
|
||||
.Hints("Client secrets - only relevant for flows that require a secret.")) |
|
||||
.AddTags("Allowed Scopes", f => f |
|
||||
.Hints("Specifies the api scopes that the client is allowed to request.")) |
|
||||
.AddTags("Allowed Grant Types", f => f |
|
||||
.Hints("Specifies the allowed grant types (legal combinations of AuthorizationCode, Implicit, Hybrid, ResourceOwner, ClientCredentials).")) |
|
||||
.AddTags("Redirect Uris", f => f |
|
||||
.Hints("Specifies allowed URIs to return tokens or authorization codes to")) |
|
||||
.AddTags("Post Logout Redirect Uris", f => f |
|
||||
.Hints("Specifies allowed URIs to redirect to after logout.")) |
|
||||
.AddTags("Allowed Cors Origins", f => f |
|
||||
.Hints("Gets or sets the allowed CORS origins for JavaScript clients.")) |
|
||||
.AddBoolean("Require Consent", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Specifies whether a consent screen is required.")) |
|
||||
.AddBoolean("Allow Offline Access", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Gets or sets a value indicating whether to allow offline access.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateSettingsSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Settings").Singleton() |
|
||||
.AddString("Site Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The name of your website.")) |
|
||||
.AddAssets("Logo", f => f |
|
||||
.MustBeImage() |
|
||||
.Hints("Logo that is rendered in the header.")) |
|
||||
.AddString("Footer Text", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The optional footer text.")) |
|
||||
.AddString("PrivacyPolicyUrl", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The link to your privacy policies.")) |
|
||||
.AddString("LegalUrl", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The link to your legal information.")) |
|
||||
.AddString("Email Confirmation Text", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The text for the confirmation email.")) |
|
||||
.AddString("Email Confirmation Subject", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The subject for the confirmation email.")) |
|
||||
.AddString("Email Password Reset Text", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The text for the password reset email.")) |
|
||||
.AddString("Email Password Reset Subject", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The subject for the password reset email.")) |
|
||||
.AddString("Terms of Service Url", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The link to your tems of service.")) |
|
||||
.AddString("Bootstrap Url", f => f |
|
||||
.Hints("The link to a custom bootstrap theme.")) |
|
||||
.AddString("Styles Url", f => f |
|
||||
.Hints("The link to a stylesheet.")) |
|
||||
.AddString("SMTP From", f => f |
|
||||
.Hints("The SMTP sender address.")) |
|
||||
.AddString("SMTP Server", f => f |
|
||||
.Hints("The smpt server.")) |
|
||||
.AddString("SMTP Username", f => f |
|
||||
.Hints("The username for your SMTP server.")) |
|
||||
.AddString("SMTP Password", f => f |
|
||||
.Hints("The password for your SMTP server.")) |
|
||||
.AddString("Google Analytics Id", f => f |
|
||||
.Hints("The id to your google analytics account.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static async Task CreateUsersSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Users") |
|
||||
.AddString("Username", f => f |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique username to login.")) |
|
||||
.AddString("Email", f => f |
|
||||
.Pattern(@"^[a-zA-Z0-9.!#$%&’*+\\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$", "Must be an email address.") |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique email to login.")) |
|
||||
.AddString("Phone Number", f => f |
|
||||
.Hints("Phone number of the user.")) |
|
||||
.AddTags("Roles", f => f |
|
||||
.Hints("The roles of the user.")) |
|
||||
.AddJson("Claims", f => f |
|
||||
.Hints("The claims of the user.")) |
|
||||
.AddBoolean("Email Confirmed", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Indicates if the email is confirmed.")) |
|
||||
.AddBoolean("Phone Number Confirmed", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Indicates if the phone number is confirmed.")) |
|
||||
.AddBoolean("LockoutEnabled", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Toggle on to lock out the user.")) |
|
||||
.AddDateTime("Lockout End Date Utc", f => f |
|
||||
.AsDateTime() |
|
||||
.Disabled() |
|
||||
.Hints("Indicates when the lockout ends.")) |
|
||||
.AddTags("Login Keys", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Login information for querying.")) |
|
||||
.AddJson("Logins", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Login information.")) |
|
||||
.AddJson("Tokens", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Login tokens.")) |
|
||||
.AddNumber("Access Failed Count", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The number of failed login attempts.")) |
|
||||
.AddString("Password Hash", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The hashed password.")) |
|
||||
.AddString("Normalized Email", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The normalized email for querying.")) |
|
||||
.AddString("Normalized Username", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The normalized user name for querying.")) |
|
||||
.AddString("Security Stamp", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Internal security stamp")) |
|
||||
.WithScripts(DefaultScripts.GenerateUsername) |
|
||||
.Build(); |
|
||||
|
|
||||
await publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateApiResourcesSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("API Resources") |
|
||||
.AddString("Name", f => f |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique name of the API.")) |
|
||||
.AddString("Display Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The display name of the API.")) |
|
||||
.AddString("Description", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The description name of the API.")) |
|
||||
.AddTags("User Claims", f => f |
|
||||
.Hints("List of accociated user claims that should be included when this resource is requested.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateIdentityResourcesSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Identity Resources") |
|
||||
.AddString("Name", f => f |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique name of the identity information.")) |
|
||||
.AddString("Display Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The display name of the identity information.")) |
|
||||
.AddString("Description", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The description name of the identity information.")) |
|
||||
.AddTags("User Claims", f => f |
|
||||
.Hints("List of accociated user claims that should be included when this resource is requested.")) |
|
||||
.AddBoolean("Required", f => f |
|
||||
.Hints("Specifies whether the user can de-select the scope on the consent screen.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,332 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Templates.Builders; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Commands; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps.Templates |
|
||||
{ |
|
||||
public sealed class CreateIdentityV2CommandMiddleware : ICommandMiddleware |
|
||||
{ |
|
||||
private const string TemplateName = "IdentityV2"; |
|
||||
|
|
||||
public async Task HandleAsync(CommandContext context, NextDelegate next) |
|
||||
{ |
|
||||
if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp)) |
|
||||
{ |
|
||||
var appId = NamedId.Of(createApp.AppId, createApp.Name); |
|
||||
|
|
||||
var publish = new Func<ICommand, Task<CommandContext>>(command => |
|
||||
{ |
|
||||
if (command is IAppCommand appCommand) |
|
||||
{ |
|
||||
appCommand.AppId = appId; |
|
||||
} |
|
||||
|
|
||||
return context.CommandBus.PublishAsync(command); |
|
||||
}); |
|
||||
|
|
||||
var apiScopeId = await CreateApiScopesSchemaAsync(publish); |
|
||||
|
|
||||
await Task.WhenAll( |
|
||||
CreateApiResourcesSchemaAsync(publish, apiScopeId), |
|
||||
CreateAuthenticationSchemeSchemaAsync(publish), |
|
||||
CreateClientsSchemaAsync(publish), |
|
||||
CreateIdentityResourcesSchemaAsync(publish), |
|
||||
CreateSettingsSchemaAsync(publish), |
|
||||
CreateUsersSchemaAsync(publish)); |
|
||||
} |
|
||||
|
|
||||
await next(context); |
|
||||
} |
|
||||
|
|
||||
private static bool IsRightTemplate(CreateApp createApp) |
|
||||
{ |
|
||||
return string.Equals(createApp.Template, TemplateName, StringComparison.OrdinalIgnoreCase); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateAuthenticationSchemeSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Authentication Schemes") |
|
||||
.AddString("Provider", f => f |
|
||||
.AsDropDown("Facebook", "Google", "Microsoft", "Twitter") |
|
||||
.Unique() |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The name and type of the provider.")) |
|
||||
.AddString("Client Id", f => f |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The client id that you must configure at the external provider.")) |
|
||||
.AddString("Client Secret", f => f |
|
||||
.Required() |
|
||||
.Hints("The client secret that you must configure at the external provider.")) |
|
||||
.AddTags("Scopes", f => f |
|
||||
.Hints("Additional scopes you want from the provider.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateClientsSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Clients") |
|
||||
.AddString("Client Id", f => f |
|
||||
.Unique() |
|
||||
.Required() |
|
||||
.Hints("Unique id of the client.")) |
|
||||
.AddString("Client Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("Client display name (used for logging and consent screen).")) |
|
||||
.AddString("Client Uri", f => f |
|
||||
.Localizable() |
|
||||
.Hints("URI to further information about client (used on consent screen).")) |
|
||||
.AddAssets("Logo", f => f |
|
||||
.MustBeImage() |
|
||||
.Hints("URI to client logo (used on consent screen).")) |
|
||||
.AddBoolean("Require Consent", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Specifies whether a consent screen is required.")) |
|
||||
.AddBoolean("Disabled", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Enable or disable the client.")) |
|
||||
.AddBoolean("Allow Offline Access", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Gets or sets a value indicating whether to allow offline access.")) |
|
||||
.AddTags("Allowed Grant Types", f => f |
|
||||
.WithAllowedValues("implicit", "hybrid", "authorization_code", "client_credentials") |
|
||||
.Hints("Specifies the allowed grant types.")) |
|
||||
.AddTags("Client Secrets", f => f |
|
||||
.Hints("Client secrets - only relevant for flows that require a secret.")) |
|
||||
.AddTags("Allowed Scopes", f => f |
|
||||
.Hints("Specifies the api scopes that the client is allowed to request.")) |
|
||||
.AddTags("Redirect Uris", f => f |
|
||||
.Hints("Specifies allowed URIs to return tokens or authorization codes to")) |
|
||||
.AddTags("Post Logout Redirect Uris", f => f |
|
||||
.Hints("Specifies allowed URIs to redirect to after logout.")) |
|
||||
.AddTags("Allowed Cors Origins", f => f |
|
||||
.Hints("Gets or sets the allowed CORS origins for JavaScript clients.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateSettingsSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Settings").Singleton() |
|
||||
.AddString("Site Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The name of your website.")) |
|
||||
.AddAssets("Logo", f => f |
|
||||
.MustBeImage() |
|
||||
.Hints("Logo that is rendered in the header.")) |
|
||||
.AddString("Footer Text", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The optional footer text.")) |
|
||||
.AddString("PrivacyPolicyUrl", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The link to your privacy policies.")) |
|
||||
.AddString("LegalUrl", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The link to your legal information.")) |
|
||||
.AddString("Email Confirmation Text", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The text for the confirmation email.")) |
|
||||
.AddString("Email Confirmation Subject", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The subject for the confirmation email.")) |
|
||||
.AddString("Email Password Reset Text", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The text for the password reset email.")) |
|
||||
.AddString("Email Password Reset Subject", f => f |
|
||||
.AsTextArea() |
|
||||
.Localizable() |
|
||||
.Hints("The subject for the password reset email.")) |
|
||||
.AddString("Terms of Service Url", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The link to your tems of service.")) |
|
||||
.AddString("Bootstrap Url", f => f |
|
||||
.Hints("The link to a custom bootstrap theme.")) |
|
||||
.AddString("Styles Url", f => f |
|
||||
.Hints("The link to a stylesheet.")) |
|
||||
.AddString("SMTP From", f => f |
|
||||
.Hints("The SMTP sender address.")) |
|
||||
.AddString("SMTP Server", f => f |
|
||||
.Hints("The smpt server.")) |
|
||||
.AddString("SMTP Username", f => f |
|
||||
.Hints("The username for your SMTP server.")) |
|
||||
.AddString("SMTP Password", f => f |
|
||||
.Hints("The password for your SMTP server.")) |
|
||||
.AddString("Google Analytics Id", f => f |
|
||||
.Hints("The id to your google analytics account.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static async Task CreateUsersSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Users") |
|
||||
.AddString("Username", f => f |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique username to login.")) |
|
||||
.AddString("Email", f => f |
|
||||
.Pattern(@"^[a-zA-Z0-9.!#$%&’*+\\/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$", "Must be an email address.") |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique email to login.")) |
|
||||
.AddString("Phone Number", f => f |
|
||||
.Hints("Phone number of the user.")) |
|
||||
.AddTags("Roles", f => f |
|
||||
.Hints("The roles of the user.")) |
|
||||
.AddJson("Claims", f => f |
|
||||
.Hints("The claims of the user.")) |
|
||||
.AddBoolean("Email Confirmed", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Indicates if the email is confirmed.")) |
|
||||
.AddBoolean("Phone Number Confirmed", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Indicates if the phone number is confirmed.")) |
|
||||
.AddBoolean("LockoutEnabled", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Toggle on to lock out the user.")) |
|
||||
.AddDateTime("Lockout End Date Utc", f => f |
|
||||
.AsDateTime() |
|
||||
.Disabled() |
|
||||
.Hints("Indicates when the lockout ends.")) |
|
||||
.AddTags("Login Keys", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Login information for querying.")) |
|
||||
.AddJson("Logins", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Login information.")) |
|
||||
.AddJson("Tokens", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Login tokens.")) |
|
||||
.AddNumber("Access Failed Count", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The number of failed login attempts.")) |
|
||||
.AddString("Password Hash", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The hashed password.")) |
|
||||
.AddString("Normalized Email", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The normalized email for querying.")) |
|
||||
.AddString("Normalized Username", f => f |
|
||||
.Disabled() |
|
||||
.Hints("The normalized user name for querying.")) |
|
||||
.AddString("Security Stamp", f => f |
|
||||
.Disabled() |
|
||||
.Hints("Internal security stamp")) |
|
||||
.WithScripts(DefaultScripts.GenerateUsername) |
|
||||
.Build(); |
|
||||
|
|
||||
await publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static async Task<NamedId<DomainId>> CreateApiScopesSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("API Scopes") |
|
||||
.AddString("Name", f => f |
|
||||
.Unique() |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique name of the API scope.")) |
|
||||
.AddString("Display Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The display name of the API scope.")) |
|
||||
.AddString("Description", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The description name of the API scope.")) |
|
||||
.AddBoolean("Disabled", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Enable or disable the scope.")) |
|
||||
.AddBoolean("Emphasize", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Emphasize the API scope for important scopes.")) |
|
||||
.AddTags("User Claims", f => f |
|
||||
.Hints("List of accociated user claims that should be included when this resource is requested.")) |
|
||||
.Build(); |
|
||||
|
|
||||
await publish(schema); |
|
||||
|
|
||||
return NamedId.Of(schema.SchemaId, schema.Name); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateApiResourcesSchemaAsync(Func<ICommand, Task> publish, NamedId<DomainId> scopeId) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("API Resources") |
|
||||
.AddString("Name", f => f |
|
||||
.Unique() |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique name of the API.")) |
|
||||
.AddString("Display Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The display name of the API.")) |
|
||||
.AddString("Description", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The description name of the API.")) |
|
||||
.AddBoolean("Disabled", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Enable or disable the API.")) |
|
||||
.AddReferences("Scopes", f => f |
|
||||
.WithSchemaId(scopeId.Id) |
|
||||
.Hints("The scopes for this API.")) |
|
||||
.AddTags("User Claims", f => f |
|
||||
.Hints("List of accociated user claims that should be included when this resource is requested.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
|
|
||||
private static Task CreateIdentityResourcesSchemaAsync(Func<ICommand, Task> publish) |
|
||||
{ |
|
||||
var schema = |
|
||||
SchemaBuilder.Create("Identity Resources") |
|
||||
.AddString("Name", f => f |
|
||||
.Unique() |
|
||||
.Required() |
|
||||
.ShowInList() |
|
||||
.Hints("The unique name of the identity information.")) |
|
||||
.AddString("Display Name", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The display name of the identity information.")) |
|
||||
.AddString("Description", f => f |
|
||||
.Localizable() |
|
||||
.Hints("The description name of the identity information.")) |
|
||||
.AddBoolean("Required", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Specifies whether the user can de-select the scope on the consent screen.")) |
|
||||
.AddBoolean("Disabled", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Enable or disable the scope.")) |
|
||||
.AddBoolean("Emphasize", f => f |
|
||||
.AsToggle() |
|
||||
.Hints("Emphasize the API scope for important scopes.")) |
|
||||
.AddTags("User Claims", f => f |
|
||||
.Hints("List of accociated user claims that should be included when this resource is requested.")) |
|
||||
.Build(); |
|
||||
|
|
||||
return publish(schema); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Templates |
||||
|
{ |
||||
|
public interface ITemplate |
||||
|
{ |
||||
|
string Name { get; } |
||||
|
|
||||
|
Task RunAsync(PublishTemplate publish); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Entities.Apps.Templates |
||||
|
{ |
||||
|
public delegate Task PublishTemplate(IAppCommand command); |
||||
|
|
||||
|
public sealed class TemplateCommandMiddleware : ICommandMiddleware |
||||
|
{ |
||||
|
private readonly Dictionary<string, ITemplate> templates; |
||||
|
|
||||
|
public TemplateCommandMiddleware(IEnumerable<ITemplate> templates) |
||||
|
{ |
||||
|
Guard.NotNull(templates, nameof(templates)); |
||||
|
|
||||
|
this.templates = templates.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); |
||||
|
} |
||||
|
|
||||
|
public async Task HandleAsync(CommandContext context, NextDelegate next) |
||||
|
{ |
||||
|
if (context.IsCompleted && context.Command is CreateApp createApp && !string.IsNullOrWhiteSpace(createApp.Template)) |
||||
|
{ |
||||
|
if (templates.TryGetValue(createApp.Template, out var template)) |
||||
|
{ |
||||
|
var appId = NamedId.Of(createApp.AppId, createApp.Name); |
||||
|
|
||||
|
var publish = new PublishTemplate(command => |
||||
|
{ |
||||
|
command.AppId = appId; |
||||
|
|
||||
|
return context.CommandBus.PublishAsync(command); |
||||
|
}); |
||||
|
|
||||
|
await template.RunAsync(publish); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await next(context); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue