diff --git a/Elsa.sln b/Elsa.sln index 12626cd95f..3bd4eac222 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -84,14 +84,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{986E54 ProjectSection(SolutionItems) = preProject docker\.dockerignore = docker\.dockerignore docker\docker-compose-datadog.yml = docker\docker-compose-datadog.yml - docker\docker-compose-kafka.yml = docker\docker-compose-kafka.yml docker\docker-compose.yml = docker\docker-compose.yml docker\ElsaServer-Datadog.Dockerfile = docker\ElsaServer-Datadog.Dockerfile docker\ElsaServer.Dockerfile = docker\ElsaServer.Dockerfile docker\ElsaServerAndStudio.Dockerfile = docker\ElsaServerAndStudio.Dockerfile docker\ElsaStudio.Dockerfile = docker\ElsaStudio.Dockerfile docker\otel-collector-config.yaml = docker\otel-collector-config.yaml - docker\docker-compose-kafka.yml = docker\docker-compose-kafka.yml docker\init-db-postgres.sh = docker\init-db-postgres.sh EndProjectSection EndProject @@ -399,6 +397,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Sql.Sqlite", "src\modules\Elsa.Sql.Sqlite\Elsa.Sql.Sqlite.csproj", "{FA5E857F-B173-4B5D-8049-B817A210DEF5}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Sql.SqlServer", "src\modules\Elsa.Sql.SqlServer\Elsa.Sql.SqlServer.csproj", "{A51F9683-DA9F-45E7-82DE-1E261ACD6D68}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "oracle-setup", "oracle-setup", "{66E2E2CF-967F-4564-89E8-F46FA973C99B}" ProjectSection(SolutionItems) = preProject docker\oracle-setup\setup.sql = docker\oracle-setup\setup.sql diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index e22f276fd9..32fdbfc5cf 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -659,7 +659,11 @@ } }); - elsa.UseTenantHttpRouting(); + elsa.UseTenantHttpRouting(tenantHttpRouting => + { + // Override the tenant header name with a custom one. + tenantHttpRouting.WithTenantHeader("X-Company-Id"); + }); } elsa.InstallDropIns(options => options.DropInRootDirectory = Path.Combine(Directory.GetCurrentDirectory(), "App_Data", "DropIns")); diff --git a/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs b/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs index 2def1e4d62..bdf0df3b8a 100644 --- a/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs +++ b/src/modules/Elsa.Tenants.AspNetCore/Features/MultitenantHttpRoutingFeature.cs @@ -3,6 +3,7 @@ using Elsa.Features.Attributes; using Elsa.Features.Services; using Elsa.Http.Features; +using Elsa.Tenants.AspNetCore.Options; using Elsa.Tenants.AspNetCore.Services; using Elsa.Tenants.Features; using Microsoft.Extensions.DependencyInjection; @@ -13,6 +14,26 @@ namespace Elsa.Tenants.AspNetCore.Features; [DependencyOf(typeof(TenantsFeature))] public class MultitenantHttpRoutingFeature(IModule module) : FeatureBase(module) { + private Action _configureMultitenancyHttpOptions = _ => { }; + + /// + /// Configures the MultitenantHttpRoutingFeature to use a specific tenant header name. + /// + /// The name of the HTTP header used to identify the tenant. + /// The current instance of for fluent configuration. + public MultitenantHttpRoutingFeature WithTenantHeader(string headerName) => WithMultitenancyHttpOptions(options => options.TenantHeaderName = headerName); + + /// + /// Configures the MultitenantHttpRoutingFeature with custom multitenancy HTTP options. + /// + /// The action to configure . + /// The current instance of for fluent configuration. + public MultitenantHttpRoutingFeature WithMultitenancyHttpOptions(Action configure) + { + _configureMultitenancyHttpOptions = configure; + return this; + } + public override void Configure() { Module.Configure(feature => @@ -24,6 +45,9 @@ public override void Configure() public override void Apply() { + // Multitenancy HTTP options. + Services.Configure(_configureMultitenancyHttpOptions); + // Tenant resolvers. Services .AddScoped() diff --git a/src/modules/Elsa.Tenants.AspNetCore/Options/MultitenancyHttpOptions.cs b/src/modules/Elsa.Tenants.AspNetCore/Options/MultitenancyHttpOptions.cs new file mode 100644 index 0000000000..877400eb68 --- /dev/null +++ b/src/modules/Elsa.Tenants.AspNetCore/Options/MultitenancyHttpOptions.cs @@ -0,0 +1,6 @@ +namespace Elsa.Tenants.AspNetCore.Options; + +public class MultitenancyHttpOptions +{ + public string TenantHeaderName { get; set; } = "X-Tenant-Id"; +} \ 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 index 06d36e387c..6970492851 100644 --- a/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HeaderTenantResolver.cs +++ b/src/modules/Elsa.Tenants.AspNetCore/Resolvers/HeaderTenantResolver.cs @@ -1,12 +1,14 @@ using Elsa.Common.Multitenancy; +using Elsa.Tenants.AspNetCore.Options; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; namespace Elsa.Tenants.AspNetCore; /// /// Resolves the tenant based on the header in the request. /// -public class HeaderTenantResolver(IHttpContextAccessor httpContextAccessor) : TenantResolverBase +public class HeaderTenantResolver(IHttpContextAccessor httpContextAccessor, IOptions options) : TenantResolverBase { protected override TenantResolverResult Resolve(TenantResolverContext context) { @@ -15,7 +17,8 @@ protected override TenantResolverResult Resolve(TenantResolverContext context) if (httpContext == null) return Unresolved(); - var tenantId = httpContext.Request.Headers["X-Tenant-Id"].FirstOrDefault(); + var headerName = options.Value.TenantHeaderName; + var tenantId = httpContext.Request.Headers[headerName].FirstOrDefault(); return AutoResolve(tenantId); }