forked from gongxuegit/tiku-backend.net
feat: enforce tenant isolation and shared question bank
This commit is contained in:
22
Tiku.Application/Tenancy/TenantDirectoryModels.cs
Normal file
22
Tiku.Application/Tenancy/TenantDirectoryModels.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Tiku.Domain.Tenancy;
|
||||
|
||||
namespace Tiku.Application.Tenancy;
|
||||
|
||||
public sealed record TenantDirectoryEntry(
|
||||
Guid TenantId,
|
||||
string TenantCode,
|
||||
string Name,
|
||||
TenantStatus Status,
|
||||
TenantMode Mode,
|
||||
string? Host);
|
||||
|
||||
public interface ITenantDirectory
|
||||
{
|
||||
Task<TenantDirectoryEntry?> FindByHostAsync(
|
||||
string host,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TenantDirectoryEntry?> FindByCodeAsync(
|
||||
string tenantCode,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
39
Tiku.Application/Tenancy/TenantDomainLifecycleModels.cs
Normal file
39
Tiku.Application/Tenancy/TenantDomainLifecycleModels.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace Tiku.Application.Tenancy;
|
||||
|
||||
public sealed class DomainLifecycleOptions
|
||||
{
|
||||
public bool Enabled { get; set; } = true;
|
||||
public int PollSeconds { get; set; } = 60;
|
||||
public int BatchSize { get; set; } = 50;
|
||||
public string DnsJsonEndpoint { get; set; } = "https://cloudflare-dns.com/dns-query";
|
||||
public string VerificationRecordPrefix { get; set; } = "_tiku-verification";
|
||||
public string[] AllowedCnameTargets { get; set; } = [];
|
||||
public string? GatewayBaseUrl { get; set; }
|
||||
public string? GatewayApiKey { get; set; }
|
||||
}
|
||||
|
||||
public sealed record DomainOwnershipResult(bool Verified, bool Configured, string? FailureReason);
|
||||
public sealed record DomainGatewayResult(bool TlsReady, bool Configured, string? FailureReason);
|
||||
|
||||
public interface IDomainOwnershipVerifier
|
||||
{
|
||||
Task<DomainOwnershipResult> VerifyAsync(
|
||||
string host,
|
||||
string verificationToken,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public interface IDomainGatewayProvisioner
|
||||
{
|
||||
Task<DomainGatewayResult> EnsureTlsAsync(string host, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public interface ITenantDomainLifecycleService
|
||||
{
|
||||
Task<int> ProcessPendingAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public interface ITenantRuntimeCacheInvalidator
|
||||
{
|
||||
void Invalidate(Guid tenantId);
|
||||
}
|
||||
47
Tiku.Application/Tenancy/TenantFrontendConfigModels.cs
Normal file
47
Tiku.Application/Tenancy/TenantFrontendConfigModels.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Tiku.Application.Tenancy;
|
||||
|
||||
public sealed record TenantFrontendConfigDraft(
|
||||
JsonElement Branding,
|
||||
JsonElement Theme,
|
||||
JsonElement Features,
|
||||
JsonElement Navigation,
|
||||
JsonElement HomeModules);
|
||||
|
||||
public sealed record TenantFrontendConfigItem(
|
||||
int SchemaVersion,
|
||||
int ConfigVersion,
|
||||
TenantFrontendConfigDraft Published,
|
||||
TenantFrontendConfigDraft Draft,
|
||||
DateTimeOffset? PublishedAt);
|
||||
|
||||
public sealed record TenantRuntimeBootstrap(
|
||||
int SchemaVersion,
|
||||
int ConfigVersion,
|
||||
string TenantCode,
|
||||
string TenantName,
|
||||
JsonElement Branding,
|
||||
JsonElement Theme,
|
||||
JsonElement Features,
|
||||
JsonElement Navigation,
|
||||
JsonElement HomeModules);
|
||||
|
||||
public interface ITenantFrontendConfigService
|
||||
{
|
||||
Task<TenantFrontendConfigItem> GetAsync(Guid tenantId, CancellationToken cancellationToken = default);
|
||||
Task<TenantFrontendConfigItem> SaveDraftAsync(
|
||||
Guid tenantId,
|
||||
TenantFrontendConfigDraft draft,
|
||||
CancellationToken cancellationToken = default);
|
||||
Task<TenantFrontendConfigItem> PublishAsync(
|
||||
Guid tenantId,
|
||||
int expectedVersion,
|
||||
CancellationToken cancellationToken = default);
|
||||
Task<TenantRuntimeBootstrap> GetRuntimeAsync(Guid tenantId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public sealed class TenantFrontendConfigException(string code, string message) : Exception(message)
|
||||
{
|
||||
public string Code { get; } = code;
|
||||
}
|
||||
Reference in New Issue
Block a user