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

@@ -15,7 +15,6 @@ public sealed class PracticeSession : TenantEntity
public Guid? TargetId { get; set; }
public DateTimeOffset StartedAt { get; set; } = DateTimeOffset.UtcNow;
public DateTimeOffset? FinishedAt { get; set; }
public JsonElement QuestionIds { get; set; } = JsonDefaults.Array();
public int QuestionCount { get; set; }
public int? DurationMinutes { get; set; }
public decimal? TotalScore { get; set; }
@@ -27,6 +26,17 @@ public sealed class PracticeSession : TenantEntity
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
}
public sealed class PracticeSessionQuestion : TenantEntity
{
public Guid PracticeSessionId { get; set; }
public Guid QuestionReferenceId { get; set; }
public Guid QuestionOwnerTenantId { get; set; }
public Guid QuestionId { get; set; }
public Guid QuestionVersionId { get; set; }
public int Position { get; set; }
public decimal? Score { get; set; }
}
public enum PracticeAccessMode
{
Free,
@@ -37,9 +47,8 @@ public enum PracticeAccessMode
public sealed class AnswerRecord : TenantEntity
{
public Guid UserId { get; set; }
public Guid? QuestionId { get; set; }
public Guid? QuestionVersionId { get; set; }
public Guid? PracticeSessionId { get; set; }
public Guid PracticeSessionId { get; set; }
public Guid SessionQuestionId { get; set; }
public string? LegacyId { get; set; }
public string? LegacyQuestionId { get; set; }
public string? LegacyCategoryId { get; set; }
@@ -50,19 +59,23 @@ public sealed class AnswerRecord : TenantEntity
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class FavoriteQuestion
public sealed class FavoriteQuestion : ITenantOwned
{
public Guid TenantId { get; set; }
public Guid UserId { get; set; }
public Guid QuestionReferenceId { get; set; }
public Guid QuestionOwnerTenantId { get; set; }
public Guid QuestionId { get; set; }
public string Source { get; set; } = "imported";
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class WrongQuestion
public sealed class WrongQuestion : ITenantOwned
{
public Guid TenantId { get; set; }
public Guid UserId { get; set; }
public Guid QuestionReferenceId { get; set; }
public Guid QuestionOwnerTenantId { get; set; }
public Guid QuestionId { get; set; }
public int WrongCount { get; set; } = 1;
public DateTimeOffset LastWrongAt { get; set; } = DateTimeOffset.UtcNow;