From 7e7a899bbfb23242e672c3f0d787f2db047c4bfc Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 14 Oct 2024 21:27:11 +0200 Subject: [PATCH] Implement multitenant HTTP routing (#6031) * Add tenant awareness to bookmark handling and route resolution Added tenant ID support across various components, including bookmark updates, route resolution, and middleware processing. This ensures that bookmark and route operations can now appropriately handle tenant-specific data, improving the system's multitenancy capabilities. * Add Multitenant HTTP Routing feature to Tenants module Introduced a new MultitenantHttpRoutingFeature class to the Elsa.Tenants.AspNetCore module, enhancing the tenant resolution capabilities. Moved RoutePrefixTenantResolver from Elsa.Http to Elsa.Tenants.AspNetCore and updated relevant project references and namespaces accordingly. This refactor improves modularity and separation of concerns between HTTP and tenancy features. * Refactor route handling and tenant configuration Removed redundant `RouteTableExtensions` and replaced with new route providers and updaters, enhancing flexibility and modularity. Introduced tenant-specific HTTP endpoint configurations for better customization and configuration management. * Rename HttpEndpointBookmarkStimulus to HttpEndpointBookmarkPayload Refactor various classes and methods to reflect the renaming from `HttpEndpointBookmarkStimulus` to `HttpEndpointBookmarkPayload`. Add and configure new extension methods for tenant route handling, update the route provider to support multi-tenancy, and adjust the tenants provider to bind configuration properly. * Add HeaderTenantResolver and refactor Http namespace. Introduce HeaderTenantResolver to resolve tenants via HTTP headers. Refactor multiple classes and interfaces to move from the Elsa.Http.Models namespace directly into Elsa.Http for clarity and consistency. * Add Host-based tenant resolution Implemented a HostTenantResolver to resolve tenants based on the request's host and updated tenant configurations with host information. Modified the tenant resolver pipeline and added the new host resolver to the service registrations. * Add tenant-aware caching and accessor support Enhanced caching by incorporating tenant identifiers into cache keys for more granular cache management. Introduced ITenantAccessor dependencies in various services to retrieve the current tenant information. This ensures that cache entries are correctly isolated per tenant. * Reorder tenant resolvers for pipeline setup. Reordered the tenant resolvers in the pipeline to prioritize HostTenantResolver before RoutePrefixTenantResolver. This ensures that tenant resolution is correctly aligned with host-based resolving before checking the route prefix. * Remove unused imports This commit eliminates redundant `using` directives across multiple files to streamline the codebase. This cleanup helps improve code readability and maintainability by removing unnecessary dependencies. --- Directory.Packages.props | 4 +- Elsa.sln | 2 - src/apps/Elsa.Server.Web/Program.cs | 27 ++-- src/apps/Elsa.Server.Web/appsettings.json | 48 ++++++- src/apps/Elsa.ServerAndStudio.Web/Program.cs | 2 - src/apps/ElsaStudioWebAssembly/Program.cs | 1 - .../Models/ActivityExecutionRecordSummary.cs | 2 - .../Elsa.Api.Common/Abstractions/Endpoints.cs | 1 - .../AgentActivityProvider.cs | 1 - .../Endpoints/Agents/Get/Endpoint.cs | 1 - .../Endpoints/Agents/IsUniqueName/Endpoint.cs | 1 - .../Endpoints/Agents/List/Endpoint.cs | 1 - .../Endpoints/Agents/Update/Endpoint.cs | 2 - .../Endpoints/ApiKeys/Get/Endpoint.cs | 2 - .../Endpoints/ApiKeys/List/Endpoint.cs | 1 - .../Endpoints/Services/Get/Endpoint.cs | 1 - .../Endpoints/Services/List/Endpoint.cs | 1 - .../Endpoints/Services/Update/Endpoint.cs | 1 - .../Configurations.cs | 1 - .../Services/WorkflowInstanceFinder.cs | 1 - .../HostedServices/StartWorkers.cs | 1 - .../Models/ReceivedServiceBusMessageModel.cs | 1 - .../Elsa.AzureServiceBus/Services/Worker.cs | 2 - src/modules/Elsa.Common/Elsa.Common.csproj | 1 + .../Multitenancy/Entities/Tenant.cs | 5 +- .../Runtime/WorkflowExecutionLogStore.cs | 1 - .../EntityStore.cs | 1 - .../Features.cs | 1 - .../Runtime/ActivityExecutionLogStore.cs | 1 - .../Modules/Runtime/BookmarkStore.cs | 1 - .../Modules/Runtime/TriggerStore.cs | 2 - ...angfireBackgroundActivityInvokerFeature.cs | 1 - .../Jobs/ExecuteBackgroundActivityJob.cs | 1 - .../Elsa.Hangfire/Jobs/RunWorkflowJob.cs | 1 - .../Services/HangfireWorkflowScheduler.cs | 1 - .../DownloadableContentHandlerBase.cs | 2 - .../HttpCorrelationIdSelectorBase.cs | 1 - .../HttpWorkflowInstanceIdSelectorBase.cs | 1 - .../Elsa.Http/Activities/DownloadHttpFile.cs | 2 - .../Elsa.Http/Activities/HttpEndpoint.cs | 4 +- .../Elsa.Http/Activities/SendHttpRequest.cs | 1 - .../Activities/SendHttpRequestBase.cs | 1 - .../Activities/WriteFileHttpResponse.cs | 2 - .../Elsa.Http/Activities/WriteHttpResponse.cs | 12 +- .../Elsa.Http/Contexts/DownloadableContext.cs | 1 - .../HttpEndpointRouteProviderContext.cs | 7 + .../Contracts/IAbsoluteUrlProvider.cs | 2 +- .../Contracts/IDownloadableContentHandler.cs | 3 +- .../Contracts/IDownloadableManager.cs | 3 +- .../Contracts/IFileCacheStorageProvider.cs | 2 +- .../Elsa.Http/Contracts/IFileDownloader.cs | 2 +- .../Elsa.Http/Contracts/IHttpContentParser.cs | 2 +- .../Contracts/IHttpCorrelationIdSelector.cs | 2 +- .../IHttpEndpointAuthorizationHandler.cs | 4 +- .../Contracts/IHttpEndpointFaultHandler.cs | 4 +- .../Contracts/IHttpEndpointRoutesProvider.cs | 8 ++ .../IHttpWorkflowInstanceIdSelector.cs | 2 +- .../Contracts/IHttpWorkflowLookupService.cs | 4 +- .../Contracts/IHttpWorkflowsCacheManager.cs | 2 +- .../Elsa.Http/Contracts/IRouteMatcher.cs | 2 +- .../Elsa.Http/Contracts/IRouteTable.cs | 10 +- .../Elsa.Http/Contracts/IRouteTableUpdater.cs | 42 +++++- .../BinaryDownloadableContentHandler.cs | 1 - .../DownloadableDownloadableContentHandler.cs | 1 - .../FormFileDownloadableContentHandler.cs | 1 - .../HttpFileDownloadableContentHandler.cs | 1 - .../MultiDownloadableContentHandler.cs | 1 - .../StreamDownloadableContentHandler.cs | 1 - .../StringDownloadableContentHandler.cs | 1 - .../UrlDownloadableContentHandler.cs | 2 - src/modules/Elsa.Http/Elsa.Http.csproj | 2 +- .../Elsa.Http/Elsa.Http.csproj.DotSettings | 4 +- .../ExpressionExecutionContextExtensions.cs | 3 +- .../HttpActivityExecutionContextExtensions.cs | 2 +- .../Extensions/RouteTableExtensions.cs | 78 ----------- .../Extensions/ServiceCollectionExtensions.cs | 2 +- .../Extensions/StringArrayExtensions.cs | 11 ++ .../Extensions/StringValueExtensions.cs | 3 +- .../Elsa.Http/Features/HttpCacheFeature.cs | 1 - src/modules/Elsa.Http/Features/HttpFeature.cs | 37 +++--- .../BlobFileCacheStorageProvider.cs | 1 - ...onymousHttpEndpointAuthorizationHandler.cs | 3 - ...onBasedHttpEndpointAuthorizationHandler.cs | 2 - .../DefaultHttpEndpointFaultHandler.cs | 2 - .../DetailedHttpEndpointFaultHandler.cs | 2 - .../Handlers/InvalidateHttpWorkflowsCache.cs | 1 - .../Elsa.Http/Handlers/UpdateRouteTable.cs | 31 ++--- .../UpdateRouteTableHostedService.cs | 3 +- .../Middleware/HttpWorkflowsMiddleware.cs | 20 ++- .../Models/AuthorizeHttpEndpointContext.cs | 2 +- src/modules/Elsa.Http/Models/Downloadable.cs | 2 +- .../Elsa.Http/Models/EventTokenPayload.cs | 2 +- .../Models/HttpEndpointFaultContext.cs | 2 +- src/modules/Elsa.Http/Models/HttpFile.cs | 2 +- src/modules/Elsa.Http/Models/HttpHeaders.cs | 2 +- src/modules/Elsa.Http/Models/HttpRouteData.cs | 31 +++++ .../Elsa.Http/Models/HttpStatusCodeCase.cs | 2 +- .../Models/HttpWorkflowLookupResult.cs | 2 +- .../Parsers/FileHttpContentParser.cs | 2 - .../Parsers/JsonHttpContentParser.cs | 1 - .../Parsers/PlainTextHttpContentParser.cs | 1 - .../Parsers/TextHtmlHttpContentParser.cs | 1 - .../Elsa.Http/Parsers/XmlHttpContentParser.cs | 1 - .../JavaScript/HttpJavaScriptHandler.cs | 1 - .../Serialization/HttpHeadersConverter.cs | 1 - ...tusCodeCaseForWorkflowInstanceConverter.cs | 1 - .../CachingHttpWorkflowLookupService.cs | 11 +- .../Services/DefaultAbsoluteUrlProvider.cs | 1 - .../Services/DefaultDownloadableManager.cs | 2 - .../DefaultHttpEndpointRoutesProvider.cs | 36 ++++++ .../Services/DefaultRouteTableUpdater.cs | 122 ++++++++++++++---- .../Services/HttpClientFileDownloader.cs | 1 - .../Services/HttpWorkflowLookupService.cs | 9 +- .../Services/HttpWorkflowsCacheManager.cs | 1 - .../Elsa.Http/Services/RouteMatcher.cs | 1 - src/modules/Elsa.Http/Services/RouteTable.cs | 14 +- src/modules/Elsa.Http/Services/ZipManager.cs | 2 - .../Endpoints/TypeDefinitions/Endpoint.cs | 1 - .../Handlers/ConfigureEngineWithVariables.cs | 1 - .../InputFunctionsDefinitionProvider.cs | 1 - ...WorkflowVariablesTypeDefinitionProvider.cs | 1 - .../Extensions/TemplateContextExtensions.cs | 1 - .../Alterations/AlterationPlanStore.cs | 1 - .../Runtime/ActivityExecutionLogStore.cs | 1 - .../Modules/Runtime/BookmarkStore.cs | 1 - .../Modules/Runtime/TriggerStore.cs | 1 - .../Runtime/WorkflowExecutionLogStore.cs | 1 - .../Activities/PatchContentItem.cs | 1 - .../Activities/ResolveTags.cs | 1 - .../Activities/UploadMedia.cs | 2 +- .../Client/Contracts/IRestApiClient.cs | 2 +- .../Client/Services/DefaultRestApiClient.cs | 2 +- .../Elsa.Quartz/Jobs/RunWorkflowJob.cs | 1 - .../Handlers/ScheduleWorkflows.cs | 2 +- .../Services/DefaultTriggerScheduler.cs | 1 - .../DbContextFactories.cs | 8 +- .../DbContextFactories.cs | 8 +- .../Feature.cs | 1 - .../Extensions/ModuleExtensions.cs | 1 - .../Activities/GatherUsingAudio.cs | 1 - .../Handlers/TriggerAnswerCallActivities.cs | 1 - .../Handlers/TriggerCallAnsweredActivities.cs | 2 - .../Handlers/TriggerCallBridgedActivities.cs | 2 - .../Handlers/TriggerCallHangupActivities.cs | 3 - .../Handlers/TriggerIncomingCallActivities.cs | 3 - .../Handlers/TriggerWebhookActivities.cs | 2 - .../TriggerWebhookDrivenActivities.cs | 1 - .../Elsa.Tenants.AspNetCore.csproj | 1 + ...Elsa.Tenants.AspNetCore.csproj.DotSettings | 3 + .../Extensions/ModuleExtensions.cs | 21 +++ .../Extensions/TenantExtensions.cs | 16 +++ .../Features/MultitenantHttpRoutingFeature.cs | 33 +++++ .../Middleware/TenantResolutionMiddleware.cs | 19 ++- .../Resolvers/HeaderTenantResolver.cs | 22 ++++ .../Resolvers/HostTenantResolver.cs | 30 +++++ .../Resolvers}/RoutePrefixTenantResolver.cs | 24 ++-- .../TenantPrefixHttpEndpointRoutesProvider.cs | 63 +++++++++ .../Settings/HttpEndpointOptions.cs | 9 ++ .../Elsa.Tenants.csproj.DotSettings | 3 +- .../Extensions/TenantsProviderExtensions.cs | 2 +- .../Providers/ConfigurationTenantsProvider.cs | 17 ++- .../WebhookEventActivityProvider.cs | 1 - .../Activities/SetWorkflowContextParameter.cs | 1 - .../ListSummaries/Endpoint.cs | 1 - .../ActivityExecutions/Get/Endpoint.cs | 1 - .../Events/TriggerPublic/Endpoint.cs | 2 +- .../WorkflowDefinitions/Refresh/Endpoint.cs | 1 - .../WorkflowDefinitions/Reload/Endpoint.cs | 1 - .../Activities/Workflow.cs | 1 - .../ExpressionExecutionContextExtensions.cs | 2 - .../Models/ActivityNode.cs | 2 - .../Models/RunWorkflowResult.cs | 1 - .../Serializers/JsonActivitySerializer.cs | 1 - .../Entities/WorkflowDefinition.cs | 1 - .../Models/WorkflowDefinitionModel.cs | 1 - .../Stores/CachingWorkflowDefinitionStore.cs | 7 +- .../Mappers/Mappers.cs | 2 - .../Services/ProtoActorWorkflowRuntime.cs | 1 - .../ActivityExecutionRecordSummary.cs | 1 - .../Workflows/PersistBookmarkMiddleware.cs | 2 +- .../Notifications/IndexedWorkflowBookmarks.cs | 2 +- .../Requests/UpdateBookmarksRequest.cs | 2 +- .../Services/BookmarkPersister.cs | 10 +- .../Services/BookmarkUpdater.cs | 2 +- .../Stores/CachingTriggerStore.cs | 7 +- src/modules/Elsa/Features/ElsaFeature.cs | 1 - .../Helpers/Fixtures/WorkflowServer.cs | 2 - .../InputOutputLoggingTests.cs | 1 - .../WorkflowActivities/AutoUpdateTests.cs | 8 +- .../DynamicEndpointTests.cs | 1 - .../ReloadWorkflowTests.cs | 1 - .../BytesAndStringEncodingTests.cs | 1 - .../ContainerSerialization/Tests.cs | 1 - 193 files changed, 677 insertions(+), 433 deletions(-) create mode 100644 src/modules/Elsa.Http/Contexts/HttpEndpointRouteProviderContext.cs create mode 100644 src/modules/Elsa.Http/Contracts/IHttpEndpointRoutesProvider.cs delete mode 100644 src/modules/Elsa.Http/Extensions/RouteTableExtensions.cs create mode 100644 src/modules/Elsa.Http/Extensions/StringArrayExtensions.cs create mode 100644 src/modules/Elsa.Http/Models/HttpRouteData.cs create mode 100644 src/modules/Elsa.Http/Services/DefaultHttpEndpointRoutesProvider.cs create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Elsa.Tenants.AspNetCore.csproj.DotSettings create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Extensions/ModuleExtensions.cs create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Extensions/TenantExtensions.cs create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Resolvers/HeaderTenantResolver.cs create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Resolvers/HostTenantResolver.cs rename src/modules/{Elsa.Http/Multitenancy => Elsa.Tenants.AspNetCore/Resolvers}/RoutePrefixTenantResolver.cs (64%) create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Services/TenantPrefixHttpEndpointRoutesProvider.cs create mode 100644 src/modules/Elsa.Tenants.AspNetCore/Settings/HttpEndpointOptions.cs 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;