diff --git a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs index baff5dc43..cef0f0aba 100644 --- a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs +++ b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaAction.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Algolia @@ -28,7 +29,7 @@ namespace Squidex.Extensions.Actions.Algolia public string ApiKey { get; set; } [Required] - [Display(Name = "Index Name", Description = "THe name of the index.")] + [Display(Name = "Index Name", Description = "The name of the index.")] public string IndexName { get; set; } } } diff --git a/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs new file mode 100644 index 000000000..71d0f4c08 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Algolia/AlgoliaPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Algolia +{ + public sealed class AlgoliaPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs index 0ee5de663..2acc7ec7c 100644 --- a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs +++ b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueueAction.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; diff --git a/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs new file mode 100644 index 000000000..e069c08d2 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/AzureQueue/AzureQueuePlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.AzureQueue +{ + public sealed class AzureQueuePlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs b/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs index 4711dec26..a73f1f493 100644 --- a/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs +++ b/extensions/Squidex.Extensions/Actions/Discourse/DiscourseAction.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; diff --git a/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs b/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs new file mode 100644 index 000000000..2d7d9f6d7 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Discourse/DiscoursePlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Discourse +{ + public sealed class DiscoursePlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs index 620f9ef6e..2bf262e82 100644 --- a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs +++ b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchAction.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; diff --git a/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs new file mode 100644 index 000000000..49cf06697 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/ElasticSearch/ElasticSearchPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.ElasticSearch +{ + public sealed class ElasticSearchPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs b/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs index 0de1cb24f..067e5fbce 100644 --- a/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs +++ b/extensions/Squidex.Extensions/Actions/Email/EmailAction.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Email diff --git a/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs b/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs new file mode 100644 index 000000000..34a5c88ce --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Email/EmailPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Email +{ + public sealed class EmailPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs b/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs index 928dab189..d1840782d 100644 --- a/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs +++ b/extensions/Squidex.Extensions/Actions/Fastly/FastlyAction.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Fastly diff --git a/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs b/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs new file mode 100644 index 000000000..8268d912a --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Fastly/FastlyPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Fastly +{ + public sealed class FastlyPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs b/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs index 1363aa430..6bbf1bb30 100644 --- a/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs +++ b/extensions/Squidex.Extensions/Actions/Medium/MediumAction.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Medium diff --git a/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs b/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs new file mode 100644 index 000000000..8a1090672 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Medium/MediumPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Medium +{ + public sealed class MediumPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs index 47c37eafa..4672a8d61 100644 --- a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs +++ b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderAction.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Prerender diff --git a/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs new file mode 100644 index 000000000..89e1a6c9b --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Prerender/PrerenderPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Prerender +{ + public sealed class PrerenderPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs b/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs index 792a0f3fc..4e2863f8a 100644 --- a/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs +++ b/extensions/Squidex.Extensions/Actions/Slack/SlackAction.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; diff --git a/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs b/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs new file mode 100644 index 000000000..1149a5875 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Slack/SlackPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Slack +{ + public sealed class SlackPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/TriggerTypes.cs b/extensions/Squidex.Extensions/Actions/TriggerTypes.cs deleted file mode 100644 index 731a280f9..000000000 --- a/extensions/Squidex.Extensions/Actions/TriggerTypes.cs +++ /dev/null @@ -1,57 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using System; -using System.Collections.Generic; -using Squidex.Domain.Apps.Core.Rules.Triggers; -using Squidex.Infrastructure; - -namespace Squidex.Extensions.Actions -{ - public static class TriggerTypes - { - private const string TriggerSuffix = "Trigger"; - private const string TriggerSuffixV2 = "TriggerV2"; - - public static readonly IReadOnlyDictionary All = new Dictionary - { - [GetTriggerName(typeof(ContentChangedTriggerV2))] = new RuleElement - { - IconImage = "", - IconColor = "#3389ff", - Display = "Content changed", - Description = "For content changes like created, updated, published, unpublished..." - }, - [GetTriggerName(typeof(AssetChangedTriggerV2))] = new RuleElement - { - IconImage = "", - IconColor = "#3389ff", - Display = "Asset changed", - Description = "For asset changes like uploaded, updated (reuploaded), renamed, deleted..." - }, - [GetTriggerName(typeof(SchemaChangedTrigger))] = new RuleElement - { - IconImage = "", - IconColor = "#3389ff", - Display = "Schema changed", - Description = "When a schema definition has been created, updated, published or deleted..." - }, - [GetTriggerName(typeof(UsageTrigger))] = new RuleElement - { - IconImage = "", - IconColor = "#3389ff", - Display = "Usage exceeded", - Description = "When monthly API calls exceed a specified limit for one time a month..." - } - }; - - private static string GetTriggerName(Type type) - { - return type.TypeName(false, TriggerSuffix, TriggerSuffixV2); - } - } -} diff --git a/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs b/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs index a16f98c6f..cc0fa3d17 100644 --- a/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs +++ b/extensions/Squidex.Extensions/Actions/Twitter/TweetAction.cs @@ -6,6 +6,7 @@ // ========================================================================== using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Extensions.Actions.Twitter diff --git a/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs b/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs new file mode 100644 index 000000000..a5b120f4a --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Twitter +{ + public sealed class TwitterPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs b/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs index e2c260b11..0877c37c9 100644 --- a/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs +++ b/extensions/Squidex.Extensions/Actions/Webhook/WebhookAction.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel.DataAnnotations; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; diff --git a/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs b/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs new file mode 100644 index 000000000..c9786cdf0 --- /dev/null +++ b/extensions/Squidex.Extensions/Actions/Webhook/WebhookPlugin.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// 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.Core.HandleRules; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Extensions.Actions.Webhook +{ + public sealed class WebhookPlugin : IPlugin + { + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + RuleActionRegistry.Add(); + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/FormattableAttribute.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/FormattableAttribute.cs new file mode 100644 index 000000000..296dcb840 --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/FormattableAttribute.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; + +namespace Squidex.Domain.Apps.Core.HandleRules +{ + [AttributeUsage(AttributeTargets.Property)] + public sealed class FormattableAttribute : Attribute + { + } +} diff --git a/extensions/Squidex.Extensions/Actions/RuleActionAttribute.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionAttribute.cs similarity index 94% rename from extensions/Squidex.Extensions/Actions/RuleActionAttribute.cs rename to src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionAttribute.cs index c5fa0343f..31c1f2368 100644 --- a/extensions/Squidex.Extensions/Actions/RuleActionAttribute.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionAttribute.cs @@ -7,7 +7,7 @@ using System; -namespace Squidex.Extensions.Actions +namespace Squidex.Domain.Apps.Core.HandleRules { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class RuleActionAttribute : Attribute diff --git a/extensions/Squidex.Extensions/Actions/RuleElement.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionDefinition.cs similarity index 88% rename from extensions/Squidex.Extensions/Actions/RuleElement.cs rename to src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionDefinition.cs index 6d7244c01..595f6d56b 100644 --- a/extensions/Squidex.Extensions/Actions/RuleElement.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionDefinition.cs @@ -7,9 +7,9 @@ using System; -namespace Squidex.Extensions.Actions +namespace Squidex.Domain.Apps.Core.HandleRules { - public sealed class RuleElement + public sealed class RuleActionDefinition { public Type Type { get; set; } diff --git a/extensions/Squidex.Extensions/Actions/RuleActionHandlerAttribute.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandlerAttribute.cs similarity index 92% rename from extensions/Squidex.Extensions/Actions/RuleActionHandlerAttribute.cs rename to src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandlerAttribute.cs index 5da96ebf5..24d29ccea 100644 --- a/extensions/Squidex.Extensions/Actions/RuleActionHandlerAttribute.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionHandlerAttribute.cs @@ -6,10 +6,9 @@ // ========================================================================== using System; -using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Infrastructure; -namespace Squidex.Extensions.Actions +namespace Squidex.Domain.Apps.Core.HandleRules { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class RuleActionHandlerAttribute : Attribute diff --git a/extensions/Squidex.Extensions/Actions/RuleElementRegistry.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistry.cs similarity index 55% rename from extensions/Squidex.Extensions/Actions/RuleElementRegistry.cs rename to src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistry.cs index dac6d42dc..a17a58872 100644 --- a/extensions/Squidex.Extensions/Actions/RuleElementRegistry.cs +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/RuleActionRegistry.cs @@ -12,21 +12,16 @@ using System.Reflection; using Squidex.Domain.Apps.Core.Rules; using Squidex.Infrastructure; -namespace Squidex.Extensions.Actions +namespace Squidex.Domain.Apps.Core.HandleRules { - public static class RuleElementRegistry + public static class RuleActionRegistry { private const string ActionSuffix = "Action"; private const string ActionSuffixV2 = "Action"; private static readonly HashSet ActionHandlerTypes = new HashSet(); - private static readonly Dictionary ActionTypes = new Dictionary(); + private static readonly Dictionary ActionTypes = new Dictionary(); - public static IReadOnlyDictionary Triggers - { - get { return TriggerTypes.All; } - } - - public static IReadOnlyDictionary Actions + public static IReadOnlyDictionary Actions { get { return ActionTypes; } } @@ -36,10 +31,10 @@ namespace Squidex.Extensions.Actions get { return ActionHandlerTypes; } } - static RuleElementRegistry() + static RuleActionRegistry() { var actionTypes = - typeof(RuleElementRegistry).Assembly + typeof(RuleActionRegistry).Assembly .GetTypes() .Where(x => typeof(RuleAction).IsAssignableFrom(x)) .Where(x => x.GetCustomAttribute() != null) @@ -48,25 +43,47 @@ namespace Squidex.Extensions.Actions foreach (var actionType in actionTypes) { - var name = GetActionName(actionType); - - var metadata = actionType.GetCustomAttribute(); - - ActionTypes[name] = - new RuleElement - { - Type = actionType, - Display = metadata.Display, - Description = metadata.Description, - IconColor = metadata.IconColor, - IconImage = metadata.IconImage, - ReadMore = metadata.ReadMore - }; - - ActionHandlerTypes.Add(actionType.GetCustomAttribute().HandlerType); + Add(actionType); } } + public static void Add() where T : RuleAction + { + Add(typeof(T)); + } + + private static void Add(Type actionType) + { + var metadata = actionType.GetCustomAttribute(); + + if (metadata == null) + { + return; + } + + var handlerAttribute = actionType.GetCustomAttribute(); + + if (handlerAttribute == null) + { + return; + } + + var name = GetActionName(actionType); + + ActionTypes[name] = + new RuleActionDefinition + { + Type = actionType, + Display = metadata.Display, + Description = metadata.Description, + IconColor = metadata.IconColor, + IconImage = metadata.IconImage, + ReadMore = metadata.ReadMore + }; + + ActionHandlerTypes.Add(actionType.GetCustomAttribute().HandlerType); + } + public static TypeNameRegistry MapRuleActions(this TypeNameRegistry typeNameRegistry) { foreach (var actionType in ActionTypes.Values) diff --git a/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs b/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs index f36089eeb..82c4e2dc9 100644 --- a/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs +++ b/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs @@ -19,8 +19,8 @@ namespace Squidex.Infrastructure.Assets.ImageSharp { public ImageSharpAssetThumbnailGenerator() { - Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Jpeg); - Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Png); + SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Jpeg); + SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.AddImageFormat(ImageFormats.Png); } public Task CreateThumbnailAsync(Stream source, Stream destination, int? width, int? height, string mode) diff --git a/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs b/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs new file mode 100644 index 000000000..2194f753b --- /dev/null +++ b/src/Squidex.Infrastructure/Configuration/ConfigurationExtensions.cs @@ -0,0 +1,65 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Globalization; +using System.Linq; +using Microsoft.Extensions.Configuration; + +namespace Squidex.Infrastructure.Configuration +{ + public static class ConfigurationExtensions + { + public static T GetOptionalValue(this IConfiguration config, string path, T defaultValue = default) + { + var value = config.GetValue(path, defaultValue); + + return value; + } + + public static int GetOptionalValue(this IConfiguration config, string path, int defaultValue) + { + var value = config.GetValue(path); + + if (string.IsNullOrWhiteSpace(value) || !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) + { + result = defaultValue; + } + + return result; + } + + public static string GetRequiredValue(this IConfiguration config, string path) + { + var value = config.GetValue(path); + + if (string.IsNullOrWhiteSpace(value)) + { + var name = string.Join(" ", path.Split(':').Select(x => x.ToPascalCase())); + + throw new ConfigurationException($"Configure the {name} with '{path}'."); + } + + return value; + } + + public static string ConfigureByOption(this IConfiguration config, string path, Options options) + { + var value = config.GetRequiredValue(path); + + if (options.TryGetValue(value, out var action)) + { + action(); + } + else + { + throw new ConfigurationException($"Unsupported value '{value}' for '{path}', supported: {string.Join(" ", options.Keys)}."); + } + + return value; + } + } +} diff --git a/src/Squidex/Config/Options.cs b/src/Squidex.Infrastructure/Configuration/Options.cs similarity index 84% rename from src/Squidex/Config/Options.cs rename to src/Squidex.Infrastructure/Configuration/Options.cs index 1962bba5e..79a3cdfae 100644 --- a/src/Squidex/Config/Options.cs +++ b/src/Squidex.Infrastructure/Configuration/Options.cs @@ -1,14 +1,14 @@ // ========================================================================== // Squidex Headless CMS // ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) +// Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.Collections.Generic; -namespace Squidex.Config +namespace Squidex.Infrastructure.Configuration { public sealed class Options : Dictionary { diff --git a/src/Squidex/Config/ServiceExtensions.cs b/src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs similarity index 61% rename from src/Squidex/Config/ServiceExtensions.cs rename to src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs index 8d185bf60..5b39ad14b 100644 --- a/src/Squidex/Config/ServiceExtensions.cs +++ b/src/Squidex.Infrastructure/DependencyInjection/DependencyInjectionExtensions.cs @@ -1,20 +1,18 @@ // ========================================================================== // Squidex Headless CMS // ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschränkt) +// Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; -using System.Globalization; using System.Linq; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Squidex.Infrastructure; +using Microsoft.Extensions.DependencyInjection.Extensions; -namespace Squidex.Config +namespace Squidex.Infrastructure.DependencyInjection { - public static class ServiceExtensions + public static class DependencyInjectionExtensions { public sealed class InterfaceRegistrator { @@ -30,6 +28,16 @@ namespace Squidex.Config return this; } + public InterfaceRegistrator AsOptional() + { + if (typeof(TInterface) != typeof(T)) + { + services.TryAddSingleton(typeof(TInterface), c => c.GetRequiredService()); + } + + return this; + } + public InterfaceRegistrator As() { if (typeof(TInterface) != typeof(T)) @@ -89,55 +97,5 @@ namespace Squidex.Config services.AddSingleton(typeof(IInitializable), c => c.GetRequiredService()); } } - - public static T GetOptionalValue(this IConfiguration config, string path, T defaultValue = default) - { - var value = config.GetValue(path, defaultValue); - - return value; - } - - public static int GetOptionalValue(this IConfiguration config, string path, int defaultValue) - { - var value = config.GetValue(path); - var result = defaultValue; - - if (string.IsNullOrWhiteSpace(value) || !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) - { - result = defaultValue; - } - - return result; - } - - public static string GetRequiredValue(this IConfiguration config, string path) - { - var value = config.GetValue(path); - - if (string.IsNullOrWhiteSpace(value)) - { - var name = string.Join(' ', path.Split(':').Select(x => x.ToPascalCase())); - - throw new ConfigurationException($"Configure the {name} with '{path}'."); - } - - return value; - } - - public static string ConfigureByOption(this IConfiguration config, string path, Options options) - { - var value = config.GetRequiredValue(path); - - if (options.TryGetValue(value, out var action)) - { - action(); - } - else - { - throw new ConfigurationException($"Unsupported value '{value}' for '{path}', supported: {string.Join(' ', options.Keys)}."); - } - - return value; - } } } diff --git a/src/Squidex.Infrastructure/Plugins/IPlugin.cs b/src/Squidex.Infrastructure/Plugins/IPlugin.cs new file mode 100644 index 000000000..72ed11047 --- /dev/null +++ b/src/Squidex.Infrastructure/Plugins/IPlugin.cs @@ -0,0 +1,18 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Squidex.Infrastructure.Plugins +{ + public interface IPlugin + { + void ConfigureServices(IServiceCollection services, IConfiguration configuration); + } +} diff --git a/src/Squidex.Infrastructure/Plugins/IWebPlugin.cs b/src/Squidex.Infrastructure/Plugins/IWebPlugin.cs new file mode 100644 index 000000000..2baddf066 --- /dev/null +++ b/src/Squidex.Infrastructure/Plugins/IWebPlugin.cs @@ -0,0 +1,16 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Microsoft.AspNetCore.Builder; + +namespace Squidex.Infrastructure.Plugins +{ + public interface IWebPlugin + { + void Configure(IApplicationBuilder app); + } +} diff --git a/src/Squidex.Infrastructure/Plugins/PluginManager.cs b/src/Squidex.Infrastructure/Plugins/PluginManager.cs new file mode 100644 index 000000000..08e2381ce --- /dev/null +++ b/src/Squidex.Infrastructure/Plugins/PluginManager.cs @@ -0,0 +1,59 @@ +// ========================================================================== +// 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.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Squidex.Infrastructure.Plugins +{ + public sealed class PluginManager + { + private readonly HashSet plugins = new HashSet(); + + public void Add(Assembly assembly) + { + Guard.NotNull(assembly, nameof(assembly)); + + var pluginTypes = + assembly.GetTypes() + .Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract); + + foreach (var pluginType in pluginTypes) + { + var plugin = (IPlugin)Activator.CreateInstance(pluginType); + + plugins.Add(plugin); + } + } + + public void ConfigureServices(IServiceCollection services, IConfiguration configuration) + { + Guard.NotNull(services, nameof(services)); + Guard.NotNull(configuration, nameof(configuration)); + + foreach (var plugin in plugins) + { + plugin.ConfigureServices(services, configuration); + } + } + + public void Configure(IApplicationBuilder app) + { + Guard.NotNull(app, nameof(app)); + + foreach (var plugin in plugins.OfType()) + { + plugin.Configure(app); + } + } + } +} diff --git a/src/Squidex.Infrastructure/Plugins/PluginOptions.cs b/src/Squidex.Infrastructure/Plugins/PluginOptions.cs new file mode 100644 index 000000000..561e0845a --- /dev/null +++ b/src/Squidex.Infrastructure/Plugins/PluginOptions.cs @@ -0,0 +1,14 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Plugins +{ + public sealed class PluginOptions + { + public string[] Plugins { get; set; } + } +} diff --git a/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj b/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj index ea5c0a8b0..f411a7f4c 100644 --- a/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj +++ b/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj @@ -8,6 +8,7 @@ True + diff --git a/src/Squidex.Infrastructure/Translations/DeepLTranslator.cs b/src/Squidex.Infrastructure/Translations/DeepLTranslator.cs index 877e76d7a..09920e6b6 100644 --- a/src/Squidex.Infrastructure/Translations/DeepLTranslator.cs +++ b/src/Squidex.Infrastructure/Translations/DeepLTranslator.cs @@ -10,6 +10,7 @@ using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using Squidex.Infrastructure.Json; namespace Squidex.Infrastructure.Translations @@ -18,7 +19,7 @@ namespace Squidex.Infrastructure.Translations { private const string Url = "https://api.deepl.com/v2/translate"; private readonly HttpClient httpClient = new HttpClient(); - private readonly string authKey; + private readonly DeepLTranslatorOptions deepLOptions; private readonly IJsonSerializer jsonSerializer; private sealed class Response @@ -31,12 +32,12 @@ namespace Squidex.Infrastructure.Translations public string Text { get; set; } } - public DeepLTranslator(string authKey, IJsonSerializer jsonSerializer) + public DeepLTranslator(IOptions deepLOptions, IJsonSerializer jsonSerializer) { - Guard.NotNull(authKey, nameof(authKey)); + Guard.NotNull(deepLOptions, nameof(deepLOptions)); Guard.NotNull(jsonSerializer, nameof(jsonSerializer)); - this.authKey = authKey; + this.deepLOptions = deepLOptions.Value; this.jsonSerializer = jsonSerializer; } @@ -48,9 +49,14 @@ namespace Squidex.Infrastructure.Translations return new Translation(TranslationResult.NotTranslated, sourceText); } + if (string.IsNullOrWhiteSpace(deepLOptions.AuthKey)) + { + return new Translation(TranslationResult.NotImplemented); + } + var parameters = new Dictionary { - ["auth_key"] = authKey, + ["auth_key"] = deepLOptions.AuthKey, ["text"] = sourceText, ["target_lang"] = GetLanguageCode(targetLanguage) }; diff --git a/src/Squidex.Infrastructure/Translations/DeepLTranslatorOptions.cs b/src/Squidex.Infrastructure/Translations/DeepLTranslatorOptions.cs new file mode 100644 index 000000000..d7124e343 --- /dev/null +++ b/src/Squidex.Infrastructure/Translations/DeepLTranslatorOptions.cs @@ -0,0 +1,14 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +namespace Squidex.Infrastructure.Translations +{ + public sealed class DeepLTranslatorOptions + { + public string AuthKey { get; set; } + } +} diff --git a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs index 5059cb21c..07a973ea4 100644 --- a/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs +++ b/src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs @@ -14,8 +14,8 @@ using NSwag.SwaggerGeneration; using NSwag.SwaggerGeneration.Processors; using Squidex.Areas.Api.Controllers.Contents.Generator; using Squidex.Areas.Api.Controllers.Rules.Models; -using Squidex.Config; using Squidex.Infrastructure; +using Squidex.Infrastructure.DependencyInjection; namespace Squidex.Areas.Api.Config.Swagger { diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs index 4efcfb7ad..fe5666dad 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionConverter.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Extensions.Actions; @@ -15,7 +16,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models { public sealed class RuleActionConverter : MyJsonInheritanceConverter { - private static readonly Dictionary Mapping = RuleElementRegistry.Actions.ToDictionary(x => x.Key, x => x.Value.Type); + private static readonly Dictionary Mapping = RuleActionRegistry.Actions.ToDictionary(x => x.Key, x => x.Value.Type); public RuleActionConverter() : base("actionType", Mapping) diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs index a0d23e12b..2ea9995b8 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using NJsonSchema; using NSwag.SwaggerGeneration.Processors; using NSwag.SwaggerGeneration.Processors.Contexts; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Core.Rules; using Squidex.Extensions.Actions; @@ -36,7 +37,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models Type = JsonObjectType.String, IsRequired = true }; - foreach (var derived in RuleElementRegistry.Actions) + foreach (var derived in RuleActionRegistry.Actions) { var derivedSchema = await context.SchemaGenerator.GenerateAsync(derived.Value.Type, context.SchemaResolver); diff --git a/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs b/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs index 998f08a70..752b4e041 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Net.Http.Headers; using NodaTime; using Squidex.Areas.Api.Controllers.Rules.Models; +using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Entities; using Squidex.Domain.Apps.Entities.Rules.Commands; using Squidex.Domain.Apps.Entities.Rules.Repositories; @@ -31,8 +32,7 @@ namespace Squidex.Areas.Api.Controllers.Rules [ApiExplorerSettings(GroupName = nameof(Rules))] public sealed class RulesController : ApiController { - private static readonly string RuleActionsEtag = string.Join(";", RuleElementRegistry.Actions.Select(x => x.Key)).Sha256Base64(); - private static readonly string RuleTriggersEtag = string.Join(";", RuleElementRegistry.Triggers.Select(x => x.Key)).Sha256Base64(); + private static readonly string RuleActionsEtag = string.Join(";", RuleActionRegistry.Actions.Select(x => x.Key)).Sha256Base64(); private readonly IAppProvider appProvider; private readonly IRuleEventRepository ruleEventsRepository; @@ -58,33 +58,13 @@ namespace Squidex.Areas.Api.Controllers.Rules [ApiCosts(0)] public IActionResult GetActions() { - var response = RuleElementRegistry.Actions.ToDictionary(x => x.Key, x => SimpleMapper.Map(x.Value, new RuleElementDto())); + var response = RuleActionRegistry.Actions.ToDictionary(x => x.Key, x => SimpleMapper.Map(x.Value, new RuleElementDto())); Response.Headers[HeaderNames.ETag] = RuleActionsEtag; return Ok(response); } - /// - /// Get the supported rule triggers. - /// - /// - /// 200 => Rule triggers returned. - /// - [HttpGet] - [Route("rules/triggers/")] - [ProducesResponseType(typeof(Dictionary), 200)] - [ApiPermission] - [ApiCosts(0)] - public IActionResult GetTriggers() - { - var response = RuleElementRegistry.Triggers.ToDictionary(x => x.Key, x => SimpleMapper.Map(x.Value, new RuleElementDto())); - - Response.Headers[HeaderNames.ETag] = RuleTriggersEtag; - - return Ok(response); - } - /// /// Get rules. /// diff --git a/src/Squidex/Config/Domain/AssetServices.cs b/src/Squidex/Config/Domain/AssetServices.cs index 8ec712b17..d1edf5d54 100644 --- a/src/Squidex/Config/Domain/AssetServices.cs +++ b/src/Squidex/Config/Domain/AssetServices.cs @@ -12,6 +12,8 @@ using MongoDB.Driver.GridFS; using Squidex.Infrastructure; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.Assets.ImageSharp; +using Squidex.Infrastructure.Configuration; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Log; namespace Squidex.Config.Domain diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 98641c63f..8cd35728e 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -42,6 +42,8 @@ using Squidex.Domain.Apps.Entities.Schemas.Indexes; using Squidex.Domain.Apps.Entities.Tags; using Squidex.Infrastructure.Assets; using Squidex.Infrastructure.Commands; +using Squidex.Infrastructure.Configuration; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Migrations; using Squidex.Pipeline; diff --git a/src/Squidex/Config/Domain/EventPublishersServices.cs b/src/Squidex/Config/Domain/EventPublishersServices.cs index dad6cd6ec..82004c1db 100644 --- a/src/Squidex/Config/Domain/EventPublishersServices.cs +++ b/src/Squidex/Config/Domain/EventPublishersServices.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Squidex.Infrastructure; using Squidex.Infrastructure.CQRS.Events; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; diff --git a/src/Squidex/Config/Domain/EventStoreServices.cs b/src/Squidex/Config/Domain/EventStoreServices.cs index defcbc2c7..03cb235e2 100644 --- a/src/Squidex/Config/Domain/EventStoreServices.cs +++ b/src/Squidex/Config/Domain/EventStoreServices.cs @@ -11,6 +11,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using MongoDB.Driver; using Squidex.Infrastructure; +using Squidex.Infrastructure.Configuration; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.EventSourcing.Grains; diff --git a/src/Squidex/Config/Domain/InfrastructureServices.cs b/src/Squidex/Config/Domain/InfrastructureServices.cs index 33687222d..a623e3650 100644 --- a/src/Squidex/Config/Domain/InfrastructureServices.cs +++ b/src/Squidex/Config/Domain/InfrastructureServices.cs @@ -18,8 +18,8 @@ using Squidex.Domain.Apps.Entities.Apps.Diagnostics; using Squidex.Domain.Users; using Squidex.Infrastructure; using Squidex.Infrastructure.Caching; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Diagnostics; -using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Translations; using Squidex.Infrastructure.UsageTracking; using Squidex.Shared.Users; @@ -32,19 +32,6 @@ namespace Squidex.Config.Domain { public static void AddMyInfrastructureServices(this IServiceCollection services, IConfiguration config) { - var deeplAuthKey = config.GetValue("translations:deeplAuthKey"); - - if (!string.IsNullOrWhiteSpace(deeplAuthKey)) - { - services.AddSingletonAs(c => new DeepLTranslator(deeplAuthKey, c.GetRequiredService())) - .As(); - } - else - { - services.AddSingletonAs() - .As(); - } - services.AddHealthChecks() .AddCheck("GC", tags: new[] { "node" }) .AddCheck("Orleans", tags: new[] { "cluster" }) @@ -59,6 +46,9 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .AsSelf(); + services.AddSingletonAs() + .As(); + services.AddSingletonAs(c => new CachingUsageTracker(c.GetRequiredService(), c.GetRequiredService())) .As(); diff --git a/src/Squidex/Config/Domain/LoggingServices.cs b/src/Squidex/Config/Domain/LoggingServices.cs index 5e18bd491..92885e424 100644 --- a/src/Squidex/Config/Domain/LoggingServices.cs +++ b/src/Squidex/Config/Domain/LoggingServices.cs @@ -9,6 +9,7 @@ using System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Log; using Squidex.Pipeline; diff --git a/src/Squidex/Config/Domain/RuleServices.cs b/src/Squidex/Config/Domain/RuleServices.cs index 02f36ecc3..5bdc3f45d 100644 --- a/src/Squidex/Config/Domain/RuleServices.cs +++ b/src/Squidex/Config/Domain/RuleServices.cs @@ -13,6 +13,7 @@ using Squidex.Domain.Apps.Entities.Rules; using Squidex.Domain.Apps.Entities.Rules.UsageTracking; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Extensions.Actions; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.EventSourcing; namespace Squidex.Config.Domain @@ -45,7 +46,7 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .AsSelf(); - foreach (var actionHandler in RuleElementRegistry.ActionHandlers) + foreach (var actionHandler in RuleActionRegistry.ActionHandlers) { services.AddSingleton(typeof(IRuleActionHandler), actionHandler); } diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index 04646016c..4ef371ba4 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -16,7 +16,6 @@ using Squidex.Domain.Apps.Core.Rules.Json; using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas.Json; using Squidex.Domain.Apps.Events; -using Squidex.Extensions.Actions; using Squidex.Infrastructure; using Squidex.Infrastructure.Json; using Squidex.Infrastructure.Json.Newtonsoft; diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index 15a41a4d7..8d79f0ec5 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -27,6 +27,8 @@ using Squidex.Domain.Users; using Squidex.Domain.Users.MongoDb; using Squidex.Domain.Users.MongoDb.Infrastructure; using Squidex.Infrastructure; +using Squidex.Infrastructure.Configuration; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Infrastructure.Diagnostics; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Json; diff --git a/src/Squidex/Config/Domain/SubscriptionServices.cs b/src/Squidex/Config/Domain/SubscriptionServices.cs index 10437c2b7..f9d6ca1a1 100644 --- a/src/Squidex/Config/Domain/SubscriptionServices.cs +++ b/src/Squidex/Config/Domain/SubscriptionServices.cs @@ -12,6 +12,7 @@ using Squidex.Domain.Apps.Entities.Apps.Services; using Squidex.Domain.Apps.Entities.Apps.Services.Implementations; using Squidex.Domain.Users; using Squidex.Infrastructure; +using Squidex.Infrastructure.DependencyInjection; namespace Squidex.Config.Domain { diff --git a/src/Squidex/Config/Orleans/OrleansServices.cs b/src/Squidex/Config/Orleans/OrleansServices.cs index aed630ded..957a3cda5 100644 --- a/src/Squidex/Config/Orleans/OrleansServices.cs +++ b/src/Squidex/Config/Orleans/OrleansServices.cs @@ -15,6 +15,7 @@ using Orleans.Hosting; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Rules; using Squidex.Domain.Apps.Entities.Rules.UsageTracking; +using Squidex.Infrastructure.Configuration; using Squidex.Infrastructure.EventSourcing.Grains; using Squidex.Infrastructure.Orleans; diff --git a/src/Squidex/Config/Web/WebServices.cs b/src/Squidex/Config/Web/WebServices.cs index 3de6a6f33..19c375aa0 100644 --- a/src/Squidex/Config/Web/WebServices.cs +++ b/src/Squidex/Config/Web/WebServices.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.DependencyInjection; using Squidex.Config.Domain; +using Squidex.Infrastructure.DependencyInjection; using Squidex.Pipeline; using Squidex.Pipeline.Robots; diff --git a/src/Squidex/Pipeline/Plugins/PluginExtensions.cs b/src/Squidex/Pipeline/Plugins/PluginExtensions.cs new file mode 100644 index 000000000..94de2338e --- /dev/null +++ b/src/Squidex/Pipeline/Plugins/PluginExtensions.cs @@ -0,0 +1,76 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Reflection; +using McMaster.NETCore.Plugins; +using Microsoft.AspNetCore.Mvc.ApplicationParts; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Squidex.Infrastructure.Plugins; + +namespace Squidex.Pipeline.Plugins +{ + public static class PluginExtensions + { + private static readonly Type[] SharedTypes = { typeof(IPlugin) }; + + public static void AddPlugins(IMvcBuilder mvcBuilder, IConfiguration configuration) + { + var options = configuration.Get(); + + if (options.Plugins != null) + { + var pluginManager = new PluginManager(); + + foreach (var pluginPath in options.Plugins) + { + PluginLoader plugin = null; + + if (pluginPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) + { + plugin = PluginLoader.CreateFromAssemblyFile(pluginPath, SharedTypes); + } + else + { + plugin = PluginLoader.CreateFromConfigFile(pluginPath, SharedTypes); + } + + if (plugin != null) + { + var pluginAssembly = plugin.LoadDefaultAssembly(); + + AddParts(mvcBuilder, pluginAssembly); + + var relatedAssemblies = pluginAssembly.GetCustomAttributes(); + + foreach (var relatedAssembly in relatedAssemblies) + { + var assembly = plugin.LoadAssembly(relatedAssembly.AssemblyFileName); + + AddParts(mvcBuilder, assembly); + } + + pluginManager.Add(pluginAssembly); + } + } + + mvcBuilder.Services.AddSingleton(pluginManager); + } + } + + private static void AddParts(IMvcBuilder mvcBuilder, Assembly assembly) + { + var partFactory = ApplicationPartFactory.GetApplicationPartFactory(assembly); + + foreach (var part in partFactory.GetApplicationParts(assembly)) + { + mvcBuilder.PartManager.ApplicationParts.Add(part); + } + } + } +} diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj index 93a7fd8f6..0cab6d9a6 100644 --- a/src/Squidex/Squidex.csproj +++ b/src/Squidex/Squidex.csproj @@ -68,6 +68,7 @@ + diff --git a/src/Squidex/WebStartup.cs b/src/Squidex/WebStartup.cs index b68fffec1..61dd0a38d 100644 --- a/src/Squidex/WebStartup.cs +++ b/src/Squidex/WebStartup.cs @@ -29,6 +29,7 @@ using Squidex.Domain.Apps.Entities.Contents; using Squidex.Extensions.Actions.Twitter; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Diagnostics; +using Squidex.Infrastructure.Translations; using Squidex.Pipeline; using Squidex.Pipeline.Robots; @@ -72,6 +73,8 @@ namespace Squidex config.GetSection("contents")); services.Configure( config.GetSection("assets")); + services.Configure( + config.GetSection("translations:deepL")); services.Configure( config.GetSection("mode")); services.Configure(