Init Git
This commit is contained in:
55
AMREZ.EOP.Infrastructures/Tenancy/TenantDbContextFactory.cs
Normal file
55
AMREZ.EOP.Infrastructures/Tenancy/TenantDbContextFactory.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using AMREZ.EOP.Abstractions.Applications.Tenancy;
|
||||
using AMREZ.EOP.Domain.Shared.Tenancy;
|
||||
using AMREZ.EOP.Infrastructures.Data;
|
||||
using AMREZ.EOP.Infrastructures.Options;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace AMREZ.EOP.Infrastructures.Tenancy;
|
||||
|
||||
public sealed class TenantDbContextFactory : ITenantDbContextFactory
|
||||
{
|
||||
private readonly IOptions<AuthOptions> _opts;
|
||||
private readonly SearchPathInterceptor _searchPath;
|
||||
private readonly TenantRlsInterceptor _rls;
|
||||
|
||||
public TenantDbContextFactory(IOptions<AuthOptions> opts, SearchPathInterceptor searchPath, TenantRlsInterceptor rls)
|
||||
{ _opts = opts; _searchPath = searchPath; _rls = rls; }
|
||||
|
||||
public TContext Create<TContext>(ITenantContext t) where TContext : class
|
||||
{
|
||||
if (typeof(TContext) != typeof(AppDbContext))
|
||||
throw new NotSupportedException($"Unsupported context: {typeof(TContext).Name}");
|
||||
|
||||
var builder = new DbContextOptionsBuilder<AppDbContext>();
|
||||
|
||||
// ✅ การ์ด: ถ้า connection string ของ tenant ไม่ใช่รูปแบบ key=value ให้ fallback ไป DefaultConnection (platform)
|
||||
var raw = (t.ConnectionString ?? string.Empty).Trim();
|
||||
string conn = IsLikelyValidConnectionString(raw)
|
||||
? raw
|
||||
: (_opts.Value.DefaultConnection ?? string.Empty).Trim();
|
||||
|
||||
if (!IsLikelyValidConnectionString(conn))
|
||||
throw new InvalidOperationException(
|
||||
$"Invalid connection string for tenant '{t.TenantKey}'. Provide a valid per-tenant or DefaultConnection.");
|
||||
|
||||
builder.UseNpgsql(conn);
|
||||
|
||||
// RLS per-tenant (ถ้า platform ควรกำหนดให้ Interceptor ทำงานในโหมด platform/disable ตามที่คุณนิยาม)
|
||||
_rls.Configure(t.Id);
|
||||
builder.AddInterceptors(_rls);
|
||||
|
||||
// ใช้ schema ต่อ tenant เมื่อเปิดโหมดนี้
|
||||
if (_opts.Value.UseSchemaPerTenant)
|
||||
{
|
||||
var schema = string.IsNullOrWhiteSpace(t.Schema) ? t.Id : t.Schema!.Trim();
|
||||
_searchPath.Configure(schema, enabled: true); // CREATE IF NOT EXISTS + SET LOCAL search_path
|
||||
builder.AddInterceptors(_searchPath);
|
||||
}
|
||||
|
||||
return (new AppDbContext(builder.Options) as TContext)!;
|
||||
}
|
||||
|
||||
private static bool IsLikelyValidConnectionString(string s)
|
||||
=> !string.IsNullOrWhiteSpace(s) && s.Contains('=');
|
||||
}
|
||||
Reference in New Issue
Block a user