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

@@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Tiku.Domain.Catalog;
using Tiku.Domain.QuestionBanks;
namespace Tiku.Infrastructure.Persistence.Configurations;
internal sealed class TaxonomyNodeConfiguration : IEntityTypeConfiguration<TaxonomyNode>
{
public void Configure(EntityTypeBuilder<TaxonomyNode> builder)
{
builder.ConfigureTenantEntity("taxonomy_nodes");
builder.ConfigureTimestamps();
builder.Property(entity => entity.NodeType).HasSnakeCaseEnum();
builder.Property(entity => entity.Code).HasMaxLength(100);
builder.Property(entity => entity.Name).HasMaxLength(300);
builder.Property(entity => entity.Path).HasColumnType("ltree");
builder.Property(entity => entity.Metadata).IsJson("{}");
builder.HasIndex(entity => new { entity.TenantId, entity.Code }).IsUnique();
builder.HasOne<TaxonomyNode>().WithMany()
.HasForeignKey(entity => new { TenantId = entity.ParentOwnerTenantId, Id = entity.ParentId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.Restrict);
builder.ToTable(table => table.HasCheckConstraint(
"ck_taxonomy_nodes_parent_pair",
"(parent_owner_tenant_id is null) = (parent_id is null)"));
}
}
internal sealed class QuestionTaxonomyAssignmentConfiguration : IEntityTypeConfiguration<QuestionTaxonomyAssignment>
{
public void Configure(EntityTypeBuilder<QuestionTaxonomyAssignment> builder)
{
builder.ConfigureEntity("question_taxonomy_assignments");
builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id });
builder.HasIndex(entity => new
{
entity.TenantId,
entity.QuestionId,
entity.TaxonomyOwnerTenantId,
entity.TaxonomyNodeId
}).IsUnique();
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
builder.HasOne<Question>().WithMany()
.HasForeignKey(entity => new { entity.TenantId, entity.QuestionId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne<TaxonomyNode>().WithMany()
.HasForeignKey(entity => new { TenantId = entity.TaxonomyOwnerTenantId, Id = entity.TaxonomyNodeId })
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
.OnDelete(DeleteBehavior.Restrict);
}
}