forked from gongxuegit/tiku-backend.net
feat: enforce tenant isolation and shared question bank
This commit is contained in:
66
Tiku.Infrastructure/Tenancy/TenantDirectory.cs
Normal file
66
Tiku.Infrastructure/Tenancy/TenantDirectory.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using Npgsql;
|
||||
using Tiku.Application.Tenancy;
|
||||
using Tiku.Domain.Tenancy;
|
||||
|
||||
namespace Tiku.Infrastructure.Tenancy;
|
||||
|
||||
public sealed class TenantDirectory(NpgsqlDataSource dataSource) : ITenantDirectory
|
||||
{
|
||||
public Task<TenantDirectoryEntry?> FindByHostAsync(
|
||||
string host,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
select t.id, t.slug, t.name, t.status, t.mode, d.host
|
||||
from tenant_domains d
|
||||
join tenants t on t.id = d.tenant_id
|
||||
where d.host = @lookup
|
||||
and d.status = 'active'
|
||||
and t.status = 'active'
|
||||
limit 1
|
||||
""";
|
||||
return FindAsync(sql, host, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<TenantDirectoryEntry?> FindByCodeAsync(
|
||||
string tenantCode,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
select t.id, t.slug, t.name, t.status, t.mode, null::text as host
|
||||
from tenants t
|
||||
where t.slug = @lookup
|
||||
and t.status = 'active'
|
||||
limit 1
|
||||
""";
|
||||
return FindAsync(sql, tenantCode, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<TenantDirectoryEntry?> FindAsync(
|
||||
string sql,
|
||||
string lookup,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await using var command = dataSource.CreateCommand(sql);
|
||||
command.Parameters.AddWithValue("lookup", lookup);
|
||||
await using var reader = await command.ExecuteReaderAsync(cancellationToken);
|
||||
if (!await reader.ReadAsync(cancellationToken))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TenantDirectoryEntry(
|
||||
reader.GetGuid(0),
|
||||
reader.GetString(1),
|
||||
reader.GetString(2),
|
||||
ParseEnum<TenantStatus>(reader.GetString(3)),
|
||||
ParseEnum<TenantMode>(reader.GetString(4)),
|
||||
reader.IsDBNull(5) ? null : reader.GetString(5));
|
||||
}
|
||||
|
||||
private static TEnum ParseEnum<TEnum>(string value)
|
||||
where TEnum : struct, Enum
|
||||
{
|
||||
return Enum.Parse<TEnum>(value.Replace("_", string.Empty, StringComparison.Ordinal), true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user