Finbuckle.MultiTenant is an open-source multitenancy middleware library for .NET. It enables tenant resolution, per-tenant app behavior, and per-tenant data isolation.
Thanks for your work (again!) - going from strength to strength.
I am implementing the HttpRemoteStore using an Azure function, and am using function-level security, which requires passing in a secret key. The URL I pass in to .WithHttpRemoteStore() looks something like:
https://internalapi.my.app/GetTenantInfo?code=[SECRET KEY]&identifier=
I then strip off the leading / that Finbuckle automatically prepends the tenant identifier with.
It would be great if the URL I pass to .WithHttpRemoteStore() could allow custom placement of the tenant identifier e.g. https://my.app/GetTenantInfo/{tenant}/?code=[SECRET KEY]
I think it would allow a lot more flexibility with HttpRemoteStore.
Thanks for considering it
Wojt
PS for anyone interested, the Azure function looks like this:
using System.Threading.Tasks;
using Finbuckle.MultiTenant;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace MyNamespace.AzureFunctions.Tenants
{
public class GetTenantInfo
{
private readonly IMultiTenantStore _store;
public GetTenantInfo(IMultiTenantStore store)
{
_store = store;
}
[FunctionName("GetTenantInfo")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
HttpRequest req, ILogger log)
{
var identifier = req.Query["identifier"].ToString();
if (identifier.StartsWith("/")) identifier = identifier.Remove(0, 1);
if (string.IsNullOrEmpty(identifier))
{
log.LogWarning($"API.GetTenantInfo: Received empty request for tenant identifier.");
return new NotFoundObjectResult($"API.GetTenantInfo: No tenant identifier received.");
}
log.LogInformation($"API.GetTenantInfo: Received request for tenant {identifier}");
TenantInfo tenantInfo = await _store.TryGetByIdentifierAsync(identifier);
if (tenantInfo == null)
{
log.LogWarning($"API.GetTenantInfo: Received request for non-existent tenant {identifier}.");
return new NotFoundObjectResult($"API.GetTenantInfo: Tenant '{identifier}' does not exist.");
}
return new OkObjectResult(tenantInfo);
}
}
}
And Configure() in Startup.cs includes this to read the MultiTenantStore from a json file (NB ensure you publish the json file to the server).
public override void Configure(IFunctionsHostBuilder builder)
{
var executioncontextoptions = builder.Services.BuildServiceProvider()
.GetService<IOptions<ExecutionContextOptions>>().Value;
var currentDirectory = executioncontextoptions.AppDirectory;
var config = new ConfigurationBuilder()
.SetBasePath(currentDirectory)
.AddJsonFile("tenants.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
builder.Services.AddMultiTenant().WithConfigurationStore(config, "TenantStore");
}
Hi Andrew
Thanks for your work (again!) - going from strength to strength.
I am implementing the HttpRemoteStore using an Azure function, and am using function-level security, which requires passing in a secret key. The URL I pass in to
.WithHttpRemoteStore()
looks something like:https://internalapi.my.app/GetTenantInfo?code=[SECRET KEY]&identifier=
I then strip off the leading / that Finbuckle automatically prepends the tenant identifier with.
It would be great if the URL I pass to
.WithHttpRemoteStore()
could allow custom placement of the tenant identifier e.g.https://my.app/GetTenantInfo/{tenant}/?code=[SECRET KEY]
I think it would allow a lot more flexibility with HttpRemoteStore.
Thanks for considering it Wojt
PS for anyone interested, the Azure function looks like this:
And Configure() in
Startup.cs
includes this to read the MultiTenantStore from a json file (NB ensure you publish the json file to the server).