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