feat(saas): implement marketplace and tenant onboarding

This commit is contained in:
2026-07-29 13:58:59 +08:00
parent 76606029e2
commit 6db200a2fc
145 changed files with 16862 additions and 94529 deletions

View File

@@ -16,8 +16,8 @@ namespace Tiku.IntegrationTests.Api;
public sealed class AuthorizationManifestTests
{
private const int ExpectedActionCount = 332;
private const string ExpectedSha256 = "a80fe477ba3021625e17c9fc639e5109bab678178f8024a51c3c732bf5a46d3f";
private const int ExpectedActionCount = 358;
private const string ExpectedSha256 = "5a26d6f0817b2939eef921d1883ad0dc8f82405a1593b82df951e97654a0225d";
[Fact]
public void Controller_authorization_surface_matches_reviewed_manifest()
@@ -61,6 +61,13 @@ public sealed class AuthorizationManifestTests
Assert.NotNull(metadata);
Assert.False(string.IsNullOrWhiteSpace(metadata.AuditAction));
Assert.Contains(metadata.Realm, new[] { "authenticated", "tenant", "platform" });
if (metadata.Realm == "tenant" &&
metadata.Module is { } module &&
PermissionModuleCatalog.RequiredFeatures.TryGetValue(module, out var requiredFeature) &&
requiredFeature is not null)
{
Assert.Contains(requiredFeature, metadata.RequiredFeatures);
}
}
}
@@ -88,6 +95,37 @@ public sealed class AuthorizationManifestTests
}
}
[Theory]
[InlineData("questions", SaasFeatureCatalog.PrivateQuestionBank)]
[InlineData("vocabulary", SaasFeatureCatalog.Vocabulary)]
[InlineData("handbook", SaasFeatureCatalog.Handbook)]
[InlineData("scoreline", SaasFeatureCatalog.Scoreline)]
[InlineData("videos", SaasFeatureCatalog.Video)]
public void Content_import_route_maps_to_an_explicit_feature(string importType, string expectedFeature)
{
Assert.Equal(expectedFeature, SaasFeatureCatalog.ResolveContentImportFeature(importType));
}
[Fact]
public void Tenant_content_permissions_are_split_by_purchasable_feature()
{
var expected = new Dictionary<string, string>(StringComparer.Ordinal)
{
[BackendPermissions.TenantContentManage] = SaasFeatureCatalog.PrivateQuestionBank,
[BackendPermissions.TenantVocabularyManage] = SaasFeatureCatalog.Vocabulary,
[BackendPermissions.TenantHandbookManage] = SaasFeatureCatalog.Handbook,
[BackendPermissions.TenantVideoManage] = SaasFeatureCatalog.Video,
[BackendPermissions.TenantScorelineManage] = SaasFeatureCatalog.Scoreline,
[BackendPermissions.TenantSiteContentManage] = SaasFeatureCatalog.SiteContent
};
foreach (var pair in expected)
{
var module = PermissionModuleCatalog.ResolvePermissionModuleCode(pair.Key);
Assert.Equal(pair.Value, PermissionModuleCatalog.RequiredFeatures[module]);
}
}
private static string Describe(Type controller, MethodInfo action)
{
var controllerRoute = controller.GetCustomAttribute<RouteAttribute>()?.Template ?? string.Empty;