elsa-workflows / elsa-workflows/elsa-core
Cannot setup multitenancy (it is ignored)
- Dominant language
- C#
- Stars
- 7.9k
- Forks
- 1.5k
- Avg merge
- 15h 22m
- Merged PRs (30d)
- 114
Description
## Description
I am trying to setup the multi tenancy for Elsa API within an a large existing webapi application. The specification of the strategy of tenant selection appears to be ignored.
## Steps to Reproduce
From the command line:
```sh
dotnet new webapi -o testelsa
cd testelsa
dotnet add package Elsa
dotnet add package Elsa.EntityFrameworkCore
dotnet add package Elsa.EntityFrameworkCore.Sqlite
dotnet add package Elsa.JavaScript
dotnet add package Elsa.Tenants.AspNetCore
dotnet add package Elsa.Workflows.Api
```
Content of `Program.cs`:
```csharp
using System.Security.Claims;
using System.Text.Encodings.Web;
using Elsa.Common.Multitenancy;
using Elsa.EntityFrameworkCore.Extensions;
using Elsa.EntityFrameworkCore.Modules.Management;
using Elsa.Extensions;
using Elsa.Identity.Multitenancy;
using Elsa.Tenants.Extensions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMyAuthentication("TestUser");
builder.Services.AddElsa(elsa =>
{
elsa.UseTenants(tenants =>
{
tenants.ConfigureMultitenancy(options =>
{
Console.WriteLine("====> THIS SECTION IS NEVER CALLED");
options.TenantResolverPipelineBuilder.Append();
});
tenants.UseConfigurationBasedTenantsProvider(options =>
{
options.Tenants.Add(new Tenant { Id = "1", Name = "1", TenantId = "1" });
options.Tenants.Add(new Tenant { Id = "2", Name = "2", TenantId = "2" });
});
});
elsa.UseWorkflowManagement(management => management
.UseEntityFrameworkCore(ef => ef
.UseSqlite()));
elsa.UseWorkflowsApi();
elsa.UseJavaScript();
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseWorkflowsApi();
app.Run();
public static class MyAuthenticationExtensions
{
public static AuthenticationBuilder AddMyAuthentication(this IServiceCollection services, string name)
=> services
.AddAuthentication(MyAuthenticationHandler.SchemeName)
.AddScheme(
MyAuthenticationHandler.SchemeName, options =>
{
options.Name = name;
});
public class MyAuthenticationSchemeOptions : AuthenticationSchemeOptions
{
public string? Name { get; set; }
}
public class MyAuthenticationHandler(
IOptionsMonitor options,
ILoggerFactory logger,
UrlEncoder encoder) : AuthenticationHandler(options, logger, encoder)
{
public static string SchemeName => "MyAuthentication";
protected override Task HandleAuthenticateAsync()
{
var identity = new ClaimsIdentity(new[]
{ new Claim(ClaimTypes.Name, Options.Name ?? "DefaultUser") },
Scheme.Name);
identity.AddClaim(new("permissions", "*"));
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
}
}
```
:bulb: *Note: I **need** that any type of authentication must be possible. This is why, here, I used a custom AuthenticationScheme*
## Expected Behavior
```http
GET http://localhost:5182/elsa/api/workflow-definitions
content-type: application/json
TenantId: 1
```
I expect call to the database done using a proper filter on the tenant. Of course this means that the line `options.TenantResolverPipelineBuilder.Append();` is called.
## Actual Behavior
It appears that `options.TenantResolverPipelineBuilder.Append();` is never called. So the tenant is never taken in consideration
## Environment
- **Elsa Package Version**: 3.4.0
- **Operating System**: Ubuntu 24.04
Contributor guide
Assessment
This issue has not been assessed yet.