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

@@ -2,10 +2,12 @@ using Microsoft.AspNetCore.Mvc;
using Tiku.Api.Controllers;
using Tiku.Application.Assets;
using Tiku.Application.Auth;
using Tiku.Application.Security;
using Tiku.Application.Commerce;
using Tiku.Application.Content;
using Tiku.Application.Growth;
using Tiku.Application.Points;
using Tiku.Application.QuestionBanks;
using Tiku.Application.Storage;
using Tiku.Infrastructure.Content;
using Tiku.Infrastructure.Learning;
@@ -13,6 +15,7 @@ using Tiku.Infrastructure.Profile;
using Tiku.Infrastructure.QuestionBanks;
using Tiku.Infrastructure.Scoreline;
using Tiku.Application.TenantAdmin;
using Tiku.Application.Tenancy;
namespace Tiku.Api.Middleware;
@@ -45,6 +48,52 @@ public sealed class ExceptionHandlingMiddleware(
return;
}
if (exception is TenantContextConflictException)
{
await WriteProblemAsync(
context,
exception.Message,
StatusCodes.Status403Forbidden,
"tenant_context_conflict");
return;
}
if (exception is TenantFrontendConfigException frontendConfigException)
{
var status = frontendConfigException.Code switch
{
"tenant_not_found" or "frontend_config_not_found" => StatusCodes.Status404NotFound,
"frontend_config_version_conflict" => StatusCodes.Status409Conflict,
_ => StatusCodes.Status400BadRequest
};
await WriteProblemAsync(
context,
frontendConfigException.Message,
status,
frontendConfigException.Code);
return;
}
if (exception is PublicQuestionAccessDeniedException publicQuestionAccessDeniedException)
{
await WriteProblemAsync(
context,
publicQuestionAccessDeniedException.Message,
StatusCodes.Status403Forbidden,
publicQuestionAccessDeniedException.Code);
return;
}
if (exception is QuestionLocatorException questionLocatorException)
{
await WriteProblemAsync(
context,
questionLocatorException.Message,
StatusCodes.Status404NotFound,
questionLocatorException.Code);
return;
}
if (exception is RequiredFieldException)
{
await WriteProblemAsync(