feat: harden SaaS authentication and authorization

This commit is contained in:
2026-07-28 12:15:51 +08:00
parent f22f329d33
commit 5d2248efee
123 changed files with 9090 additions and 2822 deletions

View File

@@ -0,0 +1,91 @@
using System.Net;
using System.Text.Json;
using Tiku.Application.Backoffice;
using Tiku.Application.Security;
using Tiku.Domain.Common;
using Tiku.Domain.Identity;
using Tiku.Domain.Operations;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Auth;
namespace Tiku.IntegrationTests.Api;
public sealed class BackofficeUiBootstrapTests
{
[Fact]
public async Task TenantUiBootstrap_ReturnsOnlyMenusAllowedByEffectivePermissions()
{
await using var factory = new ApiTestFactory();
var tenantId = Guid.NewGuid();
var userId = Guid.NewGuid();
var roleId = Guid.NewGuid();
var phone = "13710000000";
await factory.SeedAsync(
new Tenant
{
Id = tenantId,
Slug = tenantId.ToString("N"),
Name = "Scoped UI Tenant",
Status = TenantStatus.Active,
Metadata = JsonDefaults.Object()
},
new User
{
Id = userId,
Phone = phone,
Name = "Dashboard Operator"
}.WithTestPassword(),
new TenantMembership
{
TenantId = tenantId,
UserId = userId,
Role = TenantRole.Student,
Status = MembershipStatus.Active
},
new BackendPermission
{
Code = BackendPermissions.TenantDashboardView,
Name = "Tenant dashboard",
Area = BackendPermissionArea.Tenant,
Module = "tenant_dashboard",
IsSystem = true
},
new TenantBackendRole
{
Id = roleId,
TenantId = tenantId,
Code = "dashboard_operator",
Name = "Dashboard Operator",
Status = BackendRoleStatus.Active,
DataScope = JsonSerializer.SerializeToElement(new { mode = "self" })
},
new TenantBackendRolePermission
{
TenantId = tenantId,
RoleId = roleId,
PermissionCode = BackendPermissions.TenantDashboardView
},
new TenantBackendUserRole
{
TenantId = tenantId,
UserId = userId,
RoleId = roleId
});
using var client = factory.CreateClient();
client.UseAccessToken(await client.LoginAsTenantAsync(tenantId, phone));
using var response = await client.GetAsync("/api/backoffice/tenant/ui-bootstrap");
using var bootstrap = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
using var roleManagementResponse = await client.GetAsync("/api/backoffice/tenant/bootstrap");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
[BackendPermissions.TenantDashboardView],
bootstrap.RootElement.GetProperty("permissionCodes").EnumerateArray().Select(item => item.GetString()));
Assert.Equal(
["tenant.dashboard"],
bootstrap.RootElement.GetProperty("menus").EnumerateArray().Select(item => item.GetProperty("code").GetString()));
Assert.Equal(HttpStatusCode.Forbidden, roleManagementResponse.StatusCode);
}
}