feat: enforce tenant isolation and shared question bank

This commit is contained in:
2026-07-27 16:59:12 +08:00
parent 28e9a9fa41
commit db4c7b4496
137 changed files with 6402 additions and 112274 deletions

View File

@@ -11,6 +11,10 @@ public sealed class TenantDomain : AuditableTenantEntity
public bool IsPrimary { get; set; }
public string? VerificationToken { get; set; }
public DateTimeOffset? VerifiedAt { get; set; }
public DateTimeOffset? LastCheckedAt { get; set; }
public DateTimeOffset? DnsVerifiedAt { get; set; }
public DateTimeOffset? TlsReadyAt { get; set; }
public string? LastFailureReason { get; set; }
}
public enum TenantDomainType
@@ -28,7 +32,7 @@ public enum TenantDomainStatus
Disabled
}
public sealed class TenantBranding : IHasTimestamps
public sealed class TenantBranding : IHasTimestamps, ITenantOwned
{
public Guid TenantId { get; set; }
public string BrandName { get; set; } = string.Empty;
@@ -45,7 +49,7 @@ public sealed class TenantBranding : IHasTimestamps
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class TenantSettings : IHasTimestamps
public sealed class TenantSettings : IHasTimestamps, ITenantOwned
{
public Guid TenantId { get; set; }
public JsonElement FeatureFlags { get; set; } = JsonDefaults.Object();
@@ -54,3 +58,20 @@ public sealed class TenantSettings : IHasTimestamps
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class TenantFrontendConfig : AuditableTenantEntity
{
public int SchemaVersion { get; set; } = 1;
public int ConfigVersion { get; set; } = 1;
public JsonElement PublishedBranding { get; set; } = JsonDefaults.Object();
public JsonElement PublishedTheme { get; set; } = JsonDefaults.Object();
public JsonElement PublishedFeatures { get; set; } = JsonDefaults.Object();
public JsonElement PublishedNavigation { get; set; } = JsonDefaults.Array();
public JsonElement PublishedHomeModules { get; set; } = JsonDefaults.Array();
public JsonElement DraftBranding { get; set; } = JsonDefaults.Object();
public JsonElement DraftTheme { get; set; } = JsonDefaults.Object();
public JsonElement DraftFeatures { get; set; } = JsonDefaults.Object();
public JsonElement DraftNavigation { get; set; } = JsonDefaults.Array();
public JsonElement DraftHomeModules { get; set; } = JsonDefaults.Array();
public DateTimeOffset? PublishedAt { get; set; }
}

View File

@@ -26,7 +26,7 @@ public sealed class TenantSecret : AuditableTenantEntity
public DateTimeOffset? ExpiresAt { get; set; }
}
public sealed class SmsVerificationCode : Entity
public sealed class SmsVerificationCode : Entity, ITenantOwned
{
public Guid TenantId { get; set; }
public string Phone { get; set; } = string.Empty;
@@ -43,7 +43,7 @@ public sealed class SmsVerificationCode : Entity
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class AuthLoginEvent : Entity
public sealed class AuthLoginEvent : Entity, ITenantOwned
{
public Guid TenantId { get; set; }
public Guid? UserId { get; set; }
@@ -69,7 +69,7 @@ public sealed class AuthSession : AuditableTenantEntity
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}
public sealed class SmsSendRateLimit
public sealed class SmsSendRateLimit : ITenantOwned
{
public Guid TenantId { get; set; }
public SmsRateLimitDimension Dimension { get; set; } = SmsRateLimitDimension.Phone;