diff --git a/Directory.Packages.props b/Directory.Packages.props index 47cb4289c..f070fd1cd 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -95,7 +95,7 @@ - + @@ -130,6 +130,7 @@ + @@ -164,6 +165,7 @@ + diff --git a/Elsa.sln b/Elsa.sln index 403f8f081..6e979b393 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -301,8 +301,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integrations", "integration EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.OrchardCore", "src\modules\Elsa.OrchardCore\Elsa.OrchardCore.csproj", "{B0460856-7E6D-4B1E-B243-8E20662FC32E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.AspNet.OrchardCoreIntegration", "samples\aspnet\Elsa.Samples.AspNet.OrchardCoreIntegration\Elsa.Samples.AspNet.OrchardCoreIntegration.csproj", "{1451B84D-F224-4D5D-9A0D-985A8BD23D7B}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "agents", "agents", "{50470834-4CD8-479A-8B58-0A1869BA5D37}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Agents.Core", "src\modules\Elsa.Agents.Core\Elsa.Agents.Core.csproj", "{5BD671F0-9603-4C2F-8364-54B02986EAA2}" diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index 5cfda55b9..0ae3ab839 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -13,7 +13,6 @@ using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.Extensions; using Elsa.Features.Services; -using Elsa.Http.Multitenancy; using Elsa.Identity.Multitenancy; using Elsa.MassTransit.Extensions; using Elsa.MongoDb.Extensions; @@ -26,6 +25,7 @@ using Elsa.Secrets.Extensions; using Elsa.Secrets.Persistence; using Elsa.Server.Web; using Elsa.Server.Web.Filters; +using Elsa.Tenants.AspNetCore; using Elsa.Tenants.Extensions; using Elsa.Workflows; using Elsa.Workflows.Api; @@ -442,16 +442,16 @@ services .UseSecrets() .UseSecretsManagement(management => { - management.ConfigureOptions(options => configuration.GetSection("Secrets:Management").Bind(options)); - if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) - management.UseEntityFrameworkCore(ef => - ef.UseSqlServer(sqlServerConnectionString) - ); - else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) - management.UseEntityFrameworkCore(ef => - ef.UsePostgreSql(postgresConnectionString) - ); - else + management.ConfigureOptions(options => configuration.GetSection("Secrets:Management").Bind(options)); + if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) + management.UseEntityFrameworkCore(ef => + ef.UseSqlServer(sqlServerConnectionString) + ); + else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql) + management.UseEntityFrameworkCore(ef => + ef.UsePostgreSql(postgresConnectionString) + ); + else management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString)); }) .UseSecretsApi() @@ -467,10 +467,15 @@ services { configuration.GetSection("Multitenancy").Bind(options); options.TenantResolverPipelineBuilder + .Append() + .Append() + .Append() .Append(); }; tenants.UseConfigurationBasedTenantsProvider(); }); + + elsa.UseTenantHttpRouting(); } elsa.InstallDropIns(options => options.DropInRootDirectory = Path.Combine(Directory.GetCurrentDirectory(), "App_Data", "DropIns")); diff --git a/src/apps/Elsa.Server.Web/appsettings.json b/src/apps/Elsa.Server.Web/appsettings.json index 504a58879..3ad6705fe 100644 --- a/src/apps/Elsa.Server.Web/appsettings.json +++ b/src/apps/Elsa.Server.Web/appsettings.json @@ -25,21 +25,57 @@ "Multitenancy": { "Tenants": [ { - "Id": "default", - "Name": "Default" + "Id": null, + "Name": "Default", + "Configuration": { + "Http": { + "Prefix": "", + "Host": "localhost:5001" + }, + "ConnectionStrings": { + "Sqlite": "Data Source=App_Data/elsa.sqlite.db;Cache=Shared;" + } + } }, { "Id": "tenant-1", - "Name": "Tenant 1" + "Name": "Tenant 1", + "Configuration": { + "Http": { + "Prefix": "tenant-1", + "Host": "localhost:5002" + }, + "ConnectionStrings": { + "Sqlite": "Data Source=App_Data/elsa.tenant-1.sqlite.db;Cache=Shared;" + } + } }, { "Id": "tenant-2", - "Name": "Tenant 2" + "Name": "Tenant 2", + "Configuration": { + "Http": { + "Prefix": "tenant-2", + "Host": "localhost:5003" + }, + "ConnectionStrings": { + "Sqlite": "Data Source=App_Data/elsa.tenant-2.sqlite.db;Cache=Shared;" + } + } }, { "Id": "tenant-2a", "TenantId": "tenant-2", - "Name": "Tenant 2a" + "Name": "Tenant 2a", + "Configuration": { + "Http": { + "Prefix": "tenant-2a", + "Host": "localhost:5004" + }, + "ConnectionStrings": { + "Sqlite": "Data Source=App_Data/elsa.tenant-2a.sqlite.db;Cache=Shared;" + } + } } ] }, @@ -84,7 +120,7 @@ "Roles": [ "admin" ], - "TenantId": "default" + "TenantId": null }, { "id": "b0cd0e506e713a9d", diff --git a/src/apps/Elsa.ServerAndStudio.Web/Program.cs b/src/apps/Elsa.ServerAndStudio.Web/Program.cs index d54369283..59db60e34 100644 --- a/src/apps/Elsa.ServerAndStudio.Web/Program.cs +++ b/src/apps/Elsa.ServerAndStudio.Web/Program.cs @@ -8,8 +8,6 @@ using Elsa.JavaScript.Libraries.Extensions; using Elsa.ServerAndStudio.Web.Extensions; using Elsa.MassTransit.Extensions; using Elsa.ServerAndStudio.Web.Enums; -using Jint; -using Jint.Runtime.Modules; using Medallion.Threading.FileSystem; using Microsoft.AspNetCore.Mvc; using Microsoft.Data.Sqlite; diff --git a/src/apps/ElsaStudioWebAssembly/Program.cs b/src/apps/ElsaStudioWebAssembly/Program.cs index 5d553330d..c5e576a52 100644 --- a/src/apps/ElsaStudioWebAssembly/Program.cs +++ b/src/apps/ElsaStudioWebAssembly/Program.cs @@ -15,7 +15,6 @@ using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.Options; using Microsoft.JSInterop; -using Elsa.Studio.Models; // Build the host. var builder = WebAssemblyHostBuilder.CreateDefault(args); diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Models/ActivityExecutionRecordSummary.cs b/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Models/ActivityExecutionRecordSummary.cs index a224c62de..e92491d04 100644 --- a/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Models/ActivityExecutionRecordSummary.cs +++ b/src/clients/Elsa.Api.Client/Resources/ActivityExecutions/Models/ActivityExecutionRecordSummary.cs @@ -1,5 +1,3 @@ -using System.Linq.Expressions; -using Elsa.Api.Client.Resources.WorkflowInstances.Models; using Elsa.Api.Client.Shared.Models; namespace Elsa.Api.Client.Resources.ActivityExecutions.Models; diff --git a/src/common/Elsa.Api.Common/Abstractions/Endpoints.cs b/src/common/Elsa.Api.Common/Abstractions/Endpoints.cs index 79b59896b..82b6049f9 100644 --- a/src/common/Elsa.Api.Common/Abstractions/Endpoints.cs +++ b/src/common/Elsa.Api.Common/Abstractions/Endpoints.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using JetBrains.Annotations; namespace Elsa.Abstractions; diff --git a/src/modules/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs b/src/modules/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs index 888dc59f2..561e67a98 100644 --- a/src/modules/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs +++ b/src/modules/Elsa.Agents.Activities/ActivityProviders/AgentActivityProvider.cs @@ -5,7 +5,6 @@ using Elsa.Workflows; using Elsa.Workflows.Models; using Humanizer; using JetBrains.Annotations; -using Microsoft.Extensions.Logging; namespace Elsa.Agents.Activities.ActivityProviders; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Agents/Get/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Agents/Get/Endpoint.cs index 221822e28..fe7e45cda 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Agents/Get/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Agents/Get/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; using Elsa.Extensions; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Agents/IsUniqueName/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Agents/IsUniqueName/Endpoint.cs index b07201495..ce94700cc 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Agents/IsUniqueName/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Agents/IsUniqueName/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Filters; using JetBrains.Annotations; namespace Elsa.Agents.Api.Endpoints.Agents.IsUniqueName; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Agents/List/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Agents/List/Endpoint.cs index 05e48723f..47b74ec0f 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Agents/List/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Agents/List/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; using Elsa.Extensions; using Elsa.Models; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Agents/Update/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Agents/Update/Endpoint.cs index edb35dae9..c435280d4 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Agents/Update/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Agents/Update/Endpoint.cs @@ -1,7 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; -using Elsa.Agents.Persistence.Filters; using Elsa.Extensions; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/Get/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/Get/Endpoint.cs index c33580483..aaa5643f2 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/Get/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/Get/Endpoint.cs @@ -1,7 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; -using Elsa.Models; using JetBrains.Annotations; namespace Elsa.Agents.Api.Endpoints.ApiKeys.Get; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/List/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/List/Endpoint.cs index c5e895fd3..2ef4de235 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/List/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/ApiKeys/List/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; using Elsa.Models; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Services/Get/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Services/Get/Endpoint.cs index 54721c473..9467fdc2b 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Services/Get/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Services/Get/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; using JetBrains.Annotations; namespace Elsa.Agents.Api.Endpoints.Services.Get; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Services/List/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Services/List/Endpoint.cs index f2a502b16..b6f85f33e 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Services/List/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Services/List/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; using Elsa.Models; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Agents.Api/Endpoints/Services/Update/Endpoint.cs b/src/modules/Elsa.Agents.Api/Endpoints/Services/Update/Endpoint.cs index 0895eb97c..611893ef1 100644 --- a/src/modules/Elsa.Agents.Api/Endpoints/Services/Update/Endpoint.cs +++ b/src/modules/Elsa.Agents.Api/Endpoints/Services/Update/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Agents.Persistence.Contracts; -using Elsa.Agents.Persistence.Entities; using Elsa.Agents.Persistence.Filters; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Configurations.cs b/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Configurations.cs index 50eb88af9..9e59a70d3 100644 --- a/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Configurations.cs +++ b/src/modules/Elsa.Agents.Persistence.EntityFrameworkCore/Configurations.cs @@ -1,5 +1,4 @@ using Elsa.Agents.Persistence.Entities; -using Elsa.EntityFrameworkCore; using Elsa.EntityFrameworkCore.Extensions; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; diff --git a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs index 96bbc9c85..6d66a64ac 100644 --- a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs +++ b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs @@ -4,7 +4,6 @@ using Elsa.Workflows; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Filters; namespace Elsa.Alterations.Core.Services; diff --git a/src/modules/Elsa.AzureServiceBus/HostedServices/StartWorkers.cs b/src/modules/Elsa.AzureServiceBus/HostedServices/StartWorkers.cs index 3c6526053..5b325590e 100644 --- a/src/modules/Elsa.AzureServiceBus/HostedServices/StartWorkers.cs +++ b/src/modules/Elsa.AzureServiceBus/HostedServices/StartWorkers.cs @@ -4,7 +4,6 @@ using Elsa.AzureServiceBus.Models; using Elsa.Extensions; using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.AzureServiceBus/Models/ReceivedServiceBusMessageModel.cs b/src/modules/Elsa.AzureServiceBus/Models/ReceivedServiceBusMessageModel.cs index 02b414075..5b3889653 100644 --- a/src/modules/Elsa.AzureServiceBus/Models/ReceivedServiceBusMessageModel.cs +++ b/src/modules/Elsa.AzureServiceBus/Models/ReceivedServiceBusMessageModel.cs @@ -1,4 +1,3 @@ -using System.Text.Json.Serialization; using JetBrains.Annotations; namespace Elsa.AzureServiceBus.Models; diff --git a/src/modules/Elsa.AzureServiceBus/Services/Worker.cs b/src/modules/Elsa.AzureServiceBus/Services/Worker.cs index d2acfc66d..65f1e3532 100644 --- a/src/modules/Elsa.AzureServiceBus/Services/Worker.cs +++ b/src/modules/Elsa.AzureServiceBus/Services/Worker.cs @@ -1,9 +1,7 @@ using Azure.Messaging.ServiceBus; using Elsa.AzureServiceBus.Activities; using Elsa.AzureServiceBus.Models; -using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/src/modules/Elsa.Common/Elsa.Common.csproj b/src/modules/Elsa.Common/Elsa.Common.csproj index e48b149e2..54427079a 100644 --- a/src/modules/Elsa.Common/Elsa.Common.csproj +++ b/src/modules/Elsa.Common/Elsa.Common.csproj @@ -16,6 +16,7 @@ + diff --git a/src/modules/Elsa.Common/Multitenancy/Entities/Tenant.cs b/src/modules/Elsa.Common/Multitenancy/Entities/Tenant.cs index f58f5df37..fd2e9a304 100644 --- a/src/modules/Elsa.Common/Multitenancy/Entities/Tenant.cs +++ b/src/modules/Elsa.Common/Multitenancy/Entities/Tenant.cs @@ -1,5 +1,6 @@ using Elsa.Common.Entities; using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; namespace Elsa.Common.Multitenancy; @@ -13,9 +14,9 @@ public class Tenant : Entity /// Gets or sets the name. /// public string Name { get; set; } = default!; - + /// /// Gets or sets the configuration. /// - IDictionary Configuration { get; set; } = new Dictionary(); + public IConfiguration Configuration { get; set; } = new ConfigurationBuilder().Build(); } diff --git a/src/modules/Elsa.Elasticsearch/Modules/Runtime/WorkflowExecutionLogStore.cs b/src/modules/Elsa.Elasticsearch/Modules/Runtime/WorkflowExecutionLogStore.cs index 064f84a41..7addf8828 100644 --- a/src/modules/Elsa.Elasticsearch/Modules/Runtime/WorkflowExecutionLogStore.cs +++ b/src/modules/Elsa.Elasticsearch/Modules/Runtime/WorkflowExecutionLogStore.cs @@ -6,7 +6,6 @@ using Elsa.Elasticsearch.Common; using Elsa.Elasticsearch.Shared.Models; using Elsa.Extensions; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.OrderDefinitions; diff --git a/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs b/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs index 3ed12d6ed..6ff85ef22 100644 --- a/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore.Common/EntityStore.cs @@ -1,5 +1,4 @@ using Elsa.Common.Entities; -using Elsa.EntityFrameworkCore.Common.Contracts; using Microsoft.EntityFrameworkCore; namespace Elsa.EntityFrameworkCore.Common; diff --git a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Features.cs b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Features.cs index 83f146d36..48789b4cb 100644 --- a/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Features.cs +++ b/src/modules/Elsa.EntityFrameworkCore.PostgreSql/Features.cs @@ -7,7 +7,6 @@ using Elsa.EntityFrameworkCore.Modules.Labels; using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.EntityFrameworkCore.PostgreSql.Handlers; -using Elsa.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions; // ReSharper disable once CheckNamespace diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/ActivityExecutionLogStore.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/ActivityExecutionLogStore.cs index b19849752..c1526e08c 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/ActivityExecutionLogStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/ActivityExecutionLogStore.cs @@ -7,7 +7,6 @@ using Elsa.Workflows.Management; using Elsa.Workflows.Management.Compression; using Elsa.Workflows.Management.Options; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Extensions; using Elsa.Workflows.Runtime.Filters; diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/BookmarkStore.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/BookmarkStore.cs index c9b4ab117..78730b164 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/BookmarkStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/BookmarkStore.cs @@ -1,7 +1,6 @@ using Elsa.EntityFrameworkCore.Common; using Elsa.Workflows; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; diff --git a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/TriggerStore.cs b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/TriggerStore.cs index c0d4ffc58..3bda7c8a1 100644 --- a/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/TriggerStore.cs +++ b/src/modules/Elsa.EntityFrameworkCore/Modules/Runtime/TriggerStore.cs @@ -1,11 +1,9 @@ using Elsa.EntityFrameworkCore.Common; using Elsa.Workflows; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; -using Open.Linq.AsyncExtensions; namespace Elsa.EntityFrameworkCore.Modules.Runtime; diff --git a/src/modules/Elsa.Hangfire/Features/HangfireBackgroundActivityInvokerFeature.cs b/src/modules/Elsa.Hangfire/Features/HangfireBackgroundActivityInvokerFeature.cs index 416a1d16c..216ad6941 100644 --- a/src/modules/Elsa.Hangfire/Features/HangfireBackgroundActivityInvokerFeature.cs +++ b/src/modules/Elsa.Hangfire/Features/HangfireBackgroundActivityInvokerFeature.cs @@ -3,7 +3,6 @@ using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Hangfire.Services; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Features; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.Hangfire/Jobs/ExecuteBackgroundActivityJob.cs b/src/modules/Elsa.Hangfire/Jobs/ExecuteBackgroundActivityJob.cs index 49778bfc4..5a9f2622c 100644 --- a/src/modules/Elsa.Hangfire/Jobs/ExecuteBackgroundActivityJob.cs +++ b/src/modules/Elsa.Hangfire/Jobs/ExecuteBackgroundActivityJob.cs @@ -1,5 +1,4 @@ using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; namespace Elsa.Hangfire.Jobs; diff --git a/src/modules/Elsa.Hangfire/Jobs/RunWorkflowJob.cs b/src/modules/Elsa.Hangfire/Jobs/RunWorkflowJob.cs index e06b3527d..708d75a44 100644 --- a/src/modules/Elsa.Hangfire/Jobs/RunWorkflowJob.cs +++ b/src/modules/Elsa.Hangfire/Jobs/RunWorkflowJob.cs @@ -1,5 +1,4 @@ using Elsa.Scheduling; -using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Messages; diff --git a/src/modules/Elsa.Hangfire/Services/HangfireWorkflowScheduler.cs b/src/modules/Elsa.Hangfire/Services/HangfireWorkflowScheduler.cs index a2ff8d4eb..802555b3c 100644 --- a/src/modules/Elsa.Hangfire/Services/HangfireWorkflowScheduler.cs +++ b/src/modules/Elsa.Hangfire/Services/HangfireWorkflowScheduler.cs @@ -1,7 +1,6 @@ using Elsa.Hangfire.Extensions; using Elsa.Hangfire.Jobs; using Elsa.Scheduling; -using Elsa.Workflows.Runtime.Requests; using Hangfire; using Hangfire.Storage; diff --git a/src/modules/Elsa.Http/Abstractions/DownloadableContentHandlerBase.cs b/src/modules/Elsa.Http/Abstractions/DownloadableContentHandlerBase.cs index 02c7d236f..403f56823 100644 --- a/src/modules/Elsa.Http/Abstractions/DownloadableContentHandlerBase.cs +++ b/src/modules/Elsa.Http/Abstractions/DownloadableContentHandlerBase.cs @@ -1,6 +1,4 @@ using Elsa.Http.Contexts; -using Elsa.Http.Contracts; -using Elsa.Http.Models; namespace Elsa.Http.Abstractions; diff --git a/src/modules/Elsa.Http/Abstractions/HttpCorrelationIdSelectorBase.cs b/src/modules/Elsa.Http/Abstractions/HttpCorrelationIdSelectorBase.cs index 7403aef5c..43b4b4dde 100644 --- a/src/modules/Elsa.Http/Abstractions/HttpCorrelationIdSelectorBase.cs +++ b/src/modules/Elsa.Http/Abstractions/HttpCorrelationIdSelectorBase.cs @@ -1,4 +1,3 @@ -using Elsa.Http.Contracts; using Microsoft.AspNetCore.Http; namespace Elsa.Http.Abstractions; diff --git a/src/modules/Elsa.Http/Abstractions/HttpWorkflowInstanceIdSelectorBase.cs b/src/modules/Elsa.Http/Abstractions/HttpWorkflowInstanceIdSelectorBase.cs index 6d70522fa..df4890730 100644 --- a/src/modules/Elsa.Http/Abstractions/HttpWorkflowInstanceIdSelectorBase.cs +++ b/src/modules/Elsa.Http/Abstractions/HttpWorkflowInstanceIdSelectorBase.cs @@ -1,4 +1,3 @@ -using Elsa.Http.Contracts; using Microsoft.AspNetCore.Http; namespace Elsa.Http.Abstractions; diff --git a/src/modules/Elsa.Http/Activities/DownloadHttpFile.cs b/src/modules/Elsa.Http/Activities/DownloadHttpFile.cs index 86969016d..d355cf7cf 100644 --- a/src/modules/Elsa.Http/Activities/DownloadHttpFile.cs +++ b/src/modules/Elsa.Http/Activities/DownloadHttpFile.cs @@ -3,14 +3,12 @@ using System.Reflection; using System.Runtime.CompilerServices; using Elsa.Extensions; using Elsa.Http.ContentWriters; -using Elsa.Http.Models; using Elsa.Http.UIHints; using Elsa.Workflows; using Elsa.Workflows.Attributes; using Elsa.Workflows.UIHints; using Elsa.Workflows.Models; using Microsoft.Extensions.Logging; -using HttpHeaders = Elsa.Http.Models.HttpHeaders; namespace Elsa.Http; diff --git a/src/modules/Elsa.Http/Activities/HttpEndpoint.cs b/src/modules/Elsa.Http/Activities/HttpEndpoint.cs index 9f1e3c5f9..dc148b15f 100644 --- a/src/modules/Elsa.Http/Activities/HttpEndpoint.cs +++ b/src/modules/Elsa.Http/Activities/HttpEndpoint.cs @@ -3,7 +3,6 @@ using System.Text.Json; using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.Http.Bookmarks; -using Elsa.Http.Contracts; using Elsa.Http.UIHints; using Elsa.Workflows; using Elsa.Workflows.Attributes; @@ -208,7 +207,6 @@ public class HttpEndpoint : Trigger // Read route data, if any. var path = context.GetWorkflowInput(RequestPathInputKey); var routeData = GetRouteData(httpContext, path); - var routeDictionary = routeData.Values.ToDictionary(route => route.Key, route => route.Value!); var queryStringDictionary = httpContext.Request.Query.ToObjectDictionary(); var headersDictionary = httpContext.Request.Headers.ToObjectDictionary(); @@ -499,7 +497,7 @@ public class HttpEndpoint : Trigger var matchingRouteQuery = from route in routeTable - let routeValues = routeMatcher.Match(route, path) + let routeValues = routeMatcher.Match(route.Route, path) where routeValues != null select new { route, routeValues }; diff --git a/src/modules/Elsa.Http/Activities/SendHttpRequest.cs b/src/modules/Elsa.Http/Activities/SendHttpRequest.cs index f99f21548..4f9fe747a 100644 --- a/src/modules/Elsa.Http/Activities/SendHttpRequest.cs +++ b/src/modules/Elsa.Http/Activities/SendHttpRequest.cs @@ -1,5 +1,4 @@ using System.Runtime.CompilerServices; -using Elsa.Http.Models; using Elsa.Workflows; using Elsa.Workflows.Attributes; diff --git a/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs b/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs index 4fdaa3fcc..33af79027 100644 --- a/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs +++ b/src/modules/Elsa.Http/Activities/SendHttpRequestBase.cs @@ -7,7 +7,6 @@ using Elsa.Workflows.Attributes; using Elsa.Workflows.UIHints; using Elsa.Workflows.Models; using Microsoft.Extensions.Logging; -using HttpHeaders = Elsa.Http.Models.HttpHeaders; namespace Elsa.Http; diff --git a/src/modules/Elsa.Http/Activities/WriteFileHttpResponse.cs b/src/modules/Elsa.Http/Activities/WriteFileHttpResponse.cs index e12de62c9..8f0ec2557 100644 --- a/src/modules/Elsa.Http/Activities/WriteFileHttpResponse.cs +++ b/src/modules/Elsa.Http/Activities/WriteFileHttpResponse.cs @@ -1,8 +1,6 @@ using System.Security.Cryptography; using Elsa.Extensions; -using Elsa.Http.Contracts; using Elsa.Http.Exceptions; -using Elsa.Http.Models; using Elsa.Http.Options; using Elsa.Http.Services; using Elsa.Workflows; diff --git a/src/modules/Elsa.Http/Activities/WriteHttpResponse.cs b/src/modules/Elsa.Http/Activities/WriteHttpResponse.cs index 69cd8c0bf..2f583a3dc 100644 --- a/src/modules/Elsa.Http/Activities/WriteHttpResponse.cs +++ b/src/modules/Elsa.Http/Activities/WriteHttpResponse.cs @@ -2,7 +2,6 @@ using System.Net; using System.Runtime.CompilerServices; using Elsa.Extensions; using Elsa.Http.ContentWriters; -using Elsa.Http.Models; using Elsa.Http.UIHints; using Elsa.Workflows; using Elsa.Workflows.Attributes; @@ -72,7 +71,6 @@ public class WriteHttpResponse : Activity { // We're executing in a non-HTTP context (e.g. in a virtual actor). // Create a bookmark to allow the invoker to export the state and resume execution from there. - context.CreateBookmark(OnResumeAsync, BookmarkMetadata.HttpCrossBoundary); return; } @@ -135,11 +133,11 @@ public class WriteHttpResponse : Activity await response.WriteAsync("The response includes a type that cannot be serialized."); } } - } - - //Check if the configuration is set to flush immediatly the response to the caller. - var options = context.GetRequiredService>(); - if (options.Value.WriteHttpResponseSynchronously) + } + + // Check if the configuration is set to flush immediatly the response to the caller. + var options = context.GetRequiredService>(); + if (options.Value.WriteHttpResponseSynchronously) await response.CompleteAsync(); // Complete activity. diff --git a/src/modules/Elsa.Http/Contexts/DownloadableContext.cs b/src/modules/Elsa.Http/Contexts/DownloadableContext.cs index 4b72f02ef..cfe7b7c89 100644 --- a/src/modules/Elsa.Http/Contexts/DownloadableContext.cs +++ b/src/modules/Elsa.Http/Contexts/DownloadableContext.cs @@ -1,4 +1,3 @@ -using Elsa.Http.Contracts; using Elsa.Http.Options; namespace Elsa.Http.Contexts; diff --git a/src/modules/Elsa.Http/Contexts/HttpEndpointRouteProviderContext.cs b/src/modules/Elsa.Http/Contexts/HttpEndpointRouteProviderContext.cs new file mode 100644 index 000000000..ffb5666de --- /dev/null +++ b/src/modules/Elsa.Http/Contexts/HttpEndpointRouteProviderContext.cs @@ -0,0 +1,7 @@ +using Elsa.Http.Bookmarks; +using JetBrains.Annotations; + +namespace Elsa.Http.Contexts; + +[UsedImplicitly] +public record HttpEndpointRouteProviderContext(HttpEndpointBookmarkPayload Payload, string? TenantId, CancellationToken CancellationToken); \ No newline at end of file diff --git a/src/modules/Elsa.Http/Contracts/IAbsoluteUrlProvider.cs b/src/modules/Elsa.Http/Contracts/IAbsoluteUrlProvider.cs index 97d45267d..fdce26a9e 100644 --- a/src/modules/Elsa.Http/Contracts/IAbsoluteUrlProvider.cs +++ b/src/modules/Elsa.Http/Contracts/IAbsoluteUrlProvider.cs @@ -1,4 +1,4 @@ -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Provides a way to convert a relative URL to an absolute URL. diff --git a/src/modules/Elsa.Http/Contracts/IDownloadableContentHandler.cs b/src/modules/Elsa.Http/Contracts/IDownloadableContentHandler.cs index 3451bdbda..7044a3f09 100644 --- a/src/modules/Elsa.Http/Contracts/IDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/Contracts/IDownloadableContentHandler.cs @@ -1,7 +1,6 @@ using Elsa.Http.Contexts; -using Elsa.Http.Models; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Provides downloadables from the specified content, if supported. diff --git a/src/modules/Elsa.Http/Contracts/IDownloadableManager.cs b/src/modules/Elsa.Http/Contracts/IDownloadableManager.cs index 69919b48f..9ff824163 100644 --- a/src/modules/Elsa.Http/Contracts/IDownloadableManager.cs +++ b/src/modules/Elsa.Http/Contracts/IDownloadableManager.cs @@ -1,7 +1,6 @@ -using Elsa.Http.Models; using Elsa.Http.Options; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Provides downloadables from the specified content, if supported. diff --git a/src/modules/Elsa.Http/Contracts/IFileCacheStorageProvider.cs b/src/modules/Elsa.Http/Contracts/IFileCacheStorageProvider.cs index 2d7806de9..206852031 100644 --- a/src/modules/Elsa.Http/Contracts/IFileCacheStorageProvider.cs +++ b/src/modules/Elsa.Http/Contracts/IFileCacheStorageProvider.cs @@ -1,6 +1,6 @@ using FluentStorage.Blobs; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Represents a provider of a file cache storage. diff --git a/src/modules/Elsa.Http/Contracts/IFileDownloader.cs b/src/modules/Elsa.Http/Contracts/IFileDownloader.cs index 090a29682..b6414814a 100644 --- a/src/modules/Elsa.Http/Contracts/IFileDownloader.cs +++ b/src/modules/Elsa.Http/Contracts/IFileDownloader.cs @@ -1,6 +1,6 @@ using Elsa.Http.Options; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// A general-purpose downloader of files from a given URL. diff --git a/src/modules/Elsa.Http/Contracts/IHttpContentParser.cs b/src/modules/Elsa.Http/Contracts/IHttpContentParser.cs index 52562cf7e..df3b067f4 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpContentParser.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpContentParser.cs @@ -1,6 +1,6 @@ using Elsa.Http.Contexts; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// A strategy that reads a of a given content type. diff --git a/src/modules/Elsa.Http/Contracts/IHttpCorrelationIdSelector.cs b/src/modules/Elsa.Http/Contracts/IHttpCorrelationIdSelector.cs index d663acd68..9ded56059 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpCorrelationIdSelector.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpCorrelationIdSelector.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Provides a way to select the correlation ID for a request. diff --git a/src/modules/Elsa.Http/Contracts/IHttpEndpointAuthorizationHandler.cs b/src/modules/Elsa.Http/Contracts/IHttpEndpointAuthorizationHandler.cs index 8cea5d8eb..c1ae24254 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpEndpointAuthorizationHandler.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpEndpointAuthorizationHandler.cs @@ -1,6 +1,4 @@ -using Elsa.Http.Models; - -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// A handler that is invoked when authorizing an inbound HTTP request. diff --git a/src/modules/Elsa.Http/Contracts/IHttpEndpointFaultHandler.cs b/src/modules/Elsa.Http/Contracts/IHttpEndpointFaultHandler.cs index b3dd0dac1..1bf3d72c3 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpEndpointFaultHandler.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpEndpointFaultHandler.cs @@ -1,6 +1,4 @@ -using Elsa.Http.Models; - -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Implement this to control what to return to the client in case an unhandled exception occurs while executing the workflow. diff --git a/src/modules/Elsa.Http/Contracts/IHttpEndpointRoutesProvider.cs b/src/modules/Elsa.Http/Contracts/IHttpEndpointRoutesProvider.cs new file mode 100644 index 000000000..733f4883e --- /dev/null +++ b/src/modules/Elsa.Http/Contracts/IHttpEndpointRoutesProvider.cs @@ -0,0 +1,8 @@ +using Elsa.Http.Contexts; + +namespace Elsa.Http; + +public interface IHttpEndpointRoutesProvider +{ + Task> GetRoutesAsync(HttpEndpointRouteProviderContext context); +} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Contracts/IHttpWorkflowInstanceIdSelector.cs b/src/modules/Elsa.Http/Contracts/IHttpWorkflowInstanceIdSelector.cs index 28be3880f..61bbad798 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpWorkflowInstanceIdSelector.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpWorkflowInstanceIdSelector.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Provides a way to select the workflow instance ID for a request. diff --git a/src/modules/Elsa.Http/Contracts/IHttpWorkflowLookupService.cs b/src/modules/Elsa.Http/Contracts/IHttpWorkflowLookupService.cs index e6849efd1..3ceec7035 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpWorkflowLookupService.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpWorkflowLookupService.cs @@ -1,6 +1,4 @@ -using Elsa.Http.Models; - -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Represents a service that looks up HTTP workflows and triggers. diff --git a/src/modules/Elsa.Http/Contracts/IHttpWorkflowsCacheManager.cs b/src/modules/Elsa.Http/Contracts/IHttpWorkflowsCacheManager.cs index c380e84d3..f3d7ea3a4 100644 --- a/src/modules/Elsa.Http/Contracts/IHttpWorkflowsCacheManager.cs +++ b/src/modules/Elsa.Http/Contracts/IHttpWorkflowsCacheManager.cs @@ -1,6 +1,6 @@ using Elsa.Caching; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Represents a service that caches HTTP workflows and triggers. diff --git a/src/modules/Elsa.Http/Contracts/IRouteMatcher.cs b/src/modules/Elsa.Http/Contracts/IRouteMatcher.cs index deea4ae30..aea99300b 100644 --- a/src/modules/Elsa.Http/Contracts/IRouteMatcher.cs +++ b/src/modules/Elsa.Http/Contracts/IRouteMatcher.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Routing; -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Matches a given request path against the specified route template. diff --git a/src/modules/Elsa.Http/Contracts/IRouteTable.cs b/src/modules/Elsa.Http/Contracts/IRouteTable.cs index 88045e8cc..b82ce1c1f 100644 --- a/src/modules/Elsa.Http/Contracts/IRouteTable.cs +++ b/src/modules/Elsa.Http/Contracts/IRouteTable.cs @@ -1,9 +1,9 @@ -namespace Elsa.Http.Contracts; +namespace Elsa.Http; /// /// Stores a list of all routes provided by activities. /// -public interface IRouteTable : IEnumerable +public interface IRouteTable : IEnumerable { /// /// Adds a route to the table. @@ -11,6 +11,12 @@ public interface IRouteTable : IEnumerable /// The route to add. void Add(string route); + /// + /// Adds a route to the table. + /// + /// The route to add. + void Add(HttpRouteData httpRouteData); + /// /// Removes a route from the table. /// diff --git a/src/modules/Elsa.Http/Contracts/IRouteTableUpdater.cs b/src/modules/Elsa.Http/Contracts/IRouteTableUpdater.cs index 742d87c5e..fef7ad391 100644 --- a/src/modules/Elsa.Http/Contracts/IRouteTableUpdater.cs +++ b/src/modules/Elsa.Http/Contracts/IRouteTableUpdater.cs @@ -1,4 +1,8 @@ -namespace Elsa.Http.Contracts; +using Elsa.Workflows; +using Elsa.Workflows.Models; +using Elsa.Workflows.Runtime.Entities; + +namespace Elsa.Http; /// /// Updates the route table based on current workflow triggers and bookmarks. @@ -6,8 +10,42 @@ namespace Elsa.Http.Contracts; public interface IRouteTableUpdater { /// - /// Updates the route table. + /// Updates the route table based on current workflow triggers and bookmarks. /// /// The cancellation token. Task UpdateAsync(CancellationToken cancellationToken = default); + + /// + /// Adds routes to the route table based on the specified triggers. + /// + /// The triggers to create routes for. + /// The cancellation token. + Task AddRoutesAsync(IEnumerable triggers, CancellationToken cancellationToken = default); + + /// + /// Adds routes to the route table based on the specified bookmarks. + /// + /// The bookmarks to create routes for. + /// The cancellation token. + Task AddRoutesAsync(IEnumerable bookmarks, CancellationToken cancellationToken = default); + + /// + /// Adds routes to the route table based on the specified bookmarks. + /// + /// The bookmarks to create routes for. + /// The workflow execution context. + /// The cancellation token. + Task AddRoutesAsync(IEnumerable bookmarks, WorkflowExecutionContext workflowExecutionContext, CancellationToken cancellationToken = default); + + /// + /// Removes routes from the route table based on the specified triggers. + /// + /// The triggers to remove routes for. + void RemoveRoutes(IEnumerable triggers); + + /// + /// Removes routes from the route table based on the specified bookmarks. + /// + /// The bookmarks to remove routes for. + void RemoveRoutes(IEnumerable bookmarks); } \ No newline at end of file diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/BinaryDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/BinaryDownloadableContentHandler.cs index 364039f40..ba9963e69 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/BinaryDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/BinaryDownloadableContentHandler.cs @@ -1,6 +1,5 @@ using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/DownloadableDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/DownloadableDownloadableContentHandler.cs index c3ff81b8b..ef62872ab 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/DownloadableDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/DownloadableDownloadableContentHandler.cs @@ -1,6 +1,5 @@ using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/FormFileDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/FormFileDownloadableContentHandler.cs index 5c71aa83c..04d87452e 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/FormFileDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/FormFileDownloadableContentHandler.cs @@ -1,6 +1,5 @@ using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; using Microsoft.AspNetCore.Http; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/HttpFileDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/HttpFileDownloadableContentHandler.cs index dc1b52592..fd365bba4 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/HttpFileDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/HttpFileDownloadableContentHandler.cs @@ -1,6 +1,5 @@ using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/MultiDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/MultiDownloadableContentHandler.cs index 944e7c776..5ba23a4f3 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/MultiDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/MultiDownloadableContentHandler.cs @@ -1,7 +1,6 @@ using System.Collections; using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/StreamDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/StreamDownloadableContentHandler.cs index dfd5d9913..14bab3d79 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/StreamDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/StreamDownloadableContentHandler.cs @@ -1,6 +1,5 @@ using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/StringDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/StringDownloadableContentHandler.cs index cf5e9a429..239988dd7 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/StringDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/StringDownloadableContentHandler.cs @@ -1,7 +1,6 @@ using System.Text; using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Models; namespace Elsa.Http.DownloadableContentHandlers; diff --git a/src/modules/Elsa.Http/DownloadableContentHandlers/UrlDownloadableContentHandler.cs b/src/modules/Elsa.Http/DownloadableContentHandlers/UrlDownloadableContentHandler.cs index 10f836a9d..1fbbc6125 100644 --- a/src/modules/Elsa.Http/DownloadableContentHandlers/UrlDownloadableContentHandler.cs +++ b/src/modules/Elsa.Http/DownloadableContentHandlers/UrlDownloadableContentHandler.cs @@ -1,7 +1,5 @@ using Elsa.Http.Abstractions; using Elsa.Http.Contexts; -using Elsa.Http.Contracts; -using Elsa.Http.Models; using Elsa.Http.Options; using Microsoft.AspNetCore.StaticFiles; diff --git a/src/modules/Elsa.Http/Elsa.Http.csproj b/src/modules/Elsa.Http/Elsa.Http.csproj index b0cf13616..4c5dea68e 100644 --- a/src/modules/Elsa.Http/Elsa.Http.csproj +++ b/src/modules/Elsa.Http/Elsa.Http.csproj @@ -20,10 +20,10 @@ - + diff --git a/src/modules/Elsa.Http/Elsa.Http.csproj.DotSettings b/src/modules/Elsa.Http/Elsa.Http.csproj.DotSettings index 45ef2789e..96739afba 100644 --- a/src/modules/Elsa.Http/Elsa.Http.csproj.DotSettings +++ b/src/modules/Elsa.Http/Elsa.Http.csproj.DotSettings @@ -2,4 +2,6 @@ True True True - True \ No newline at end of file + True + True + True \ No newline at end of file diff --git a/src/modules/Elsa.Http/Extensions/ExpressionExecutionContextExtensions.cs b/src/modules/Elsa.Http/Extensions/ExpressionExecutionContextExtensions.cs index fc85796db..a4eac875f 100644 --- a/src/modules/Elsa.Http/Extensions/ExpressionExecutionContextExtensions.cs +++ b/src/modules/Elsa.Http/Extensions/ExpressionExecutionContextExtensions.cs @@ -1,6 +1,5 @@ using Elsa.Expressions.Models; -using Elsa.Http.Contracts; -using Elsa.Http.Models; +using Elsa.Http; using Elsa.Http.Options; using Elsa.SasTokens.Contracts; using Microsoft.Extensions.Options; diff --git a/src/modules/Elsa.Http/Extensions/HttpActivityExecutionContextExtensions.cs b/src/modules/Elsa.Http/Extensions/HttpActivityExecutionContextExtensions.cs index a51a16f60..3538ace13 100644 --- a/src/modules/Elsa.Http/Extensions/HttpActivityExecutionContextExtensions.cs +++ b/src/modules/Elsa.Http/Extensions/HttpActivityExecutionContextExtensions.cs @@ -1,5 +1,5 @@ +using Elsa.Http; using Elsa.Http.Contexts; -using Elsa.Http.Contracts; using Elsa.Workflows; using Elsa.Workflows.Models; diff --git a/src/modules/Elsa.Http/Extensions/RouteTableExtensions.cs b/src/modules/Elsa.Http/Extensions/RouteTableExtensions.cs deleted file mode 100644 index 28d0db608..000000000 --- a/src/modules/Elsa.Http/Extensions/RouteTableExtensions.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Elsa.Http; -using Elsa.Http.Bookmarks; -using Elsa.Http.Contracts; -using Elsa.Workflows.Helpers; -using Elsa.Workflows.Models; -using Elsa.Workflows.Runtime.Entities; - -// ReSharper disable once CheckNamespace -namespace Elsa.Extensions; - -/// -/// Adds extensions to . -/// -public static class RouteTableExtensions -{ - /// - /// Adds routes from the specified set of triggers. - /// - public static void AddRoutes(this IRouteTable routeTable, IEnumerable triggers) - { - var paths = Filter(triggers).Select(x => x.GetPayload().Path).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); - routeTable.AddRange(paths); - } - - /// - /// Adds routes from the specified set of bookmarks. - /// - public static void AddRoutes(this IRouteTable routeTable, IEnumerable bookmarks) - { - var paths = Filter(bookmarks).Select(x => x.GetPayload().Path).ToList(); - routeTable.AddRange(paths); - } - - /// - /// Adds routes from the specified set of bookmarks. - /// - public static void AddRoutes(this IRouteTable routeTable, IEnumerable bookmarks) - { - var paths = Filter(bookmarks).Select(x => x.GetPayload().Path).ToList(); - routeTable.AddRange(paths); - } - - /// - /// Removes routes from the specified set of triggers. - /// - public static void RemoveRoutes(this IRouteTable routeTable, IEnumerable triggers) - { - var paths = Filter(triggers).Select(x => x.GetPayload().Path).ToList(); - routeTable.RemoveRange(paths); - } - - /// - /// Removes routes from the specified set of bookmarks. - /// - public static void RemoveRoutes(this IRouteTable routeTable, IEnumerable bookmarks) - { - var paths = Filter(bookmarks).Select(x => x.GetPayload().Path).ToList(); - routeTable.RemoveRange(paths); - } - - private static IEnumerable Filter(IEnumerable triggers) - { - var triggerName = ActivityTypeNameHelper.GenerateTypeName(); - return triggers.Where(x => x.Name == triggerName && x.Payload != null); - } - - private static IEnumerable Filter(IEnumerable bookmarks) - { - var activityTypeName = ActivityTypeNameHelper.GenerateTypeName(); - return bookmarks.Where(x => x.ActivityTypeName == activityTypeName && x.Payload != null); - } - - private static IEnumerable Filter(IEnumerable bookmarks) - { - var bookmarkName = ActivityTypeNameHelper.GenerateTypeName(); - return bookmarks.Where(x => x.Name == bookmarkName && x.Payload != null); - } -} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Extensions/ServiceCollectionExtensions.cs b/src/modules/Elsa.Http/Extensions/ServiceCollectionExtensions.cs index 75640982c..300080538 100644 --- a/src/modules/Elsa.Http/Extensions/ServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Http/Extensions/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -using Elsa.Http.Contracts; +using Elsa.Http; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; diff --git a/src/modules/Elsa.Http/Extensions/StringArrayExtensions.cs b/src/modules/Elsa.Http/Extensions/StringArrayExtensions.cs new file mode 100644 index 000000000..fa02c9e44 --- /dev/null +++ b/src/modules/Elsa.Http/Extensions/StringArrayExtensions.cs @@ -0,0 +1,11 @@ +// ReSharper disable once CheckNamespace + +namespace Elsa.Extensions; + +public static class StringArrayExtensions +{ + public static string JoinSegments(this IEnumerable segments, string separator = "/") + { + return string.Join(separator, segments.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x!.Trim('/'))); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Extensions/StringValueExtensions.cs b/src/modules/Elsa.Http/Extensions/StringValueExtensions.cs index bd05d043c..1296027ff 100644 --- a/src/modules/Elsa.Http/Extensions/StringValueExtensions.cs +++ b/src/modules/Elsa.Http/Extensions/StringValueExtensions.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Primitives; +// ReSharper disable once CheckNamespace namespace Elsa.Extensions; /// @@ -20,4 +21,4 @@ public static class StringValueExtensions item.Value[0]! : item.Value.ToArray()); } -} +} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Features/HttpCacheFeature.cs b/src/modules/Elsa.Http/Features/HttpCacheFeature.cs index 1f54df1da..4dbc59ba2 100644 --- a/src/modules/Elsa.Http/Features/HttpCacheFeature.cs +++ b/src/modules/Elsa.Http/Features/HttpCacheFeature.cs @@ -1,7 +1,6 @@ using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; -using Elsa.Http.Contracts; using Elsa.Http.Handlers; using Elsa.Http.Services; using Elsa.Workflows.Management.Features; diff --git a/src/modules/Elsa.Http/Features/HttpFeature.cs b/src/modules/Elsa.Http/Features/HttpFeature.cs index 43572675e..416ed7d84 100644 --- a/src/modules/Elsa.Http/Features/HttpFeature.cs +++ b/src/modules/Elsa.Http/Features/HttpFeature.cs @@ -1,17 +1,13 @@ -using Elsa.Common.Multitenancy; using Elsa.Expressions.Options; using Elsa.Extensions; using Elsa.Features.Abstractions; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Http.ContentWriters; -using Elsa.Http.Contracts; using Elsa.Http.DownloadableContentHandlers; using Elsa.Http.FileCaches; using Elsa.Http.Handlers; using Elsa.Http.HostedServices; -using Elsa.Http.Models; -using Elsa.Http.Multitenancy; using Elsa.Http.Options; using Elsa.Http.Parsers; using Elsa.Http.PortResolvers; @@ -23,7 +19,6 @@ using Elsa.Workflows.Management.Requests; using Elsa.Workflows.Management.Responses; using FluentStorage; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -34,12 +29,9 @@ namespace Elsa.Http.Features; /// Installs services related to HTTP services and activities. /// [DependsOn(typeof(HttpJavaScriptFeature))] -public class HttpFeature : FeatureBase +public class HttpFeature(IModule module) : FeatureBase(module) { - /// - public HttpFeature(IModule module) : base(module) - { - } + private Func _httpEndpointRouteProvider = sp => sp.GetRequiredService(); /// /// A delegate to configure . @@ -104,14 +96,24 @@ public class HttpFeature : FeatureBase typeof(QueryStringHttpWorkflowInstanceIdSelector) }; + public HttpFeature WithHttpEndpointRoutesProvider() where T : IHttpEndpointRoutesProvider + { + return WithHttpEndpointRoutesProvider(sp => sp.GetRequiredService()); + } + + public HttpFeature WithHttpEndpointRoutesProvider(Func httpEndpointRouteProvider) + { + _httpEndpointRouteProvider = httpEndpointRouteProvider; + return this; + } + /// public override void Configure() { Module.UseWorkflowManagement(management => { - management.AddVariableTypes(new[] - { - typeof(RouteData), + management.AddVariableTypes([ + typeof(HttpRouteData), typeof(HttpRequest), typeof(HttpResponse), typeof(HttpResponseMessage), @@ -119,7 +121,7 @@ public class HttpFeature : FeatureBase typeof(IFormFile), typeof(HttpFile), typeof(Downloadable) - }, "HTTP"); + ], "HTTP"); management.AddActivitiesFrom(); }); @@ -184,8 +186,10 @@ public class HttpFeature : FeatureBase .AddScoped() .AddScoped() .AddScoped() + .AddScoped() .AddScoped(HttpEndpointWorkflowFaultHandler) .AddScoped(HttpEndpointAuthorizationHandler) + .AddScoped(_httpEndpointRouteProvider) // Downloadable content handlers. .AddScoped() @@ -208,9 +212,6 @@ public class HttpFeature : FeatureBase // HTTP clients. Services.AddHttpClient(); - - // Tenant resolvers. - Services.AddScoped(); // Add selectors. foreach (var httpCorrelationIdSelectorType in HttpCorrelationIdSelectorTypes) @@ -225,7 +226,7 @@ public class HttpFeature : FeatureBase options.AddTypeAlias("HttpResponse"); options.AddTypeAlias("HttpResponseMessage"); options.AddTypeAlias("HttpHeaders"); - options.AddTypeAlias("RouteData"); + options.AddTypeAlias("RouteData"); options.AddTypeAlias("FormFile"); options.AddTypeAlias("FormFile[]"); options.AddTypeAlias("HttpFile"); diff --git a/src/modules/Elsa.Http/FileCaches/BlobFileCacheStorageProvider.cs b/src/modules/Elsa.Http/FileCaches/BlobFileCacheStorageProvider.cs index b067a1c59..17c94840d 100644 --- a/src/modules/Elsa.Http/FileCaches/BlobFileCacheStorageProvider.cs +++ b/src/modules/Elsa.Http/FileCaches/BlobFileCacheStorageProvider.cs @@ -1,4 +1,3 @@ -using Elsa.Http.Contracts; using FluentStorage.Blobs; namespace Elsa.Http.FileCaches; diff --git a/src/modules/Elsa.Http/Handlers/AllowAnonymousHttpEndpointAuthorizationHandler.cs b/src/modules/Elsa.Http/Handlers/AllowAnonymousHttpEndpointAuthorizationHandler.cs index 8007ba79a..050316302 100644 --- a/src/modules/Elsa.Http/Handlers/AllowAnonymousHttpEndpointAuthorizationHandler.cs +++ b/src/modules/Elsa.Http/Handlers/AllowAnonymousHttpEndpointAuthorizationHandler.cs @@ -1,6 +1,3 @@ -using Elsa.Http.Contracts; -using Elsa.Http.Models; - namespace Elsa.Http.Handlers; /// diff --git a/src/modules/Elsa.Http/Handlers/AuthenticationBasedHttpEndpointAuthorizationHandler.cs b/src/modules/Elsa.Http/Handlers/AuthenticationBasedHttpEndpointAuthorizationHandler.cs index 973c0723e..fa7a540fa 100644 --- a/src/modules/Elsa.Http/Handlers/AuthenticationBasedHttpEndpointAuthorizationHandler.cs +++ b/src/modules/Elsa.Http/Handlers/AuthenticationBasedHttpEndpointAuthorizationHandler.cs @@ -1,5 +1,3 @@ -using Elsa.Http.Contracts; -using Elsa.Http.Models; using JetBrains.Annotations; using Microsoft.AspNetCore.Authorization; diff --git a/src/modules/Elsa.Http/Handlers/DefaultHttpEndpointFaultHandler.cs b/src/modules/Elsa.Http/Handlers/DefaultHttpEndpointFaultHandler.cs index cdbeef028..81a93c34e 100644 --- a/src/modules/Elsa.Http/Handlers/DefaultHttpEndpointFaultHandler.cs +++ b/src/modules/Elsa.Http/Handlers/DefaultHttpEndpointFaultHandler.cs @@ -1,6 +1,4 @@ -using Elsa.Http.Models; using Microsoft.AspNetCore.Http; -using Elsa.Http.Contracts; using Elsa.Http.Exceptions; namespace Elsa.Http.Handlers; diff --git a/src/modules/Elsa.Http/Handlers/DetailedHttpEndpointFaultHandler.cs b/src/modules/Elsa.Http/Handlers/DetailedHttpEndpointFaultHandler.cs index 731d893b4..82dd93174 100644 --- a/src/modules/Elsa.Http/Handlers/DetailedHttpEndpointFaultHandler.cs +++ b/src/modules/Elsa.Http/Handlers/DetailedHttpEndpointFaultHandler.cs @@ -1,6 +1,4 @@ using System.Net.Mime; -using Elsa.Http.Contracts; -using Elsa.Http.Models; using Elsa.Workflows; using Microsoft.AspNetCore.Http; diff --git a/src/modules/Elsa.Http/Handlers/InvalidateHttpWorkflowsCache.cs b/src/modules/Elsa.Http/Handlers/InvalidateHttpWorkflowsCache.cs index 0fddca961..b40893216 100644 --- a/src/modules/Elsa.Http/Handlers/InvalidateHttpWorkflowsCache.cs +++ b/src/modules/Elsa.Http/Handlers/InvalidateHttpWorkflowsCache.cs @@ -1,5 +1,4 @@ using Elsa.Http.Bookmarks; -using Elsa.Http.Contracts; using Elsa.Mediator.Contracts; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Notifications; diff --git a/src/modules/Elsa.Http/Handlers/UpdateRouteTable.cs b/src/modules/Elsa.Http/Handlers/UpdateRouteTable.cs index 9f47ae2e6..4d3571006 100644 --- a/src/modules/Elsa.Http/Handlers/UpdateRouteTable.cs +++ b/src/modules/Elsa.Http/Handlers/UpdateRouteTable.cs @@ -1,38 +1,31 @@ -using Elsa.Extensions; -using Elsa.Http.Contracts; +using Elsa.Http.Options; using Elsa.Mediator.Contracts; using Elsa.Workflows.Runtime.Notifications; +using JetBrains.Annotations; +using Microsoft.Extensions.Options; namespace Elsa.Http.Handlers; /// /// A handler that updates the route table when workflow triggers and bookmarks are indexed. /// -public class UpdateRouteTable : +[UsedImplicitly] +public class UpdateRouteTable(IRouteTableUpdater routeTableUpdater, IOptions options) : INotificationHandler, INotificationHandler { - private readonly IRouteTable _routeTable; - - /// - /// Initializes a new instance of the class. - /// - public UpdateRouteTable(IRouteTable routeTable) => _routeTable = routeTable; - /// - public Task HandleAsync(WorkflowTriggersIndexed notification, CancellationToken cancellationToken) + public async Task HandleAsync(WorkflowTriggersIndexed notification, CancellationToken cancellationToken) { - _routeTable.RemoveRoutes(notification.IndexedWorkflowTriggers.RemovedTriggers); - _routeTable.AddRoutes(notification.IndexedWorkflowTriggers.AddedTriggers); - _routeTable.AddRoutes(notification.IndexedWorkflowTriggers.UnchangedTriggers); - return Task.CompletedTask; + routeTableUpdater.RemoveRoutes(notification.IndexedWorkflowTriggers.RemovedTriggers); + await routeTableUpdater.AddRoutesAsync(notification.IndexedWorkflowTriggers.AddedTriggers, cancellationToken); + await routeTableUpdater.AddRoutesAsync(notification.IndexedWorkflowTriggers.UnchangedTriggers, cancellationToken); } /// - public Task HandleAsync(WorkflowBookmarksIndexed notification, CancellationToken cancellationToken) + public async Task HandleAsync(WorkflowBookmarksIndexed notification, CancellationToken cancellationToken) { - _routeTable.RemoveRoutes(notification.IndexedWorkflowBookmarks.RemovedBookmarks); - _routeTable.AddRoutes(notification.IndexedWorkflowBookmarks.AddedBookmarks); - return Task.CompletedTask; + routeTableUpdater.RemoveRoutes(notification.IndexedWorkflowBookmarks.RemovedBookmarks); + await routeTableUpdater.AddRoutesAsync(notification.IndexedWorkflowBookmarks.AddedBookmarks, notification.IndexedWorkflowBookmarks.WorkflowExecutionContext, cancellationToken); } } \ No newline at end of file diff --git a/src/modules/Elsa.Http/HostedServices/UpdateRouteTableHostedService.cs b/src/modules/Elsa.Http/HostedServices/UpdateRouteTableHostedService.cs index 760e6950f..378737997 100644 --- a/src/modules/Elsa.Http/HostedServices/UpdateRouteTableHostedService.cs +++ b/src/modules/Elsa.Http/HostedServices/UpdateRouteTableHostedService.cs @@ -1,5 +1,4 @@ -using Elsa.Http.Contracts; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace Elsa.Http.HostedServices; diff --git a/src/modules/Elsa.Http/Middleware/HttpWorkflowsMiddleware.cs b/src/modules/Elsa.Http/Middleware/HttpWorkflowsMiddleware.cs index 1466c771f..229a2a055 100644 --- a/src/modules/Elsa.Http/Middleware/HttpWorkflowsMiddleware.cs +++ b/src/modules/Elsa.Http/Middleware/HttpWorkflowsMiddleware.cs @@ -1,7 +1,5 @@ using Elsa.Extensions; using Elsa.Http.Bookmarks; -using Elsa.Http.Contracts; -using Elsa.Http.Models; using Elsa.Http.Options; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; @@ -17,8 +15,6 @@ using Elsa.Workflows.Runtime.Entities; using FastEndpoints; using System.Diagnostics.CodeAnalysis; using Elsa.Common.Multitenancy; -using Elsa.Tenants; -using Elsa.Tenants.Extensions; using Elsa.Workflows; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; @@ -33,7 +29,7 @@ namespace Elsa.Http.Middleware; /// An ASP.NET middleware component that tries to match the inbound request path to an associated workflow and then run that workflow. /// [PublicAPI] -public class HttpWorkflowsMiddleware(RequestDelegate next, IOptions options) +public class HttpWorkflowsMiddleware(RequestDelegate next, ITenantAccessor tenantAccessor, IOptions options) { private readonly string _activityTypeName = ActivityTypeNameHelper.GenerateTypeName(); @@ -59,7 +55,7 @@ public class HttpWorkflowsMiddleware(RequestDelegate next, IOptions { [HttpEndpoint.HttpContextInputKey] = true, @@ -252,23 +248,23 @@ public class HttpWorkflowsMiddleware(RequestDelegate next, IOptions(); var routeTable = serviceProvider.GetRequiredService(); var matchingRouteQuery = - from route in routeTable - let routeValues = routeMatcher.Match(route, path) + from routeData in routeTable + let routeValues = routeMatcher.Match(routeData.Route, path) where routeValues != null select new { - route, + route = routeData, routeValues }; var matchingRoute = matchingRouteQuery.FirstOrDefault(); - var routeTemplate = matchingRoute?.route ?? path; + var routeTemplate = matchingRoute?.route ?? new HttpRouteData(path); return routeTemplate; } @@ -366,7 +362,7 @@ public class HttpWorkflowsMiddleware(RequestDelegate next, IOptions(); - if (bookmarkPayload.Authorize ?? false) + if (bookmarkPayload.Authorize == false) return true; return await httpEndpointAuthorizationHandler.AuthorizeAsync(new AuthorizeHttpEndpointContext(httpContext, workflow, bookmarkPayload.Policy)); diff --git a/src/modules/Elsa.Http/Models/AuthorizeHttpEndpointContext.cs b/src/modules/Elsa.Http/Models/AuthorizeHttpEndpointContext.cs index 684ce9387..d5d2c66d3 100644 --- a/src/modules/Elsa.Http/Models/AuthorizeHttpEndpointContext.cs +++ b/src/modules/Elsa.Http/Models/AuthorizeHttpEndpointContext.cs @@ -1,7 +1,7 @@ using Elsa.Workflows.Activities; using Microsoft.AspNetCore.Http; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Represents the context for authorizing an HTTP endpoint. diff --git a/src/modules/Elsa.Http/Models/Downloadable.cs b/src/modules/Elsa.Http/Models/Downloadable.cs index 151647676..064845fc2 100644 --- a/src/modules/Elsa.Http/Models/Downloadable.cs +++ b/src/modules/Elsa.Http/Models/Downloadable.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Represents a downloadable object. diff --git a/src/modules/Elsa.Http/Models/EventTokenPayload.cs b/src/modules/Elsa.Http/Models/EventTokenPayload.cs index c35deb837..22d5fd214 100644 --- a/src/modules/Elsa.Http/Models/EventTokenPayload.cs +++ b/src/modules/Elsa.Http/Models/EventTokenPayload.cs @@ -1,4 +1,4 @@ -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Represents the payload of an event, serialized as a secured token. diff --git a/src/modules/Elsa.Http/Models/HttpEndpointFaultContext.cs b/src/modules/Elsa.Http/Models/HttpEndpointFaultContext.cs index 7263f4ece..22d0b06ba 100644 --- a/src/modules/Elsa.Http/Models/HttpEndpointFaultContext.cs +++ b/src/modules/Elsa.Http/Models/HttpEndpointFaultContext.cs @@ -1,7 +1,7 @@ using Elsa.Workflows.State; using Microsoft.AspNetCore.Http; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Provides context about the faulted workflow. diff --git a/src/modules/Elsa.Http/Models/HttpFile.cs b/src/modules/Elsa.Http/Models/HttpFile.cs index 3977bb3bc..4f3fcf1da 100644 --- a/src/modules/Elsa.Http/Models/HttpFile.cs +++ b/src/modules/Elsa.Http/Models/HttpFile.cs @@ -1,7 +1,7 @@ using System.Net.Http.Headers; using System.Text.Json.Serialization; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Represents a downloadable object. diff --git a/src/modules/Elsa.Http/Models/HttpHeaders.cs b/src/modules/Elsa.Http/Models/HttpHeaders.cs index bcf4a160d..9c95098c0 100644 --- a/src/modules/Elsa.Http/Models/HttpHeaders.cs +++ b/src/modules/Elsa.Http/Models/HttpHeaders.cs @@ -3,7 +3,7 @@ using System.Text.Json.Serialization; using Elsa.Extensions; using Elsa.Http.Serialization; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Represents the headers of an HTTP message. diff --git a/src/modules/Elsa.Http/Models/HttpRouteData.cs b/src/modules/Elsa.Http/Models/HttpRouteData.cs new file mode 100644 index 000000000..2379537b4 --- /dev/null +++ b/src/modules/Elsa.Http/Models/HttpRouteData.cs @@ -0,0 +1,31 @@ +using JetBrains.Annotations; +using Microsoft.AspNetCore.Routing; + +namespace Elsa.Http; + +[UsedImplicitly] +public class HttpRouteData +{ + public HttpRouteData() + { + } + + public HttpRouteData(string route) : this() + { + Route = route; + } + + public HttpRouteData(string route, RouteValueDictionary dataTokens) : this(route) + { + DataTokens = dataTokens; + } + + public HttpRouteData(string route, RouteValueDictionary dataTokens, RouteValueDictionary routeValues) : this(route, dataTokens) + { + RouteValues = routeValues; + } + + public string Route { get; set; } = default!; + public RouteValueDictionary DataTokens { get; set; } = new(); + public RouteValueDictionary RouteValues { get; set; } = new(); +} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Models/HttpStatusCodeCase.cs b/src/modules/Elsa.Http/Models/HttpStatusCodeCase.cs index 9e033f9a3..c778f3896 100644 --- a/src/modules/Elsa.Http/Models/HttpStatusCodeCase.cs +++ b/src/modules/Elsa.Http/Models/HttpStatusCodeCase.cs @@ -1,7 +1,7 @@ using System.Text.Json.Serialization; using Elsa.Workflows; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// A binding between an HTTP status code and an activity. diff --git a/src/modules/Elsa.Http/Models/HttpWorkflowLookupResult.cs b/src/modules/Elsa.Http/Models/HttpWorkflowLookupResult.cs index 64a578901..9c7d601e6 100644 --- a/src/modules/Elsa.Http/Models/HttpWorkflowLookupResult.cs +++ b/src/modules/Elsa.Http/Models/HttpWorkflowLookupResult.cs @@ -1,7 +1,7 @@ using Elsa.Workflows.Models; using Elsa.Workflows.Runtime.Entities; -namespace Elsa.Http.Models; +namespace Elsa.Http; /// /// Represents the result of a workflow lookup. diff --git a/src/modules/Elsa.Http/Parsers/FileHttpContentParser.cs b/src/modules/Elsa.Http/Parsers/FileHttpContentParser.cs index aa1dc0471..3067a59ed 100644 --- a/src/modules/Elsa.Http/Parsers/FileHttpContentParser.cs +++ b/src/modules/Elsa.Http/Parsers/FileHttpContentParser.cs @@ -1,7 +1,5 @@ using Elsa.Extensions; using Elsa.Http.Contexts; -using Elsa.Http.Contracts; -using Elsa.Http.Models; namespace Elsa.Http.Parsers; diff --git a/src/modules/Elsa.Http/Parsers/JsonHttpContentParser.cs b/src/modules/Elsa.Http/Parsers/JsonHttpContentParser.cs index b55beca38..b563c818d 100644 --- a/src/modules/Elsa.Http/Parsers/JsonHttpContentParser.cs +++ b/src/modules/Elsa.Http/Parsers/JsonHttpContentParser.cs @@ -3,7 +3,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Expressions.Helpers; using Elsa.Http.Contexts; -using Elsa.Http.Contracts; using Elsa.Workflows.Serialization.Converters; namespace Elsa.Http.Parsers; diff --git a/src/modules/Elsa.Http/Parsers/PlainTextHttpContentParser.cs b/src/modules/Elsa.Http/Parsers/PlainTextHttpContentParser.cs index 782646131..f04544474 100644 --- a/src/modules/Elsa.Http/Parsers/PlainTextHttpContentParser.cs +++ b/src/modules/Elsa.Http/Parsers/PlainTextHttpContentParser.cs @@ -1,5 +1,4 @@ using Elsa.Http.Contexts; -using Elsa.Http.Contracts; namespace Elsa.Http.Parsers; diff --git a/src/modules/Elsa.Http/Parsers/TextHtmlHttpContentParser.cs b/src/modules/Elsa.Http/Parsers/TextHtmlHttpContentParser.cs index f33b92d63..fbf559981 100644 --- a/src/modules/Elsa.Http/Parsers/TextHtmlHttpContentParser.cs +++ b/src/modules/Elsa.Http/Parsers/TextHtmlHttpContentParser.cs @@ -1,5 +1,4 @@ using Elsa.Http.Contexts; -using Elsa.Http.Contracts; namespace Elsa.Http.Parsers; diff --git a/src/modules/Elsa.Http/Parsers/XmlHttpContentParser.cs b/src/modules/Elsa.Http/Parsers/XmlHttpContentParser.cs index 51a82c214..4827c06ae 100644 --- a/src/modules/Elsa.Http/Parsers/XmlHttpContentParser.cs +++ b/src/modules/Elsa.Http/Parsers/XmlHttpContentParser.cs @@ -1,6 +1,5 @@ using System.Xml.Serialization; using Elsa.Http.Contexts; -using Elsa.Http.Contracts; namespace Elsa.Http.Parsers; diff --git a/src/modules/Elsa.Http/Scripting/JavaScript/HttpJavaScriptHandler.cs b/src/modules/Elsa.Http/Scripting/JavaScript/HttpJavaScriptHandler.cs index c0565fac3..c71bfb661 100644 --- a/src/modules/Elsa.Http/Scripting/JavaScript/HttpJavaScriptHandler.cs +++ b/src/modules/Elsa.Http/Scripting/JavaScript/HttpJavaScriptHandler.cs @@ -1,5 +1,4 @@ using Elsa.Extensions; -using Elsa.Http.Models; using Elsa.JavaScript.Notifications; using Elsa.JavaScript.TypeDefinitions.Builders; using Elsa.JavaScript.TypeDefinitions.Contracts; diff --git a/src/modules/Elsa.Http/Serialization/HttpHeadersConverter.cs b/src/modules/Elsa.Http/Serialization/HttpHeadersConverter.cs index ece243fd7..81291ec24 100644 --- a/src/modules/Elsa.Http/Serialization/HttpHeadersConverter.cs +++ b/src/modules/Elsa.Http/Serialization/HttpHeadersConverter.cs @@ -1,6 +1,5 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Http.Models; namespace Elsa.Http.Serialization; diff --git a/src/modules/Elsa.Http/Serialization/HttpStatusCodeCaseForWorkflowInstanceConverter.cs b/src/modules/Elsa.Http/Serialization/HttpStatusCodeCaseForWorkflowInstanceConverter.cs index d11e4e5b6..98946b074 100644 --- a/src/modules/Elsa.Http/Serialization/HttpStatusCodeCaseForWorkflowInstanceConverter.cs +++ b/src/modules/Elsa.Http/Serialization/HttpStatusCodeCaseForWorkflowInstanceConverter.cs @@ -1,6 +1,5 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Http.Models; namespace Elsa.Http.Serialization; diff --git a/src/modules/Elsa.Http/Services/CachingHttpWorkflowLookupService.cs b/src/modules/Elsa.Http/Services/CachingHttpWorkflowLookupService.cs index 25169a64b..dc0052fac 100644 --- a/src/modules/Elsa.Http/Services/CachingHttpWorkflowLookupService.cs +++ b/src/modules/Elsa.Http/Services/CachingHttpWorkflowLookupService.cs @@ -1,5 +1,4 @@ -using Elsa.Http.Contracts; -using Elsa.Http.Models; +using Elsa.Common.Multitenancy; using JetBrains.Annotations; using Microsoft.Extensions.Caching.Memory; @@ -11,12 +10,16 @@ namespace Elsa.Http.Services; [UsedImplicitly] public class CachingHttpWorkflowLookupService( IHttpWorkflowLookupService decoratedService, - IHttpWorkflowsCacheManager cacheManager) : IHttpWorkflowLookupService + IHttpWorkflowsCacheManager cacheManager, + ITenantAccessor tenantAccessor) : IHttpWorkflowLookupService { /// public async Task FindWorkflowAsync(string bookmarkHash, CancellationToken cancellationToken = default) { - var key = $"http-workflow:{bookmarkHash}"; + var tenant = tenantAccessor.CurrentTenant; + var tenantId = tenant?.Id; + var tenantIdPrefix = !string.IsNullOrEmpty(tenantId) ? $"{tenantId}:" : string.Empty; + var key = $"{tenantIdPrefix}http-workflow:{bookmarkHash}"; var cache = cacheManager.Cache; return await cache.GetOrCreateAsync(key, async entry => { diff --git a/src/modules/Elsa.Http/Services/DefaultAbsoluteUrlProvider.cs b/src/modules/Elsa.Http/Services/DefaultAbsoluteUrlProvider.cs index ddc8c9568..356c786fd 100644 --- a/src/modules/Elsa.Http/Services/DefaultAbsoluteUrlProvider.cs +++ b/src/modules/Elsa.Http/Services/DefaultAbsoluteUrlProvider.cs @@ -1,4 +1,3 @@ -using Elsa.Http.Contracts; using Elsa.Http.Options; using Microsoft.Extensions.Options; diff --git a/src/modules/Elsa.Http/Services/DefaultDownloadableManager.cs b/src/modules/Elsa.Http/Services/DefaultDownloadableManager.cs index dcd954a72..ee7b6406c 100644 --- a/src/modules/Elsa.Http/Services/DefaultDownloadableManager.cs +++ b/src/modules/Elsa.Http/Services/DefaultDownloadableManager.cs @@ -1,6 +1,4 @@ using Elsa.Http.Contexts; -using Elsa.Http.Contracts; -using Elsa.Http.Models; using Elsa.Http.Options; namespace Elsa.Http.Services; diff --git a/src/modules/Elsa.Http/Services/DefaultHttpEndpointRoutesProvider.cs b/src/modules/Elsa.Http/Services/DefaultHttpEndpointRoutesProvider.cs new file mode 100644 index 000000000..8669d089d --- /dev/null +++ b/src/modules/Elsa.Http/Services/DefaultHttpEndpointRoutesProvider.cs @@ -0,0 +1,36 @@ +using Elsa.Extensions; +using Elsa.Http.Contexts; +using Elsa.Http.Options; +using JetBrains.Annotations; +using Microsoft.Extensions.Options; + +namespace Elsa.Http.Services; + +/// +/// Provides a route for an HTTP endpoint based on the specified context. +/// +[UsedImplicitly] +public class DefaultHttpEndpointRoutesProvider(IOptions options) : IHttpEndpointRoutesProvider +{ + public Task> GetRoutesAsync(HttpEndpointRouteProviderContext context) + { + var routes = GetRoutes(context); + return Task.FromResult(routes); + } + + private IEnumerable GetRoutes(HttpEndpointRouteProviderContext context) + { + var routes = new List(); + var path = context.Payload.Path; + + if (string.IsNullOrWhiteSpace(path)) + return routes; + + var routeData = new HttpRouteData(new[] + { + options.Value.BasePath.ToString(), path + }.JoinSegments()); + routes.Add(routeData); + return routes; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Services/DefaultRouteTableUpdater.cs b/src/modules/Elsa.Http/Services/DefaultRouteTableUpdater.cs index 459cc8f57..97cc16e23 100644 --- a/src/modules/Elsa.Http/Services/DefaultRouteTableUpdater.cs +++ b/src/modules/Elsa.Http/Services/DefaultRouteTableUpdater.cs @@ -1,38 +1,116 @@ using Elsa.Extensions; -using Elsa.Http.Contracts; +using Elsa.Http.Bookmarks; +using Elsa.Http.Contexts; +using Elsa.Http.Options; +using Elsa.Workflows; using Elsa.Workflows.Helpers; +using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; +using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; +using Microsoft.Extensions.Options; namespace Elsa.Http.Services; /// -public class DefaultRouteTableUpdater : IRouteTableUpdater +public class DefaultRouteTableUpdater( + IRouteTable routeTable, + ITriggerStore triggerStore, + IBookmarkStore bookmarkStore, + IHttpEndpointRoutesProvider httpEndpointRoutesProvider, + IOptions options) + : IRouteTableUpdater { - private readonly IRouteTable _routeTable; - private readonly ITriggerStore _triggerStore; - private readonly IBookmarkStore _bookmarkStore; - - /// - /// Initializes a new instance of the class. - /// - public DefaultRouteTableUpdater(IRouteTable routeTable, ITriggerStore triggerStore, IBookmarkStore bookmarkStore) - { - _routeTable = routeTable; - _triggerStore = triggerStore; - _bookmarkStore = bookmarkStore; - } - /// public async Task UpdateAsync(CancellationToken cancellationToken = default) { var bookmarkName = ActivityTypeNameHelper.GenerateTypeName(); - var triggerFilter = new TriggerFilter { Name = bookmarkName }; - var bookmarkFilter = new BookmarkFilter { ActivityTypeName = bookmarkName}; - var triggers = (await _triggerStore.FindManyAsync(triggerFilter, cancellationToken)).ToList(); - var bookmarks = (await _bookmarkStore.FindManyAsync(bookmarkFilter, cancellationToken)).ToList(); + var triggerFilter = new TriggerFilter + { + Name = bookmarkName, + TenantAgnostic = true + }; + var bookmarkFilter = new BookmarkFilter + { + ActivityTypeName = bookmarkName, + TenantAgnostic = true + }; + var triggers = (await triggerStore.FindManyAsync(triggerFilter, cancellationToken)).ToList(); + var bookmarks = (await bookmarkStore.FindManyAsync(bookmarkFilter, cancellationToken)).ToList(); - _routeTable.AddRoutes(triggers); - _routeTable.AddRoutes(bookmarks); + await AddRoutesAsync(triggers, cancellationToken); + await AddRoutesAsync(bookmarks, cancellationToken); + } + + public async Task AddRoutesAsync(IEnumerable triggers, CancellationToken cancellationToken = default) + { + var httpEndpointTriggers = Filter(triggers).ToList(); + + foreach (var trigger in httpEndpointTriggers) + { + var payload = trigger.GetPayload(); + await AddRoutesAsync(payload, trigger.TenantId, cancellationToken); + } + } + + public async Task AddRoutesAsync(IEnumerable bookmarks, CancellationToken cancellationToken = default) + { + var httpEndpointBookmarks = Filter(bookmarks).ToList(); + + foreach (var bookmark in httpEndpointBookmarks) + { + var payload = bookmark.GetPayload(); + await AddRoutesAsync(payload, bookmark.TenantId, cancellationToken); + } + } + + public async Task AddRoutesAsync(IEnumerable bookmarks, WorkflowExecutionContext workflowExecutionContext, CancellationToken cancellationToken = default) + { + var httpEndpointBookmarks = Filter(bookmarks).ToList(); + + foreach (var bookmark in httpEndpointBookmarks) + { + var payload = bookmark.GetPayload(); + await AddRoutesAsync(payload, workflowExecutionContext.Workflow.Identity.TenantId, cancellationToken); + } + } + + public void RemoveRoutes(IEnumerable triggers) + { + var paths = Filter(triggers).Select(x => x.GetPayload().Path).ToList(); + routeTable.RemoveRange(paths); + } + + public void RemoveRoutes(IEnumerable bookmarks) + { + var paths = Filter(bookmarks).Select(x => x.GetPayload().Path).ToList(); + routeTable.RemoveRange(paths); + } + + private async Task AddRoutesAsync(HttpEndpointBookmarkPayload payload, string? tenantId, CancellationToken cancellationToken) + { + var context = new HttpEndpointRouteProviderContext(payload, tenantId, cancellationToken); + var routes = await httpEndpointRoutesProvider.GetRoutesAsync(context); + + foreach (var route in routes) + routeTable.Add(route); + } + + private static IEnumerable Filter(IEnumerable triggers) + { + var triggerName = ActivityTypeNameHelper.GenerateTypeName(); + return triggers.Where(x => x.Name == triggerName && x.Payload != null); + } + + private static IEnumerable Filter(IEnumerable bookmarks) + { + var activityTypeName = ActivityTypeNameHelper.GenerateTypeName(); + return bookmarks.Where(x => x.ActivityTypeName == activityTypeName && x.Payload != null); + } + + private static IEnumerable Filter(IEnumerable bookmarks) + { + var bookmarkName = ActivityTypeNameHelper.GenerateTypeName(); + return bookmarks.Where(x => x.Name == bookmarkName && x.Payload != null); } } \ No newline at end of file diff --git a/src/modules/Elsa.Http/Services/HttpClientFileDownloader.cs b/src/modules/Elsa.Http/Services/HttpClientFileDownloader.cs index d1950d65c..1b28a0166 100644 --- a/src/modules/Elsa.Http/Services/HttpClientFileDownloader.cs +++ b/src/modules/Elsa.Http/Services/HttpClientFileDownloader.cs @@ -1,4 +1,3 @@ -using Elsa.Http.Contracts; using Elsa.Http.Options; namespace Elsa.Http.Services; diff --git a/src/modules/Elsa.Http/Services/HttpWorkflowLookupService.cs b/src/modules/Elsa.Http/Services/HttpWorkflowLookupService.cs index 9f0473722..1ef3e72e7 100644 --- a/src/modules/Elsa.Http/Services/HttpWorkflowLookupService.cs +++ b/src/modules/Elsa.Http/Services/HttpWorkflowLookupService.cs @@ -1,7 +1,4 @@ -using Elsa.Http.Contracts; -using Elsa.Http.Models; using Elsa.Workflows.Management; -using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; @@ -39,8 +36,7 @@ public class HttpWorkflowLookupService(ITriggerStore triggerStore, IWorkflowDefi { var triggerFilter = new TriggerFilter { - Hash = bookmarkHash, - TenantAgnostic = true + Hash = bookmarkHash }; return await triggerStore.FindManyAsync(triggerFilter, cancellationToken); } @@ -50,8 +46,7 @@ public class HttpWorkflowLookupService(ITriggerStore triggerStore, IWorkflowDefi var workflowDefinitionVersionId = trigger.WorkflowDefinitionVersionId; var filter = new WorkflowDefinitionFilter { - Id = workflowDefinitionVersionId, - TenantAgnostic = true + Id = workflowDefinitionVersionId }; return await workflowDefinitionService.FindWorkflowGraphAsync(filter, cancellationToken); } diff --git a/src/modules/Elsa.Http/Services/HttpWorkflowsCacheManager.cs b/src/modules/Elsa.Http/Services/HttpWorkflowsCacheManager.cs index 0da46b6ba..01629ddc7 100644 --- a/src/modules/Elsa.Http/Services/HttpWorkflowsCacheManager.cs +++ b/src/modules/Elsa.Http/Services/HttpWorkflowsCacheManager.cs @@ -1,6 +1,5 @@ using Elsa.Caching; using Elsa.Http.Bookmarks; -using Elsa.Http.Contracts; using Elsa.Workflows; using Elsa.Workflows.Helpers; diff --git a/src/modules/Elsa.Http/Services/RouteMatcher.cs b/src/modules/Elsa.Http/Services/RouteMatcher.cs index c01fb6aa8..f89326283 100644 --- a/src/modules/Elsa.Http/Services/RouteMatcher.cs +++ b/src/modules/Elsa.Http/Services/RouteMatcher.cs @@ -1,7 +1,6 @@ // Taken & adapted from https://github.com/markvincze/Stubbery/blob/main/src/Stubbery/RequestMatching/RouteMatcher.cs using Elsa.Extensions; -using Elsa.Http.Contracts; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing.Template; diff --git a/src/modules/Elsa.Http/Services/RouteTable.cs b/src/modules/Elsa.Http/Services/RouteTable.cs index 3f0e94e0c..aef62d131 100644 --- a/src/modules/Elsa.Http/Services/RouteTable.cs +++ b/src/modules/Elsa.Http/Services/RouteTable.cs @@ -1,7 +1,6 @@ using System.Collections; using System.Collections.Concurrent; using Elsa.Extensions; -using Elsa.Http.Contracts; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; @@ -23,11 +22,18 @@ public class RouteTable : IRouteTable _logger = logger; } - private ConcurrentDictionary Routes => _cache.GetOrCreate(Key, _ => new ConcurrentDictionary())!; + private ConcurrentDictionary Routes => _cache.GetOrCreate(Key, _ => new ConcurrentDictionary())!; /// public void Add(string route) { + Add(new HttpRouteData(route)); + } + + /// + public void Add(HttpRouteData httpRouteData) + { + var route = httpRouteData.Route; if (route.Contains("//")) { _logger.LogWarning("Path cannot contain double slashes. Ignoring path: {Path}", route); @@ -35,7 +41,7 @@ public class RouteTable : IRouteTable } var normalizedRoute = route.NormalizeRoute(); - Routes.TryAdd(normalizedRoute, normalizedRoute); + Routes.TryAdd(normalizedRoute, httpRouteData); } /// @@ -58,7 +64,7 @@ public class RouteTable : IRouteTable } /// - public IEnumerator GetEnumerator() => Routes.Values.GetEnumerator(); + public IEnumerator GetEnumerator() => Routes.Values.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } \ No newline at end of file diff --git a/src/modules/Elsa.Http/Services/ZipManager.cs b/src/modules/Elsa.Http/Services/ZipManager.cs index 2af5f2787..d3c9d41b2 100644 --- a/src/modules/Elsa.Http/Services/ZipManager.cs +++ b/src/modules/Elsa.Http/Services/ZipManager.cs @@ -1,7 +1,5 @@ using System.IO.Compression; using Elsa.Common; -using Elsa.Http.Contracts; -using Elsa.Http.Models; using Elsa.Http.Options; using FluentStorage.Blobs; using Microsoft.Extensions.Logging; diff --git a/src/modules/Elsa.JavaScript/Endpoints/TypeDefinitions/Endpoint.cs b/src/modules/Elsa.JavaScript/Endpoints/TypeDefinitions/Endpoint.cs index dcaef7c5a..1e07af1be 100644 --- a/src/modules/Elsa.JavaScript/Endpoints/TypeDefinitions/Endpoint.cs +++ b/src/modules/Elsa.JavaScript/Endpoints/TypeDefinitions/Endpoint.cs @@ -4,7 +4,6 @@ using Elsa.Common.Models; using Elsa.JavaScript.TypeDefinitions.Contracts; using Elsa.JavaScript.TypeDefinitions.Models; using Elsa.Workflows.Management; -using Elsa.Workflows.Management.Contracts; using Elsa.Workflows.Models; using JetBrains.Annotations; diff --git a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs index 621a3cb47..9f134433f 100644 --- a/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs +++ b/src/modules/Elsa.JavaScript/Handlers/ConfigureEngineWithVariables.cs @@ -2,7 +2,6 @@ using System.Dynamic; using Elsa.Expressions.Models; using Elsa.Extensions; using Elsa.JavaScript.Helpers; -using Elsa.JavaScript.Models; using Elsa.JavaScript.Notifications; using Elsa.Mediator.Contracts; using Elsa.Workflows.Activities; diff --git a/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs b/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs index cee375298..29d50ed1e 100644 --- a/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/Providers/InputFunctionsDefinitionProvider.cs @@ -2,7 +2,6 @@ using Elsa.JavaScript.Contracts; using Elsa.JavaScript.TypeDefinitions.Abstractions; using Elsa.JavaScript.TypeDefinitions.Models; using Elsa.Workflows.Activities; -using Elsa.Workflows.Management; using Humanizer; using JetBrains.Annotations; diff --git a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs b/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs index e33a2267f..59e809cff 100644 --- a/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs +++ b/src/modules/Elsa.JavaScript/TypeDefinitions/Providers/WorkflowVariablesTypeDefinitionProvider.cs @@ -1,6 +1,5 @@ using Elsa.Extensions; using Elsa.JavaScript.TypeDefinitions.Abstractions; -using Elsa.JavaScript.TypeDefinitions.Contracts; using Elsa.JavaScript.TypeDefinitions.Models; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Liquid/Extensions/TemplateContextExtensions.cs b/src/modules/Elsa.Liquid/Extensions/TemplateContextExtensions.cs index d45f3e63a..2a25a11ad 100644 --- a/src/modules/Elsa.Liquid/Extensions/TemplateContextExtensions.cs +++ b/src/modules/Elsa.Liquid/Extensions/TemplateContextExtensions.cs @@ -1,7 +1,6 @@ using Elsa.Liquid.Contracts; using Elsa.Liquid.Options; using Fluid; -using Fluid.Filters; using Microsoft.Extensions.DependencyInjection; // ReSharper disable once CheckNamespace diff --git a/src/modules/Elsa.MongoDb/Modules/Alterations/AlterationPlanStore.cs b/src/modules/Elsa.MongoDb/Modules/Alterations/AlterationPlanStore.cs index 76de65739..a0ddb98af 100644 --- a/src/modules/Elsa.MongoDb/Modules/Alterations/AlterationPlanStore.cs +++ b/src/modules/Elsa.MongoDb/Modules/Alterations/AlterationPlanStore.cs @@ -4,7 +4,6 @@ using Elsa.Alterations.Core.Filters; using Elsa.MongoDb.Common; using Elsa.MongoDb.Modules.Alterations.Documents; using Microsoft.Extensions.DependencyInjection; -using MongoDB.Driver; using MongoDB.Driver.Linq; namespace Elsa.MongoDb.Modules.Alterations; diff --git a/src/modules/Elsa.MongoDb/Modules/Runtime/ActivityExecutionLogStore.cs b/src/modules/Elsa.MongoDb/Modules/Runtime/ActivityExecutionLogStore.cs index a4b28939b..2e95ad1ba 100644 --- a/src/modules/Elsa.MongoDb/Modules/Runtime/ActivityExecutionLogStore.cs +++ b/src/modules/Elsa.MongoDb/Modules/Runtime/ActivityExecutionLogStore.cs @@ -3,7 +3,6 @@ using Elsa.Extensions; using Elsa.MongoDb.Common; using Elsa.MongoDb.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.OrderDefinitions; diff --git a/src/modules/Elsa.MongoDb/Modules/Runtime/BookmarkStore.cs b/src/modules/Elsa.MongoDb/Modules/Runtime/BookmarkStore.cs index 634449e18..ca4b8805a 100644 --- a/src/modules/Elsa.MongoDb/Modules/Runtime/BookmarkStore.cs +++ b/src/modules/Elsa.MongoDb/Modules/Runtime/BookmarkStore.cs @@ -1,6 +1,5 @@ using Elsa.MongoDb.Common; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; diff --git a/src/modules/Elsa.MongoDb/Modules/Runtime/TriggerStore.cs b/src/modules/Elsa.MongoDb/Modules/Runtime/TriggerStore.cs index 107965186..a75a71d75 100644 --- a/src/modules/Elsa.MongoDb/Modules/Runtime/TriggerStore.cs +++ b/src/modules/Elsa.MongoDb/Modules/Runtime/TriggerStore.cs @@ -1,6 +1,5 @@ using Elsa.MongoDb.Common; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; diff --git a/src/modules/Elsa.MongoDb/Modules/Runtime/WorkflowExecutionLogStore.cs b/src/modules/Elsa.MongoDb/Modules/Runtime/WorkflowExecutionLogStore.cs index 773dfd1fc..d62f0f401 100644 --- a/src/modules/Elsa.MongoDb/Modules/Runtime/WorkflowExecutionLogStore.cs +++ b/src/modules/Elsa.MongoDb/Modules/Runtime/WorkflowExecutionLogStore.cs @@ -2,7 +2,6 @@ using Elsa.Common.Models; using Elsa.Extensions; using Elsa.MongoDb.Common; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.OrderDefinitions; diff --git a/src/modules/Elsa.OrchardCore/Activities/PatchContentItem.cs b/src/modules/Elsa.OrchardCore/Activities/PatchContentItem.cs index 3dbab5205..968ef61c9 100644 --- a/src/modules/Elsa.OrchardCore/Activities/PatchContentItem.cs +++ b/src/modules/Elsa.OrchardCore/Activities/PatchContentItem.cs @@ -1,5 +1,4 @@ using System.Text.Json.Nodes; -using Elsa.Expressions.Helpers; using Elsa.Extensions; using Elsa.OrchardCore.Client; using Elsa.Workflows; diff --git a/src/modules/Elsa.OrchardCore/Activities/ResolveTags.cs b/src/modules/Elsa.OrchardCore/Activities/ResolveTags.cs index bdfae9615..4f4a9d351 100644 --- a/src/modules/Elsa.OrchardCore/Activities/ResolveTags.cs +++ b/src/modules/Elsa.OrchardCore/Activities/ResolveTags.cs @@ -1,5 +1,4 @@ using System.Text.Json.Nodes; -using Elsa.Expressions.Helpers; using Elsa.Extensions; using Elsa.OrchardCore.Client; using Elsa.Workflows; diff --git a/src/modules/Elsa.OrchardCore/Activities/UploadMedia.cs b/src/modules/Elsa.OrchardCore/Activities/UploadMedia.cs index 6e777b716..0a1dbaf30 100644 --- a/src/modules/Elsa.OrchardCore/Activities/UploadMedia.cs +++ b/src/modules/Elsa.OrchardCore/Activities/UploadMedia.cs @@ -1,6 +1,6 @@ using System.Text.Json.Nodes; using Elsa.Extensions; -using Elsa.Http.Models; +using Elsa.Http; using Elsa.OrchardCore.Client; using Elsa.Workflows; using Elsa.Workflows.Attributes; diff --git a/src/modules/Elsa.OrchardCore/Client/Contracts/IRestApiClient.cs b/src/modules/Elsa.OrchardCore/Client/Contracts/IRestApiClient.cs index adc349667..828e46551 100644 --- a/src/modules/Elsa.OrchardCore/Client/Contracts/IRestApiClient.cs +++ b/src/modules/Elsa.OrchardCore/Client/Contracts/IRestApiClient.cs @@ -1,5 +1,5 @@ using System.Text.Json.Nodes; -using Elsa.Http.Models; +using Elsa.Http; namespace Elsa.OrchardCore.Client; diff --git a/src/modules/Elsa.OrchardCore/Client/Services/DefaultRestApiClient.cs b/src/modules/Elsa.OrchardCore/Client/Services/DefaultRestApiClient.cs index 54265f3bb..f01abbd0d 100644 --- a/src/modules/Elsa.OrchardCore/Client/Services/DefaultRestApiClient.cs +++ b/src/modules/Elsa.OrchardCore/Client/Services/DefaultRestApiClient.cs @@ -1,7 +1,7 @@ using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Nodes; -using Elsa.Http.Models; +using Elsa.Http; namespace Elsa.OrchardCore.Client; diff --git a/src/modules/Elsa.Quartz/Jobs/RunWorkflowJob.cs b/src/modules/Elsa.Quartz/Jobs/RunWorkflowJob.cs index 785cb0a6b..055e4ca5b 100644 --- a/src/modules/Elsa.Quartz/Jobs/RunWorkflowJob.cs +++ b/src/modules/Elsa.Quartz/Jobs/RunWorkflowJob.cs @@ -3,7 +3,6 @@ using Elsa.Scheduling; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Messages; -using Elsa.Workflows.Runtime.Requests; using Quartz; namespace Elsa.Quartz.Jobs; diff --git a/src/modules/Elsa.Scheduling/Handlers/ScheduleWorkflows.cs b/src/modules/Elsa.Scheduling/Handlers/ScheduleWorkflows.cs index e767ced65..bb792ceee 100644 --- a/src/modules/Elsa.Scheduling/Handlers/ScheduleWorkflows.cs +++ b/src/modules/Elsa.Scheduling/Handlers/ScheduleWorkflows.cs @@ -34,7 +34,7 @@ public class ScheduleWorkflows : INotificationHandler, /// public async Task HandleAsync(WorkflowBookmarksIndexed notification, CancellationToken cancellationToken) { - var workflowInstanceId = notification.IndexedWorkflowBookmarks.InstanceId; + var workflowInstanceId = notification.IndexedWorkflowBookmarks.WorkflowExecutionContext.Id; await _bookmarkScheduler.UnscheduleAsync(notification.IndexedWorkflowBookmarks.RemovedBookmarks, cancellationToken); await _bookmarkScheduler.ScheduleAsync(workflowInstanceId, notification.IndexedWorkflowBookmarks.AddedBookmarks, cancellationToken); } diff --git a/src/modules/Elsa.Scheduling/Services/DefaultTriggerScheduler.cs b/src/modules/Elsa.Scheduling/Services/DefaultTriggerScheduler.cs index a384a010c..31165173a 100644 --- a/src/modules/Elsa.Scheduling/Services/DefaultTriggerScheduler.cs +++ b/src/modules/Elsa.Scheduling/Services/DefaultTriggerScheduler.cs @@ -1,5 +1,4 @@ using Elsa.Common; -using Elsa.Common.Models; using Elsa.Extensions; using Elsa.Scheduling.Activities; using Elsa.Scheduling.Bookmarks; diff --git a/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.PostgreSql/DbContextFactories.cs b/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.PostgreSql/DbContextFactories.cs index 0af2b22dc..8b4131bf0 100644 --- a/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.PostgreSql/DbContextFactories.cs +++ b/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.PostgreSql/DbContextFactories.cs @@ -1,10 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Abstractions; -using Elsa.EntityFrameworkCore.Extensions; -using Elsa.EntityFrameworkCore.Modules.Alterations; -using Elsa.EntityFrameworkCore.Modules.Identity; -using Elsa.EntityFrameworkCore.Modules.Labels; -using Elsa.EntityFrameworkCore.Modules.Management; -using Elsa.EntityFrameworkCore.Modules.Runtime; +using Elsa.EntityFrameworkCore.Extensions; using Elsa.EntityFrameworkCore.PostgreSql; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; diff --git a/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.SqlServer/DbContextFactories.cs b/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.SqlServer/DbContextFactories.cs index 410b2a4b6..c3ed1b2e6 100644 --- a/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.SqlServer/DbContextFactories.cs +++ b/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore.SqlServer/DbContextFactories.cs @@ -1,10 +1,4 @@ -using Elsa.EntityFrameworkCore.Common.Abstractions; -using Elsa.EntityFrameworkCore.Extensions; -using Elsa.EntityFrameworkCore.Modules.Alterations; -using Elsa.EntityFrameworkCore.Modules.Identity; -using Elsa.EntityFrameworkCore.Modules.Labels; -using Elsa.EntityFrameworkCore.Modules.Management; -using Elsa.EntityFrameworkCore.Modules.Runtime; +using Elsa.EntityFrameworkCore.Extensions; using Elsa.EntityFrameworkCore.SqlServer; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; diff --git a/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore/Feature.cs b/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore/Feature.cs index 1c293b1c6..b49d25051 100644 --- a/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore/Feature.cs +++ b/src/modules/Elsa.Secrets.Persistence.EntityFrameworkCore/Feature.cs @@ -1,5 +1,4 @@ using Elsa.EntityFrameworkCore.Common; -using Elsa.EntityFrameworkCore.Common.Contracts; using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Secrets.Management; diff --git a/src/modules/Elsa.Secrets.Scripting/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Secrets.Scripting/Extensions/ModuleExtensions.cs index 24209acf0..b6a7c9eb9 100644 --- a/src/modules/Elsa.Secrets.Scripting/Extensions/ModuleExtensions.cs +++ b/src/modules/Elsa.Secrets.Scripting/Extensions/ModuleExtensions.cs @@ -1,5 +1,4 @@ using Elsa.Features.Services; -using Elsa.Secrets.Management.Features; using Elsa.Secrets.Scripting.Features; // ReSharper disable once CheckNamespace diff --git a/src/modules/Elsa.Telnyx/Activities/GatherUsingAudio.cs b/src/modules/Elsa.Telnyx/Activities/GatherUsingAudio.cs index 7f479312e..082ac0dcd 100644 --- a/src/modules/Elsa.Telnyx/Activities/GatherUsingAudio.cs +++ b/src/modules/Elsa.Telnyx/Activities/GatherUsingAudio.cs @@ -11,7 +11,6 @@ using Elsa.Workflows.Activities.Flowchart.Attributes; using Elsa.Workflows.Attributes; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Refit; namespace Elsa.Telnyx.Activities; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerAnswerCallActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerAnswerCallActivities.cs index 2d31050c2..e9fb6d731 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerAnswerCallActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerAnswerCallActivities.cs @@ -7,7 +7,6 @@ using Elsa.Telnyx.Extensions; using Elsa.Telnyx.Payloads.Call; using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; using Microsoft.Extensions.Logging; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerCallAnsweredActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerCallAnsweredActivities.cs index 0b1afc212..318832ce4 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerCallAnsweredActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerCallAnsweredActivities.cs @@ -5,9 +5,7 @@ using Elsa.Telnyx.Bookmarks; using Elsa.Telnyx.Events; using Elsa.Telnyx.Extensions; using Elsa.Telnyx.Payloads.Call; -using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; using Microsoft.Extensions.Logging; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerCallBridgedActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerCallBridgedActivities.cs index 2bbc3c360..b209d188f 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerCallBridgedActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerCallBridgedActivities.cs @@ -7,9 +7,7 @@ using Elsa.Telnyx.Extensions; using Elsa.Telnyx.Payloads.Call; using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; -using Microsoft.Extensions.Logging; namespace Elsa.Telnyx.Handlers; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerCallHangupActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerCallHangupActivities.cs index 1653fe6d5..c2eb0ebc2 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerCallHangupActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerCallHangupActivities.cs @@ -5,11 +5,8 @@ using Elsa.Telnyx.Bookmarks; using Elsa.Telnyx.Events; using Elsa.Telnyx.Extensions; using Elsa.Telnyx.Payloads.Call; -using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; -using Microsoft.Extensions.Logging; namespace Elsa.Telnyx.Handlers; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerIncomingCallActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerIncomingCallActivities.cs index f9d792ad2..51f3f6b1a 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerIncomingCallActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerIncomingCallActivities.cs @@ -4,11 +4,8 @@ using Elsa.Telnyx.Activities; using Elsa.Telnyx.Bookmarks; using Elsa.Telnyx.Events; using Elsa.Telnyx.Payloads.Call; -using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; -using Microsoft.Extensions.Logging; namespace Elsa.Telnyx.Handlers; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookActivities.cs index 8832b269f..9b07c185c 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookActivities.cs @@ -8,9 +8,7 @@ using Elsa.Telnyx.Events; using Elsa.Telnyx.Extensions; using Elsa.Telnyx.Payloads.Abstractions; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; -using Microsoft.Extensions.Logging; namespace Elsa.Telnyx.Handlers; diff --git a/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookDrivenActivities.cs b/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookDrivenActivities.cs index e385daf30..9fa0fdd01 100644 --- a/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookDrivenActivities.cs +++ b/src/modules/Elsa.Telnyx/Handlers/TriggerWebhookDrivenActivities.cs @@ -8,7 +8,6 @@ using Elsa.Telnyx.Payloads.Abstractions; using Elsa.Workflows; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; namespace Elsa.Telnyx.Handlers; diff --git a/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj b/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj index 1de27c514..f0f59dbbe 100644 --- a/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj +++ b/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj @@ -12,6 +12,7 @@ + diff --git a/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj.DotSettings b/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj.DotSettings new file mode 100644 index 000000000..6c3ec7879 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Extensions/ModuleExtensions.cs b/src/modules/Elsa.Tenants.AspNetCore/Extensions/ModuleExtensions.cs new file mode 100644 index 000000000..a098277e0 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Extensions/ModuleExtensions.cs @@ -0,0 +1,21 @@ +using Elsa.Features.Services; +using Elsa.Tenants.AspNetCore.Features; +using Elsa.Tenants.Features; + +// ReSharper disable once CheckNamespace +namespace Elsa.Tenants.Extensions; + +/// +/// Extensions for that installs the feature. +/// +public static class ModuleExtensions +{ + /// + /// Installs and configures the feature. + /// + public static IModule UseTenantHttpRouting(this IModule module, Action? configure = default) + { + module.Configure(configure); + return module; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Extensions/TenantExtensions.cs b/src/modules/Elsa.Tenants.AspNetCore/Extensions/TenantExtensions.cs new file mode 100644 index 000000000..4ae71b497 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Extensions/TenantExtensions.cs @@ -0,0 +1,16 @@ +using Elsa.Common.Multitenancy; + +namespace Elsa.Tenants.AspNetCore; + +public static class TenantExtensions +{ + public static string? GetRoutePrefix(this Tenant tenant) + { + return tenant.Configuration.GetSection("Http")["Prefix"]; + } + + public static string? GetHost(this Tenant tenant) + { + return tenant.Configuration.GetSection("Http")["Host"]; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs b/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs new file mode 100644 index 000000000..5f43ebb2a --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs @@ -0,0 +1,33 @@ +using Elsa.Common.Multitenancy; +using Elsa.Features.Abstractions; +using Elsa.Features.Attributes; +using Elsa.Features.Services; +using Elsa.Http.Features; +using Elsa.Tenants.AspNetCore.Services; +using Elsa.Tenants.Features; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Tenants.AspNetCore.Features; + +[DependencyOf(typeof(HttpFeature))] +[DependencyOf(typeof(TenantsFeature))] +public class MultitenantHttpRoutingFeature(IModule module) : FeatureBase(module) +{ + public override void Configure() + { + Module.Configure(feature => + { + feature.WithHttpEndpointRoutesProvider(); + }); + } + + public override void Apply() + { + // Tenant resolvers. + Services + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Middleware/TenantResolutionMiddleware.cs b/src/modules/Elsa.Tenants.AspNetCore/Middleware/TenantResolutionMiddleware.cs index da12aad0c..27ed2e169 100644 --- a/src/modules/Elsa.Tenants.AspNetCore/Middleware/TenantResolutionMiddleware.cs +++ b/src/modules/Elsa.Tenants.AspNetCore/Middleware/TenantResolutionMiddleware.cs @@ -19,7 +19,24 @@ public class TenantResolutionMiddleware(RequestDelegate next, ITenantScopeFactor { var tenant = await tenantResolverPipelineInvoker.InvokePipelineAsync(); - using (tenantScopeFactory.CreateScope(tenant)) + if (tenant != null) + { + var tenantPrefix = tenant.GetRoutePrefix(); + + if (!string.IsNullOrWhiteSpace(tenantPrefix)) + { + var tenantPath = $"/{tenantPrefix}"; + if (context.Request.Path.StartsWithSegments(tenantPath)) + { + context.Request.PathBase = tenantPath; + context.Request.Path = context.Request.Path.Value![tenantPath.Length..]; + } + } + } + + using (tenantScopeFactory.CreateScope(tenant)) + { await next(context); + } } } \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HeaderTenantResolver.cs b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HeaderTenantResolver.cs new file mode 100644 index 000000000..06d36e387 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HeaderTenantResolver.cs @@ -0,0 +1,22 @@ +using Elsa.Common.Multitenancy; +using Microsoft.AspNetCore.Http; + +namespace Elsa.Tenants.AspNetCore; + +/// +/// Resolves the tenant based on the header in the request. +/// +public class HeaderTenantResolver(IHttpContextAccessor httpContextAccessor) : TenantResolverBase +{ + protected override TenantResolverResult Resolve(TenantResolverContext context) + { + var httpContext = httpContextAccessor.HttpContext; + + if (httpContext == null) + return Unresolved(); + + var tenantId = httpContext.Request.Headers["X-Tenant-Id"].FirstOrDefault(); + + return AutoResolve(tenantId); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HostTenantResolver.cs b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HostTenantResolver.cs new file mode 100644 index 000000000..e1053e44b --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HostTenantResolver.cs @@ -0,0 +1,30 @@ +using Elsa.Common.Multitenancy; +using Microsoft.AspNetCore.Http; + +namespace Elsa.Tenants.AspNetCore; + +/// +/// Resolves the tenant based on the host in the request. +/// +public class HostTenantResolver(IHttpContextAccessor httpContextAccessor) : TenantResolverBase +{ + protected override TenantResolverResult Resolve(TenantResolverContext context) + { + var httpContext = httpContextAccessor.HttpContext; + + if (httpContext == null) + return Unresolved(); + + var host = httpContext.Request.Host; + var inboundHostAndPort = host.Host + (host.Port.HasValue ? ":" + host.Port : null); + var tenant = context.FindTenant(x => + { + var tenantHost = x.GetHost(); + return tenantHost == inboundHostAndPort; + }); + + var tenantId = tenant?.Id; + + return AutoResolve(tenantId); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Http/Multitenancy/RoutePrefixTenantResolver.cs b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/RoutePrefixTenantResolver.cs similarity index 64% rename from src/modules/Elsa.Http/Multitenancy/RoutePrefixTenantResolver.cs rename to src/modules/Elsa.Tenants.AspNetCore/Resolvers/RoutePrefixTenantResolver.cs index d3ccb49d5..a424df589 100644 --- a/src/modules/Elsa.Http/Multitenancy/RoutePrefixTenantResolver.cs +++ b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/RoutePrefixTenantResolver.cs @@ -1,11 +1,10 @@ using Elsa.Common.Multitenancy; using Elsa.Extensions; -using Elsa.Http.Contracts; +using Elsa.Http; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; -namespace Elsa.Http.Multitenancy; +namespace Elsa.Tenants.AspNetCore; /// /// Resolves the tenant based on the route prefix in the request URL. The tenant ID is expected to be part of the route. @@ -21,27 +20,32 @@ public class RoutePrefixTenantResolver(IHttpContextAccessor httpContextAccessor, return Unresolved(); var path = GetPath(httpContext); - var routeValues = GetMatchingRouteValues(path); + var routeData = GetMatchingRouteValues(path); - if (routeValues == null) + if (routeData == null) return Unresolved(); - var tenantId = routeValues["tenantId"] as string; + var routeValues = routeData.RouteValues; + var tenantPrefix = routeValues["tenantPrefix"] as string; + if (string.IsNullOrWhiteSpace(tenantPrefix)) + return Unresolved(); + + var tenantId = routeData.DataTokens["tenantId"] as string; return AutoResolve(tenantId); } private string GetPath(HttpContext httpContext) => httpContext.Request.Path.Value!.NormalizeRoute(); - private RouteValueDictionary? GetMatchingRouteValues(string path) + private HttpRouteData? GetMatchingRouteValues(string path) { var routeMatcher = serviceProvider.GetRequiredService(); var routeTable = serviceProvider.GetRequiredService(); var matchingRouteQuery = - from route in routeTable - let routeValues = routeMatcher.Match(route, path) + from routeData in routeTable + let routeValues = routeMatcher.Match(routeData.Route, path) where routeValues != null - select routeValues; + select new HttpRouteData(routeData.Route, routeData.DataTokens, routeValues); return matchingRouteQuery.FirstOrDefault(); } diff --git a/src/modules/Elsa.Tenants.AspNetCore/Services/TenantPrefixHttpEndpointRoutesProvider.cs b/src/modules/Elsa.Tenants.AspNetCore/Services/TenantPrefixHttpEndpointRoutesProvider.cs new file mode 100644 index 000000000..25c5805a1 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Services/TenantPrefixHttpEndpointRoutesProvider.cs @@ -0,0 +1,63 @@ +using Elsa.Extensions; +using Elsa.Http; +using Elsa.Http.Contexts; +using Elsa.Http.Options; +using JetBrains.Annotations; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Options; + +namespace Elsa.Tenants.AspNetCore.Services; + +/// +/// Provides a route for an HTTP endpoint based on the specified context and tenant prefix. +/// +[UsedImplicitly] +public class TenantPrefixHttpEndpointRoutesProvider(ITenantsProvider tenantsProvider, IOptions options) : IHttpEndpointRoutesProvider +{ + public async Task> GetRoutesAsync(HttpEndpointRouteProviderContext context) + { + var routes = new List(); + var path = context.Payload.Path; + + if (string.IsNullOrWhiteSpace(path)) + return routes; + + await AddTenantRouteAsync(context, routes); + AddDefaultRoute(context, routes); + return routes; + } + + private async Task AddTenantRouteAsync(HttpEndpointRouteProviderContext context, List routes) + { + var segments = new List(); + var routeDataValues = new RouteValueDictionary(); + + if (!string.IsNullOrEmpty(context.TenantId)) + { + var tenant = await tenantsProvider.FindByIdAsync(context.TenantId); + var tenantPrefix = tenant?.GetRoutePrefix(); + + if (!string.IsNullOrWhiteSpace(tenantPrefix)) + { + segments.Add("{tenantPrefix}"); + routeDataValues.Add("tenantId", tenant!.Id); + } + } + + var path = context.Payload.Path; + segments.AddRange(options.Value.BasePath.ToString(), path); + var routeData = new HttpRouteData(segments.JoinSegments(), routeDataValues); + routes.Add(routeData); + } + + private void AddDefaultRoute(HttpEndpointRouteProviderContext context, List routes) + { + var basePath = options.Value.BasePath.ToString(); + var path = context.Payload.Path; + var routeData = new HttpRouteData(new[] + { + basePath, path + }.JoinSegments()); + routes.Add(routeData); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Tenants.AspNetCore/Settings/HttpEndpointOptions.cs b/src/modules/Elsa.Tenants.AspNetCore/Settings/HttpEndpointOptions.cs new file mode 100644 index 000000000..063f646d5 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Settings/HttpEndpointOptions.cs @@ -0,0 +1,9 @@ +namespace Elsa.Tenants.AspNetCore.Settings; + +public class HttpEndpointSettings +{ + public string? Prefix { get; set; } + public string? HeaderName { get; set; } + public string? QueryStringName { get; set; } + public string? Origin { get; set; } +} \ No newline at end of file diff --git a/src/modules/Elsa.Tenants/Elsa.Tenants.csproj.DotSettings b/src/modules/Elsa.Tenants/Elsa.Tenants.csproj.DotSettings index 127787e89..4c6e2920c 100644 --- a/src/modules/Elsa.Tenants/Elsa.Tenants.csproj.DotSettings +++ b/src/modules/Elsa.Tenants/Elsa.Tenants.csproj.DotSettings @@ -1,2 +1,3 @@  - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/src/modules/Elsa.Tenants/Extensions/TenantsProviderExtensions.cs b/src/modules/Elsa.Tenants/Extensions/TenantsProviderExtensions.cs index baca3bc09..a32373237 100644 --- a/src/modules/Elsa.Tenants/Extensions/TenantsProviderExtensions.cs +++ b/src/modules/Elsa.Tenants/Extensions/TenantsProviderExtensions.cs @@ -2,7 +2,7 @@ using Elsa.Common.Multitenancy; using Elsa.Tenants.Models; using JetBrains.Annotations; -namespace Elsa.Tenants.Extensions; +namespace Elsa.Tenants; [UsedImplicitly] public static class TenantsProviderExtensions diff --git a/src/modules/Elsa.Tenants/Providers/ConfigurationTenantsProvider.cs b/src/modules/Elsa.Tenants/Providers/ConfigurationTenantsProvider.cs index 562224a3e..50ea2dff7 100644 --- a/src/modules/Elsa.Tenants/Providers/ConfigurationTenantsProvider.cs +++ b/src/modules/Elsa.Tenants/Providers/ConfigurationTenantsProvider.cs @@ -2,6 +2,7 @@ using Elsa.Common.Multitenancy; using Elsa.Tenants.Models; using Elsa.Tenants.Options; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; namespace Elsa.Tenants.Providers; @@ -11,27 +12,33 @@ namespace Elsa.Tenants.Providers; /// public class ConfigurationTenantsProvider : ITenantsProvider { - private readonly IOptions _options; + private readonly ICollection _tenants; /// /// Initializes a new instance of the class. /// - public ConfigurationTenantsProvider(IOptions options) + public ConfigurationTenantsProvider(IOptions options, IConfiguration configuration) { - _options = options; + var tenants = options.Value.Tenants.ToList(); + + // Rebind each Tenant's Configuration property manually using array indices + for (int i = 0; i < tenants.Count; i++) + tenants[i].Configuration = configuration.GetSection($"Multitenancy:Tenants:{i}:Configuration"); + + _tenants = tenants; } /// public ValueTask> ListAsync(CancellationToken cancellationToken = default) { - return new(_options.Value.Tenants.ToList()); + return new(_tenants); } /// [RequiresUnreferencedCode("The caller of this method may require dynamic access to the tenant properties.")] public ValueTask FindAsync(TenantFilter filter, CancellationToken cancellationToken = default) { - var tenantsQueryable = _options.Value.Tenants.AsQueryable(); + var tenantsQueryable = _tenants.AsQueryable(); var tenant = filter.Apply(tenantsQueryable).FirstOrDefault(); return new(tenant); } diff --git a/src/modules/Elsa.Webhooks/ActivityProviders/WebhookEventActivityProvider.cs b/src/modules/Elsa.Webhooks/ActivityProviders/WebhookEventActivityProvider.cs index 830a3bd56..d1a55d04c 100644 --- a/src/modules/Elsa.Webhooks/ActivityProviders/WebhookEventActivityProvider.cs +++ b/src/modules/Elsa.Webhooks/ActivityProviders/WebhookEventActivityProvider.cs @@ -1,7 +1,6 @@ using Elsa.Webhooks.Activities; using Elsa.Workflows; using Elsa.Workflows.Models; -using Humanizer; using WebhooksCore; namespace Elsa.Webhooks.ActivityProviders; diff --git a/src/modules/Elsa.WorkflowContexts/Activities/SetWorkflowContextParameter.cs b/src/modules/Elsa.WorkflowContexts/Activities/SetWorkflowContextParameter.cs index 00fbf01c9..f032acc36 100644 --- a/src/modules/Elsa.WorkflowContexts/Activities/SetWorkflowContextParameter.cs +++ b/src/modules/Elsa.WorkflowContexts/Activities/SetWorkflowContextParameter.cs @@ -6,7 +6,6 @@ using Elsa.Workflows; using Elsa.Workflows.Attributes; using Elsa.Workflows.Models; using JetBrains.Annotations; -using Microsoft.Extensions.DependencyInjection; namespace Elsa.WorkflowContexts.Activities; diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutionSummaries/ListSummaries/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutionSummaries/ListSummaries/Endpoint.cs index 21605a5a3..bcf78ed31 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutionSummaries/ListSummaries/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutionSummaries/ListSummaries/Endpoint.cs @@ -2,7 +2,6 @@ using Elsa.Abstractions; using Elsa.Common.Entities; using Elsa.Models; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Elsa.Workflows.Runtime.OrderDefinitions; diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs index 709e75f4b..40d13fda0 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityExecutions/Get/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/Events/TriggerPublic/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/Events/TriggerPublic/Endpoint.cs index e5ba28086..6685e7c97 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/Events/TriggerPublic/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/Events/TriggerPublic/Endpoint.cs @@ -1,5 +1,5 @@ using Elsa.Abstractions; -using Elsa.Http.Models; +using Elsa.Http; using Elsa.SasTokens.Contracts; using Elsa.Workflows.Runtime; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Refresh/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Refresh/Endpoint.cs index d6e312041..7dc056b45 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Refresh/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Refresh/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Elsa.Workflows.Runtime.Requests; using Elsa.Workflows.Runtime.Responses; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Reload/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Reload/Endpoint.cs index 2f886ca69..fafb82df9 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Reload/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/WorkflowDefinitions/Reload/Endpoint.cs @@ -1,6 +1,5 @@ using Elsa.Abstractions; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using JetBrains.Annotations; namespace Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Reload; diff --git a/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs b/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs index 28c88cfaf..1c5ed00a5 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Workflow.cs @@ -1,5 +1,4 @@ using System.ComponentModel; -using Elsa.Common.Models; using Elsa.Expressions.Models; using Elsa.Workflows.Attributes; using Elsa.Workflows.Memory; diff --git a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs index 583525e40..d796a1c18 100644 --- a/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs +++ b/src/modules/Elsa.Workflows.Core/Extensions/ExpressionExecutionContextExtensions.cs @@ -1,8 +1,6 @@ using System.Collections; -using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; -using System.Text.Unicode; using Elsa.Common; using Elsa.Expressions.Helpers; using Elsa.Expressions.Models; diff --git a/src/modules/Elsa.Workflows.Core/Models/ActivityNode.cs b/src/modules/Elsa.Workflows.Core/Models/ActivityNode.cs index 570f1b959..44e39ac00 100644 --- a/src/modules/Elsa.Workflows.Core/Models/ActivityNode.cs +++ b/src/modules/Elsa.Workflows.Core/Models/ActivityNode.cs @@ -1,5 +1,3 @@ -using System.Text.Json.Serialization; - namespace Elsa.Workflows.Models; /// diff --git a/src/modules/Elsa.Workflows.Core/Models/RunWorkflowResult.cs b/src/modules/Elsa.Workflows.Core/Models/RunWorkflowResult.cs index 476f4da52..422d6dd9a 100644 --- a/src/modules/Elsa.Workflows.Core/Models/RunWorkflowResult.cs +++ b/src/modules/Elsa.Workflows.Core/Models/RunWorkflowResult.cs @@ -1,5 +1,4 @@ using Elsa.Workflows.Activities; -using Elsa.Workflows.Helpers; using Elsa.Workflows.State; namespace Elsa.Workflows.Models; diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonActivitySerializer.cs b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonActivitySerializer.cs index f50c503f3..62f65db9a 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonActivitySerializer.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/Serializers/JsonActivitySerializer.cs @@ -1,6 +1,5 @@ using System.Text.Json; using Elsa.Common.Serialization; -using Elsa.Extensions; using Elsa.Workflows.Serialization.Converters; namespace Elsa.Workflows.Serialization.Serializers; diff --git a/src/modules/Elsa.Workflows.Management/Entities/WorkflowDefinition.cs b/src/modules/Elsa.Workflows.Management/Entities/WorkflowDefinition.cs index 9bffa0499..5c4316d70 100644 --- a/src/modules/Elsa.Workflows.Management/Entities/WorkflowDefinition.cs +++ b/src/modules/Elsa.Workflows.Management/Entities/WorkflowDefinition.cs @@ -1,5 +1,4 @@ using Elsa.Common.Entities; -using Elsa.Common.Models; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; diff --git a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs index 5458ef43a..d9be855cd 100644 --- a/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs +++ b/src/modules/Elsa.Workflows.Management/Models/WorkflowDefinitionModel.cs @@ -1,4 +1,3 @@ -using Elsa.Common.Models; using Elsa.Workflows.Models; using JetBrains.Annotations; diff --git a/src/modules/Elsa.Workflows.Management/Stores/CachingWorkflowDefinitionStore.cs b/src/modules/Elsa.Workflows.Management/Stores/CachingWorkflowDefinitionStore.cs index 4f4bbafd9..1c4c04cd1 100644 --- a/src/modules/Elsa.Workflows.Management/Stores/CachingWorkflowDefinitionStore.cs +++ b/src/modules/Elsa.Workflows.Management/Stores/CachingWorkflowDefinitionStore.cs @@ -1,5 +1,6 @@ using Elsa.Caching; using Elsa.Common.Models; +using Elsa.Common.Multitenancy; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Management.Models; @@ -10,7 +11,7 @@ namespace Elsa.Workflows.Management.Stores; /// /// A decorator for that caches workflow definitions. /// -public class CachingWorkflowDefinitionStore(IWorkflowDefinitionStore decoratedStore, ICacheManager cacheManager, IHasher hasher) : IWorkflowDefinitionStore +public class CachingWorkflowDefinitionStore(IWorkflowDefinitionStore decoratedStore, ICacheManager cacheManager, IHasher hasher, ITenantAccessor tenantAccessor) : IWorkflowDefinitionStore { private static readonly string CacheInvalidationTokenKey = typeof(CachingWorkflowDefinitionStore).FullName!; @@ -136,7 +137,9 @@ public class CachingWorkflowDefinitionStore(IWorkflowDefinitionStore decoratedSt private async Task GetOrCreateAsync(string key, Func> factory) { - var internalKey = $"{typeof(T).Name}:{key}"; + var tenantId = tenantAccessor.CurrentTenant?.Id; + var tenantIdPrefix = !string.IsNullOrEmpty(tenantId) ? $"{tenantId}:" : string.Empty; + var internalKey = $"{tenantIdPrefix}{typeof(T).Name}:{key}"; return await cacheManager.GetOrCreateAsync(internalKey, async entry => { var invalidationRequestToken = cacheManager.GetToken(CacheInvalidationTokenKey); diff --git a/src/modules/Elsa.Workflows.Runtime.ProtoActor/Mappers/Mappers.cs b/src/modules/Elsa.Workflows.Runtime.ProtoActor/Mappers/Mappers.cs index cd690a881..9117bf065 100644 --- a/src/modules/Elsa.Workflows.Runtime.ProtoActor/Mappers/Mappers.cs +++ b/src/modules/Elsa.Workflows.Runtime.ProtoActor/Mappers/Mappers.cs @@ -1,6 +1,4 @@ -using Elsa.Workflows.Runtime.ProtoActor.ProtoBuf; using Elsa.Workflows.Models; -using Elsa.Workflows.Runtime.Messages; using Elsa.Workflows.State; namespace Elsa.Workflows.Runtime.ProtoActor.Mappers; diff --git a/src/modules/Elsa.Workflows.Runtime.ProtoActor/Services/ProtoActorWorkflowRuntime.cs b/src/modules/Elsa.Workflows.Runtime.ProtoActor/Services/ProtoActorWorkflowRuntime.cs index 0d5556d70..8ba6c1bd8 100644 --- a/src/modules/Elsa.Workflows.Runtime.ProtoActor/Services/ProtoActorWorkflowRuntime.cs +++ b/src/modules/Elsa.Workflows.Runtime.ProtoActor/Services/ProtoActorWorkflowRuntime.cs @@ -1,4 +1,3 @@ -using Elsa.Workflows.Runtime; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.Runtime.ProtoActor.Services; diff --git a/src/modules/Elsa.Workflows.Runtime/Entities/ActivityExecutionRecordSummary.cs b/src/modules/Elsa.Workflows.Runtime/Entities/ActivityExecutionRecordSummary.cs index 9b13941cb..9803c5bca 100644 --- a/src/modules/Elsa.Workflows.Runtime/Entities/ActivityExecutionRecordSummary.cs +++ b/src/modules/Elsa.Workflows.Runtime/Entities/ActivityExecutionRecordSummary.cs @@ -1,6 +1,5 @@ using System.Linq.Expressions; using Elsa.Common.Entities; -using Elsa.Workflows.Management.Entities; namespace Elsa.Workflows.Runtime.Entities; diff --git a/src/modules/Elsa.Workflows.Runtime/Middleware/Workflows/PersistBookmarkMiddleware.cs b/src/modules/Elsa.Workflows.Runtime/Middleware/Workflows/PersistBookmarkMiddleware.cs index cb66198c2..0319baf07 100644 --- a/src/modules/Elsa.Workflows.Runtime/Middleware/Workflows/PersistBookmarkMiddleware.cs +++ b/src/modules/Elsa.Workflows.Runtime/Middleware/Workflows/PersistBookmarkMiddleware.cs @@ -20,7 +20,7 @@ public class PersistBookmarkMiddleware : WorkflowExecutionMiddleware public override async ValueTask InvokeAsync(WorkflowExecutionContext context) { await Next(context); - var bookmarkRequest = new UpdateBookmarksRequest(context.Id, context.BookmarksDiff, context.CorrelationId); + var bookmarkRequest = new UpdateBookmarksRequest(context, context.BookmarksDiff, context.CorrelationId); await _bookmarksPersister.PersistBookmarksAsync(bookmarkRequest); } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Notifications/IndexedWorkflowBookmarks.cs b/src/modules/Elsa.Workflows.Runtime/Notifications/IndexedWorkflowBookmarks.cs index 19969b257..500564992 100644 --- a/src/modules/Elsa.Workflows.Runtime/Notifications/IndexedWorkflowBookmarks.cs +++ b/src/modules/Elsa.Workflows.Runtime/Notifications/IndexedWorkflowBookmarks.cs @@ -10,7 +10,7 @@ namespace Elsa.Workflows.Runtime.Notifications; /// The bookmarks that were removed. /// The bookmarks that were unchanged. public record IndexedWorkflowBookmarks( - string InstanceId, + WorkflowExecutionContext WorkflowExecutionContext, ICollection AddedBookmarks, ICollection RemovedBookmarks, ICollection UnchangedBookmarks); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Requests/UpdateBookmarksRequest.cs b/src/modules/Elsa.Workflows.Runtime/Requests/UpdateBookmarksRequest.cs index 166b9b532..b6e6b145d 100644 --- a/src/modules/Elsa.Workflows.Runtime/Requests/UpdateBookmarksRequest.cs +++ b/src/modules/Elsa.Workflows.Runtime/Requests/UpdateBookmarksRequest.cs @@ -9,4 +9,4 @@ namespace Elsa.Workflows.Runtime.Requests; /// The workflow instance ID. /// A diff of the bookmarks. /// The correlation ID, if any. -public record UpdateBookmarksRequest(string WorkflowInstanceId, Diff Diff, string? CorrelationId = default); \ No newline at end of file +public record UpdateBookmarksRequest(WorkflowExecutionContext WorkflowExecutionContext, Diff Diff, string? CorrelationId = default); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Services/BookmarkPersister.cs b/src/modules/Elsa.Workflows.Runtime/Services/BookmarkPersister.cs index 630eaa645..4531843f1 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/BookmarkPersister.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/BookmarkPersister.cs @@ -11,10 +11,14 @@ public class BookmarksPersister(IBookmarkUpdater bookmarkUpdater, INotificationS public async Task PersistBookmarksAsync(UpdateBookmarksRequest updateBookmarksRequest) { await bookmarkUpdater.UpdateBookmarksAsync(updateBookmarksRequest); - + // Publish domain event. - await notificationSender.SendAsync(new WorkflowBookmarksIndexed(new IndexedWorkflowBookmarks(updateBookmarksRequest.WorkflowInstanceId, updateBookmarksRequest.Diff.Added, updateBookmarksRequest.Diff.Removed, updateBookmarksRequest.Diff.Unchanged))); - + await notificationSender.SendAsync(new WorkflowBookmarksIndexed(new IndexedWorkflowBookmarks( + updateBookmarksRequest.WorkflowExecutionContext, + updateBookmarksRequest.Diff.Added, + updateBookmarksRequest.Diff.Removed, + updateBookmarksRequest.Diff.Unchanged))); + // Publish domain event. await notificationSender.SendAsync(new WorkflowBookmarksPersisted(updateBookmarksRequest.Diff)); } diff --git a/src/modules/Elsa.Workflows.Runtime/Services/BookmarkUpdater.cs b/src/modules/Elsa.Workflows.Runtime/Services/BookmarkUpdater.cs index 2a5cd0359..d7eef18c4 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/BookmarkUpdater.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/BookmarkUpdater.cs @@ -11,7 +11,7 @@ public class BookmarkUpdater(IBookmarkManager bookmarkManager, IBookmarkStore bo /// public async Task UpdateBookmarksAsync(UpdateBookmarksRequest request, CancellationToken cancellationToken = default) { - var instanceId = request.WorkflowInstanceId; + var instanceId = request.WorkflowExecutionContext.Id; await RemoveBookmarksAsync(instanceId, request.Diff.Removed, cancellationToken); await StoreBookmarksAsync(instanceId, request.Diff.Added, request.CorrelationId, cancellationToken); } diff --git a/src/modules/Elsa.Workflows.Runtime/Stores/CachingTriggerStore.cs b/src/modules/Elsa.Workflows.Runtime/Stores/CachingTriggerStore.cs index 7dc9da643..df7649ae7 100644 --- a/src/modules/Elsa.Workflows.Runtime/Stores/CachingTriggerStore.cs +++ b/src/modules/Elsa.Workflows.Runtime/Stores/CachingTriggerStore.cs @@ -1,4 +1,5 @@ using Elsa.Caching; +using Elsa.Common.Multitenancy; using Elsa.Workflows.Runtime.Entities; using Elsa.Workflows.Runtime.Filters; using Microsoft.Extensions.Caching.Memory; @@ -8,7 +9,7 @@ namespace Elsa.Workflows.Runtime.Stores; /// /// A decorator for that caches trigger records. /// -public class CachingTriggerStore(ITriggerStore decoratedStore, ICacheManager cacheManager, IHasher hasher) : ITriggerStore +public class CachingTriggerStore(ITriggerStore decoratedStore, ICacheManager cacheManager, IHasher hasher, ITenantAccessor tenantAccessor) : ITriggerStore { /// The token key to evict all cached triggers. public static readonly string CacheInvalidationTokenKey = typeof(CachingTriggerStore).FullName!; @@ -57,7 +58,9 @@ public class CachingTriggerStore(ITriggerStore decoratedStore, ICacheManager cac private async Task GetOrCreateAsync(string key, Func> factory) { - var internalKey = $"{typeof(T).Name}:{key}"; + var tenantId = tenantAccessor.CurrentTenant?.Id; + var tenantIdPrefix = !string.IsNullOrEmpty(tenantId) ? $"{tenantId}:" : string.Empty; + var internalKey = $"{tenantIdPrefix}{typeof(T).Name}:{key}"; return await cacheManager.GetOrCreateAsync(internalKey, async entry => { var invalidationRequestToken = cacheManager.GetToken(CacheInvalidationTokenKey); diff --git a/src/modules/Elsa/Features/ElsaFeature.cs b/src/modules/Elsa/Features/ElsaFeature.cs index e4fc95efa..f6941f456 100644 --- a/src/modules/Elsa/Features/ElsaFeature.cs +++ b/src/modules/Elsa/Features/ElsaFeature.cs @@ -6,7 +6,6 @@ using Elsa.Features.Services; using Elsa.Workflows.Activities; using Elsa.Workflows.Features; using Elsa.Workflows.Management.Features; -using Elsa.Workflows.Runtime.Extensions; using Elsa.Workflows.Runtime.Features; namespace Elsa.Features; diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs index 0820347e8..4e02e6c33 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs @@ -10,11 +10,9 @@ using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.Extensions; using Elsa.Identity.Providers; using Elsa.MassTransit.Extensions; -using Elsa.Tenants.Extensions; using Elsa.Testing.Shared.Handlers; using Elsa.Testing.Shared.Services; using Elsa.Workflows.Management; -using Elsa.Workflows.Runtime.Distributed.Extensions; using FluentStorage; using Hangfire.Annotations; using Microsoft.AspNetCore.Hosting; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs index 2323f510b..68d1171e5 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs @@ -1,5 +1,4 @@ using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; -using Elsa.Api.Client.Resources.WorkflowDefinitions.Models; using Elsa.Api.Client.Resources.WorkflowDefinitions.Responses; using Elsa.Api.Client.Resources.WorkflowInstances.Models; using Elsa.Common.Entities; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs index 27d83d130..8d25b686a 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs @@ -1,4 +1,4 @@ -using Elsa.Http.Contracts; +using Elsa.Http; using Elsa.Testing.Shared; using Elsa.Testing.Shared.Services; using Elsa.Workflows.ComponentTests.Helpers; @@ -60,16 +60,14 @@ public class AutoUpdateTests : AppComponentTest var filter = new TriggerFilter { - Hash = hash, - TenantAgnostic = true + Hash = hash }; var hashedFilter = _hasher.Hash(filter); Assert.True(_cache.TryGetValue($"IEnumerable`1:{hashedFilter}", out _)); var parentWorkflowDefinitionFilter = new WorkflowDefinitionFilter { - Id = ParentDefinitionVersionId, - TenantAgnostic = true + Id = ParentDefinitionVersionId }; var parentVersionCacheKey = _definitionCacheManager.CreateWorkflowFilterCacheKey(parentWorkflowDefinitionFilter); Assert.True(_cache.TryGetValue(parentVersionCacheKey, out _)); diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs index d17d703b3..a21b5ab36 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs @@ -2,7 +2,6 @@ using Elsa.Testing.Shared.Services; using Elsa.Workflows.ComponentTests.Helpers; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.ComponentTests.Scenarios.WorkflowDefinitionRefresh; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs index b5086a3da..6a8b7157d 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs @@ -4,7 +4,6 @@ using Elsa.Workflows.Activities; using Elsa.Workflows.ComponentTests.Helpers; using Elsa.Workflows.Management; using Elsa.Workflows.Runtime; -using Elsa.Workflows.Runtime.Contracts; using Humanizer; using Microsoft.Extensions.DependencyInjection; diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptFunctions/BytesAndStringEncodingTests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptFunctions/BytesAndStringEncodingTests.cs index 4b6d3c5e7..73092ab57 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptFunctions/BytesAndStringEncodingTests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Scenarios/JavaScriptFunctions/BytesAndStringEncodingTests.cs @@ -4,7 +4,6 @@ using Elsa.Extensions; using Elsa.JavaScript.Contracts; using Elsa.Testing.Shared; using Microsoft.Extensions.DependencyInjection; -using Xunit; using Xunit.Abstractions; namespace Elsa.Workflows.IntegrationTests.Scenarios.JavaScriptFunctions; diff --git a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/ContainerSerialization/Tests.cs b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/ContainerSerialization/Tests.cs index cfe888837..6785e73b8 100644 --- a/test/integration/Elsa.Workflows.IntegrationTests/Serialization/ContainerSerialization/Tests.cs +++ b/test/integration/Elsa.Workflows.IntegrationTests/Serialization/ContainerSerialization/Tests.cs @@ -6,7 +6,6 @@ using Elsa.Workflows.Activities.Flowchart.Models; using Elsa.Workflows.Memory; using Elsa.Workflows.Models; using Microsoft.Extensions.DependencyInjection; -using Xunit; using Xunit.Abstractions; namespace Elsa.Workflows.IntegrationTests.Serialization.ContainerSerialization;