Using mix auth-db 2 new files are added:
Configure.Db.cs
Configure.AuthRepository.cs
Right now, I have pretty much everything in Startup.cs as per the MultiTenancy example (full code at the end).
Does it make sense to use the added classes/files generated by mix auth-db in the context of a MultiTenancy service?
For example, in the Configure method of AppHost in the Multitenancy example we have:
container.Register<IAuthRepository>(c => new OrmLiteAuthRepositoryMultitenancy(c.TryResolve<IDbConnectionFactory>(),
connectionStrings.ToArray()));
From what I understand, I could use Configure.Db.cs to set the “Master” db from the example and create any tables in that database if needed.
But should I also move in this class the code to initiate each tenant db and somehow set the array of available connection strings in that class? If so how can this be done?
The same question applies to Configure.AuthRepository.cs
For example,
Should this:
public class ConfigureAuthRepository : IConfigureAppHost, IConfigureServices, IPreInitPlugin
{
public void Configure(IServiceCollection services)
{
services.AddSingleton<IAuthRepository>(c =>
new OrmLiteAuthRepository<AppUser, UserAuthDetails>(c.Resolve<IDbConnectionFactory>())
{
UseDistinctRoleTables = true
});
}
...
}
Be modified to use OrmLiteAuthRepositoryMultitenancy instead? Is so how can the array of connections be accessed?
Here is the full content of my Startup.cs file:
using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Funq;
using ServiceStack;
using ServiceStack.Configuration;
using MultitenancyAuth.ServiceInterface;
using ServiceStack.Auth;
using ServiceStack.Data;
using ServiceStack.OrmLite;
using ServiceStack.Web;
namespace MultitenancyAuth
{
public class Startup : ModularStartup
{
public new void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseServiceStack(new AppHost
{
AppSettings = new NetCoreAppSettings(Configuration)
});
}
}
public class AppHost : AppHostBase
{
public AppHost() : base("MultitenancyAuth", typeof(MultiTenantService).Assembly) {}
public override IAuthRepository GetAuthRepository(IRequest req = null)
{
Console.WriteLine($"In {typeof(AppHost)} ** override ** {nameof(GetAuthRepository)} param: {nameof(IRequest)}");
return req != null
? new OrmLiteAuthRepositoryMultitenancy(GetDbConnection(req)) //At Runtime
: TryResolve<IAuthRepository>(); //On Startup
}
// Configure your AppHost with the necessary configuration and dependencies your App needs
public override void Configure(Container container)
{
Console.WriteLine($"In {typeof(AppHost)} {nameof(Configure)} param: {nameof(Container)}");
SetConfig(new HostConfig
{
DefaultRedirectPath = "/metadata",
DebugMode = AppSettings.Get(nameof(HostConfig.DebugMode), false)
});
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[]
{
new BasicAuthProvider(AppSettings),
new CredentialsAuthProvider(AppSettings)
}));
var maindb = "maindb";
TenantCredentials credentials = Configuration.GetSection(maindb)
.Get<TenantCredentials>();
string mainDbConnection = $"Server=localhost;User Id={credentials.MySql.User};Password={credentials.MySql.UserPassword};Database={maindb};Pooling=true;MinPoolSize=0;MaxPoolSize=200";
container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(mainDbConnection, MySqlDialect.Provider));
var dbFactory = container.Resolve<IDbConnectionFactory>();
List<string> tenants = new List<string>
{
"tenantone",
"tenanttwo"
};
List<string> connectionStrings = new List<string>();
foreach (var tenant in tenants)
{
string conn = GetConnectionStringForTenant(tenant);
connectionStrings.Add(conn);
using IDbConnection db = dbFactory.OpenDbConnectionString(conn);
InitDb(db, tenant, $"{tenant} inc.");
}
container.Register<IAuthRepository>(c =>
new OrmLiteAuthRepositoryMultitenancy(c.TryResolve<IDbConnectionFactory>(),
connectionStrings.ToArray()));
container.Resolve<IAuthRepository>().InitSchema(); // Create any missing UserAuth tables
RegisterTypedRequestFilter<IForTenant>((req,res,dto) =>
req.Items[Keywords.DbInfo] = new ConnectionInfo { ConnectionString = GetConnectionStringForTenant(dto.TenantId)});
}
public void InitDb(IDbConnection db, string tenantId, string company)
{
Console.WriteLine($"In {typeof(AppHost)} {nameof(InitDb)} params: {nameof(IDbConnection)} tenantID, company");
db.DropAndCreateTable<TenantConfig>();
db.Insert(new TenantConfig { Id = tenantId, Company = company });
}
public string GetConnectionStringForTenant(string tenantId)
{
Console.WriteLine($"In {typeof(AppHost)} {nameof(GetConnectionStringForTenant)} params: tenantID");
if (string.IsNullOrWhiteSpace(tenantId)) return null;
TenantCredentials credentials = Configuration.GetSection(tenantId)
.Get<TenantCredentials>();
if (string.IsNullOrWhiteSpace(credentials.MySql.User)) return null;
string db = tenantId.ToLowerInvariant();
return $"Server=localhost;User Id={credentials.MySql.User};Password={credentials.MySql.UserPassword};Database={db};Pooling=true;MinPoolSize=0;MaxPoolSize=200";
}
}
}