diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs index 91116db56..d5aa71dd8 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.EntityFramework.Core/EntityFrameworkWebhookStartupBase.cs @@ -17,8 +17,8 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.Core { var services = elsa.Services; var section = configuration.GetSection($"Elsa:Features:Webhooks:Persistence:EntityFrameworkCore:{ProviderName}"); - var connectionStringName = section.GetValue("Options:ConnectionStringName"); - var connectionString = section.GetValue("Options:ConnectionString"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs index 93a318ac6..98a249f44 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.MongoDb/Startup.cs @@ -15,8 +15,8 @@ namespace Elsa.Webhooks.Persistence.MongoDb { var services = elsa.Services; var section = configuration.GetSection($"Elsa:Features:Webhooks:Persistence:MongoDb"); - var connectionStringName = section.GetValue("Options:ConnectionStringName"); - var connectionString = section.GetValue("Options:ConnectionString"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { diff --git a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs index cd396dea7..b605ee7bb 100644 --- a/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs +++ b/src/activities/webhooks/Elsa.Webhooks.Persistence.YesSql/Startups.cs @@ -50,8 +50,8 @@ namespace Elsa.Webhooks.Persistence.YesSql { var services = elsa.Services; var section = configuration.GetSection($"Elsa:Features:Webhooks:Persistence:YesSql:{ProviderName}"); - var connectionStringName = section.GetValue("Options:ConnectionStringName"); - var connectionString = section.GetValue("Options:ConnectionString"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { diff --git a/src/core/Elsa.Core/ElsaOptions.cs b/src/core/Elsa.Core/ElsaOptions.cs index c80107e2e..e0bd103ac 100644 --- a/src/core/Elsa.Core/ElsaOptions.cs +++ b/src/core/Elsa.Core/ElsaOptions.cs @@ -77,7 +77,6 @@ namespace Elsa public Type DefaultWorkflowStorageProviderType { get; set; } public WorkflowChannelOptions WorkflowChannelOptions { get; set; } = new(); - public FeatureOptions FeatureOptions { get; set; } = new(); internal Func StorageFactory { get; set; } internal Func WorkflowDefinitionStoreFactory { get; set; } diff --git a/src/core/Elsa.Core/ElsaOptionsBuilder.cs b/src/core/Elsa.Core/ElsaOptionsBuilder.cs index 8ee06078a..68ac903fb 100644 --- a/src/core/Elsa.Core/ElsaOptionsBuilder.cs +++ b/src/core/Elsa.Core/ElsaOptionsBuilder.cs @@ -66,38 +66,6 @@ namespace Elsa return this; } - public ElsaOptionsBuilder ConfigureFeatures(IConfiguration configuration) - { - var elsaFeaturesSection = "Elsa:Features"; - - ElsaOptions.FeatureOptions.Features = new List(); - var features = configuration.GetSection(elsaFeaturesSection).AsEnumerable(); - - foreach (var feature in features) - { - if (!configuration.GetSection($"{feature.Key}:Enabled").Exists()) continue; - - var enabled = configuration.GetValue($"{feature.Key}:Enabled"); - if (!enabled) continue; - - var opts = new Dictionary(); - var config = configuration.GetSection($"{feature.Key}:Options"); - config.Bind(opts); - - var name = feature.Key.Replace($"{elsaFeaturesSection}:", string.Empty); - - ElsaOptions.FeatureOptions.Features.Add( - new FeatureOption - { - Name = name, - Enabled = enabled, - Options = opts - }); - } - - return this; - } - public ElsaOptionsBuilder AddActivity() where T : IActivity => AddActivity(typeof(T)); public ElsaOptionsBuilder AddActivity(Type activityType) diff --git a/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs b/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs index ec1f3dda1..227fd650f 100644 --- a/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs +++ b/src/core/Elsa.Core/Extensions/ElsaOptionBuilderExtensions.cs @@ -15,17 +15,18 @@ namespace Elsa public static ElsaOptionsBuilder AddFeatures(this ElsaOptionsBuilder builder, IEnumerable assemblies, IConfiguration configuration) { - if (builder.ElsaOptions.FeatureOptions.Features == null!) // Null when configuration binding finds an empty array. + ParseFeatures(configuration); + + if (EnabledFeatures == null!) // Null when configuration binding finds an empty array. return builder; - var enabledFeatures = builder.ElsaOptions.FeatureOptions.Features.ToHashSet(); + var enabledFeatures = EnabledFeatures.ToHashSet(); var startupTypesQuery = from assembly in assemblies from type in assembly.GetExportedTypes() where type.IsClass && !type.IsAbstract && typeof(IStartup).IsAssignableFrom(type) let featureAttribute = type.GetCustomAttribute() - let enabledFeature = enabledFeatures.FirstOrDefault(x => x.Name == featureAttribute.FeatureName) - where featureAttribute != null && enabledFeature != null + where featureAttribute != null && enabledFeatures.Contains(featureAttribute.FeatureName) select type; var startupTypes = startupTypesQuery.ToList(); @@ -39,7 +40,38 @@ namespace Elsa return builder; } - + + private static void ParseFeatures(IConfiguration configuration) + { + var elsaFeaturesSection = "Elsa:Features"; + + EnabledFeatures = new List(); + var features = configuration.GetSection(elsaFeaturesSection).AsEnumerable(); + + foreach (var feature in features) + { + var explEnabled = false; + var implEnabled = false; + + if (configuration.GetSection($"{feature.Key}:Enabled").Exists()) + { + bool.TryParse(configuration.GetValue($"{feature.Key}:Enabled"), out explEnabled); + } + else if (!feature.Key.EndsWith(":Enabled")) + { + bool.TryParse(configuration.GetValue($"{feature.Key}"), out implEnabled); + } + + if (!explEnabled && !implEnabled) continue; + + var featureName = feature.Key.Replace($"{elsaFeaturesSection}:", string.Empty); + + EnabledFeatures.Add(featureName); + } + } + private static IEnumerable GetAssemblies(IEnumerable assemblyMarkerTypes) => assemblyMarkerTypes.Select(x => x.Assembly).Distinct(); + + private static ICollection? EnabledFeatures { get; set; } } } \ No newline at end of file diff --git a/src/core/Elsa.Core/FeatureOptions.cs b/src/core/Elsa.Core/FeatureOptions.cs deleted file mode 100644 index fa3ff1213..000000000 --- a/src/core/Elsa.Core/FeatureOptions.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; -using Elsa.Models; - -namespace Elsa -{ - public class FeatureOptions - { - public ICollection? Features { get; set; } - } -} diff --git a/src/core/Elsa.Core/Models/FeatureOption.cs b/src/core/Elsa.Core/Models/FeatureOption.cs deleted file mode 100644 index 976e1cfb0..000000000 --- a/src/core/Elsa.Core/Models/FeatureOption.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Elsa.Models -{ - public class FeatureOption - { - public string Name { get; set; } = default!; - public bool Enabled { get; set; } = default!; - public Dictionary? Options { get; set; } - } -} diff --git a/src/persistence/Elsa.Persistence.EntityFramework/Elsa.Persistence.EntityFramework.Core/EntityFrameworkCoreStartupBase.cs b/src/persistence/Elsa.Persistence.EntityFramework/Elsa.Persistence.EntityFramework.Core/EntityFrameworkCoreStartupBase.cs index d69244c95..6cf381516 100644 --- a/src/persistence/Elsa.Persistence.EntityFramework/Elsa.Persistence.EntityFramework.Core/EntityFrameworkCoreStartupBase.cs +++ b/src/persistence/Elsa.Persistence.EntityFramework/Elsa.Persistence.EntityFramework.Core/EntityFrameworkCoreStartupBase.cs @@ -13,8 +13,8 @@ namespace Elsa.Persistence.EntityFramework.Core public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) { var section = configuration.GetSection($"Elsa:Features:Persistence:EntityFrameworkCore:{ProviderName}"); - var connectionStringName = section.GetValue("Options:ConnectionStringName"); - var connectionString = section.GetValue("Options:ConnectionString"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { diff --git a/src/persistence/Elsa.Persistence.MongoDb/Startup.cs b/src/persistence/Elsa.Persistence.MongoDb/Startup.cs index a14faa3b1..38eaf73ca 100644 --- a/src/persistence/Elsa.Persistence.MongoDb/Startup.cs +++ b/src/persistence/Elsa.Persistence.MongoDb/Startup.cs @@ -10,8 +10,8 @@ namespace Elsa.Persistence.MongoDb public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) { var section = configuration.GetSection($"Elsa:Features:Persistence:MongoDb"); - var connectionStringName = section.GetValue("Options:ConnectionStringName"); - var connectionString = section.GetValue("Options:ConnectionString"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { diff --git a/src/persistence/Elsa.Persistence.YesSql/Startups.cs b/src/persistence/Elsa.Persistence.YesSql/Startups.cs index 58e7763e2..ffcce94d6 100644 --- a/src/persistence/Elsa.Persistence.YesSql/Startups.cs +++ b/src/persistence/Elsa.Persistence.YesSql/Startups.cs @@ -45,8 +45,8 @@ namespace Elsa.Persistence.YesSql public override void ConfigureElsa(ElsaOptionsBuilder elsa, IConfiguration configuration) { var section = configuration.GetSection($"Elsa:Features:Persistence:YesSql:{ProviderName}"); - var connectionStringName = section.GetValue("Options:ConnectionStringName"); - var connectionString = section.GetValue("Options:ConnectionString"); + var connectionStringName = section.GetValue("ConnectionStringName"); + var connectionString = section.GetValue("ConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { diff --git a/src/samples/dashboard/aspnetcore/ElsaDashboard.Samples.AspNetCore.Monolith/Startup.cs b/src/samples/dashboard/aspnetcore/ElsaDashboard.Samples.AspNetCore.Monolith/Startup.cs index 2b76a1b07..1dfd52ca0 100644 --- a/src/samples/dashboard/aspnetcore/ElsaDashboard.Samples.AspNetCore.Monolith/Startup.cs +++ b/src/samples/dashboard/aspnetcore/ElsaDashboard.Samples.AspNetCore.Monolith/Startup.cs @@ -36,7 +36,6 @@ namespace ElsaDashboard.Samples.AspNetCore.Monolith .AddQuartzTemporalActivities() .AddJavaScriptActivities() .AddActivitiesFrom() - .ConfigureFeatures(Configuration) .AddFeatures(new[] { typeof(Startup) }, Configuration) ); diff --git a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs index 638ae70dc..ddfbed3f1 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Startup.cs +++ b/src/samples/server/Elsa.Samples.Server.Host/Startup.cs @@ -66,7 +66,6 @@ namespace Elsa.Samples.Server.Host .AddElsa(elsa => elsa .AddActivitiesFrom() .AddWorkflowsFrom() - .ConfigureFeatures(Configuration) .AddFeatures(startups, Configuration) .ConfigureWorkflowChannels(options => elsaSection.GetSection("WorkflowChannels").Bind(options)) ); diff --git a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json index 6a5d011c3..0ee36a572 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/appsettings.json +++ b/src/samples/server/Elsa.Samples.Server.Host/appsettings.json @@ -21,45 +21,21 @@ "Features": { "Persistence:EntityFrameworkCore:Sqlite": { "Enabled": "true", - "Options": { - "ConnectionStringName": "Sqlite" - } - }, - "Dispatcher:Hangfire": { - "Enabled": "true" - }, - "Console": { - "Enabled": "true" - }, - "Http": { - "Enabled": "true" - }, - "Email": { - "Enabled": "true" - }, - "Temporal:Quartz": { - "Enabled": "true" - }, - "JavaScript:Activities": { - "Enabled": "true" - }, - "UserTask": { - "Enabled": "true" - }, - "Conductor": { - "Enabled": "true" - }, - "Telnyx": { - "Enabled": "true" - }, - "Webhooks": { - "Enabled": "true" + "ConnectionStringName": "Sqlite" }, + "Dispatcher:Hangfire": true, + "Console": true, + "Http": true, + "Email": true, + "Temporal:Quartz": true, + "JavaScript:Activities": true, + "UserTask": true, + "Conductor": true, + "Telnyx": true, + "Webhooks": true, "Webhooks:Persistence:EntityFrameworkCore:Sqlite": { "Enabled": "true", - "Options": { - "ConnectionStringName": "Sqlite" - } + "ConnectionStringName": "Sqlite" } }, "WorkflowChannels": {