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

@@ -3,7 +3,7 @@ using Tiku.Domain.Common;
namespace Tiku.Domain.Content;
public sealed class ContentAssetAccessEvent : Entity
public sealed class ContentAssetAccessEvent : Entity, ITenantOwned
{
public Guid TenantId { get; set; }
public Guid? AssetId { get; set; }
@@ -24,7 +24,7 @@ public sealed class ContentAssetAccessEvent : Entity
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class ContentAssetSecurityScanEvent : Entity
public sealed class ContentAssetSecurityScanEvent : Entity, ITenantOwned
{
public Guid TenantId { get; set; }
public Guid? AssetId { get; set; }
@@ -36,38 +36,25 @@ public sealed class ContentAssetSecurityScanEvent : Entity
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class QuestionBankGrant : AuditableEntity
public sealed class TenantQuestionBankPreference : AuditableTenantEntity
{
public Guid SourceQuestionBankId { get; set; }
public Guid QuestionBankOwnerTenantId { get; set; }
public Guid QuestionBankId { get; set; }
public bool IsVisible { get; set; } = true;
public string? Alias { get; set; }
public int SortOrder { get; set; }
public string? NavigationLocation { get; set; }
public Guid? CreatedBy { get; set; }
public Guid? UpdatedBy { get; set; }
public QuestionBankGrantScope GrantScope { get; set; } = QuestionBankGrantScope.Plans;
public string[] AllowedPlanCodes { get; set; } = [];
public Guid[] AllowedTenantIds { get; set; } = [];
public Guid[] AllowedRegionIds { get; set; } = [];
public Guid[] AllowedSubjectIds { get; set; } = [];
public QuestionBankGrantStatus Status { get; set; } = QuestionBankGrantStatus.Active;
public DateTimeOffset? StartsAt { get; set; }
public DateTimeOffset? ExpiresAt { get; set; }
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}
public sealed class TenantQuestionBankAdoption : AuditableTenantEntity
public sealed class TenantQuestionReference : AuditableTenantEntity
{
public Guid SourceQuestionBankId { get; set; }
public Guid? GrantId { get; set; }
public Guid? TargetQuestionBankId { get; set; }
public Guid? TargetEntryId { get; set; }
public Guid? TargetCollectionId { get; set; }
public Guid QuestionOwnerTenantId { get; set; }
public Guid QuestionId { get; set; }
public QuestionSource Source { get; set; } = QuestionSource.Tenant;
public Guid? CreatedBy { get; set; }
public Guid? UpdatedBy { get; set; }
public QuestionBankAdoptionMode AdoptionMode { get; set; } = QuestionBankAdoptionMode.CopiedSnapshot;
public QuestionBankAdoptionStatus Status { get; set; } = QuestionBankAdoptionStatus.Active;
public QuestionBankAdoptionSyncStatus SyncStatus { get; set; } = QuestionBankAdoptionSyncStatus.Synced;
public JsonElement SourceSnapshot { get; set; } = JsonDefaults.Object();
public int CopiedQuestionCount { get; set; }
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
public DateTimeOffset? LastSyncedAt { get; set; }
}
public sealed class AiRecommendationReport : AuditableTenantEntity
@@ -90,9 +77,5 @@ public enum AssetAccessType { Download, Preview, AdminDownload, AdminPreview, Up
public enum AssetAccessDisposition { Attachment, Inline }
public enum AssetAccessResult { Granted, Denied }
public enum AssetSecurityRiskLevel { None, Low, Medium, High, Critical }
public enum QuestionBankGrantScope { AllActiveTenants, Plans, Tenants, Mixed }
public enum QuestionBankGrantStatus { Active, Disabled, Expired }
public enum QuestionBankAdoptionMode { CopiedSnapshot, Reference }
public enum QuestionBankAdoptionStatus { Active, SyncPending, Suspended, Archived }
public enum QuestionBankAdoptionSyncStatus { Pending, Synced, Failed }
public enum QuestionSource { Platform, Tenant }
public enum AiRecommendationReportStatus { Draft, Generated, Failed }