using System.Net; using System.Text.Json; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Tiku.Application.Security; using Tiku.Domain.Common; using Tiku.Domain.Identity; using Tiku.Domain.Operations; using Tiku.Domain.Tenancy; using Tiku.Infrastructure.Persistence; namespace Tiku.IntegrationTests.Api; public sealed class BackofficeUiBootstrapTests { [Fact] public async Task TenantUiBootstrap_ReturnsOnlyMenusAllowedByEffectivePermissions() { var commandRecorder = new RecordingDbCommandInterceptor(); await using var factory = new ApiTestFactory(dbCommandInterceptor: commandRecorder); await factory.SeedBuiltinBackofficeCatalogAsync(); 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 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)); commandRecorder.Reset(); using var response = await client.GetAsync("/api/tenant/access/ui-bootstrap"); using var bootstrap = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); var firstRequestCommands = commandRecorder.Snapshot(); commandRecorder.Reset(); using var repeatedResponse = await client.GetAsync("/api/tenant/access/ui-bootstrap"); var repeatedRequestCommands = commandRecorder.Snapshot(); using var roleManagementResponse = await client.GetAsync("/api/tenant/access/bootstrap"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, repeatedResponse.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.True( firstRequestCommands.Count is >= 1 and <= 10, $"Expected at most 10 SQL commands, but captured {firstRequestCommands.Count}:{Environment.NewLine}{string.Join($"{Environment.NewLine}---{Environment.NewLine}", firstRequestCommands)}"); Assert.InRange(repeatedRequestCommands.Count, 1, firstRequestCommands.Count); AssertNoPerCodeCatalogExistenceQueries(firstRequestCommands); AssertNoPerCodeCatalogExistenceQueries(repeatedRequestCommands); Assert.Equal(HttpStatusCode.Forbidden, roleManagementResponse.StatusCode); } [Fact] public async Task PlatformUiBootstrap_DoesNotProbeCatalogPerCode() { var commandRecorder = new RecordingDbCommandInterceptor(); await using var factory = new ApiTestFactory( configurationOverrides: new Dictionary { ["Tenancy:Resolution:PlatformHosts:0"] = "localhost" }, dbCommandInterceptor: commandRecorder); await factory.SeedBuiltinBackofficeCatalogAsync(); var userId = Guid.NewGuid(); var roleId = Guid.NewGuid(); var email = $"platform-{Guid.NewGuid():N}@example.test"; await factory.SeedAsync( new User { Id = userId, Email = email, NormalizedEmail = email.ToUpperInvariant(), UserName = email, NormalizedUserName = email.ToUpperInvariant(), Name = "Platform UI Operator", PrimaryRole = "platform_admin", RawProfile = JsonDefaults.Object() }.WithTestPassword(), new PlatformBackendRole { Id = roleId, Code = $"platform_ui_{Guid.NewGuid():N}", Name = "Platform UI Operator", Status = BackendRoleStatus.Active }, new PlatformBackendRolePermission { RoleId = roleId, PermissionCode = BackendPermissions.PlatformDashboardView }, new PlatformBackendUserRole { UserId = userId, RoleId = roleId }); using var client = factory.CreateClient(); client.UseAccessToken(await client.LoginAsPlatformAsync(email)); commandRecorder.Reset(); using var response = await client.GetAsync("/api/platform/access/ui-bootstrap"); using var bootstrap = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); var firstRequestCommands = commandRecorder.Snapshot(); commandRecorder.Reset(); using var repeatedResponse = await client.GetAsync("/api/platform/access/ui-bootstrap"); var repeatedRequestCommands = commandRecorder.Snapshot(); using (var scope = factory.CreateSystemScope("Revoke cached platform UI permission")) { var dbContext = scope.ServiceProvider.GetRequiredService(); var permission = await dbContext.PlatformBackendRolePermissions.SingleAsync(item => item.RoleId == roleId && item.PermissionCode == BackendPermissions.PlatformDashboardView); dbContext.Remove(permission); await dbContext.SaveChangesAsync(); } using var revokedResponse = await client.GetAsync("/api/platform/access/ui-bootstrap"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, repeatedResponse.StatusCode); Assert.Equal(HttpStatusCode.Unauthorized, revokedResponse.StatusCode); Assert.Equal( [BackendPermissions.PlatformDashboardView], bootstrap.RootElement.GetProperty("permissionCodes").EnumerateArray().Select(item => item.GetString())); Assert.Equal( ["platform.dashboard"], bootstrap.RootElement.GetProperty("menus").EnumerateArray() .Select(item => item.GetProperty("code").GetString())); Assert.InRange(firstRequestCommands.Count, 1, 10); Assert.Contains(firstRequestCommands, IsPlatformPermissionQuery); Assert.DoesNotContain(repeatedRequestCommands, IsPlatformPermissionQuery); AssertNoPerCodeCatalogExistenceQueries(firstRequestCommands); AssertNoPerCodeCatalogExistenceQueries(repeatedRequestCommands); } private static void AssertNoPerCodeCatalogExistenceQueries(IEnumerable commands) { string[] catalogTables = ["saas_features", "permission_modules", "backend_permissions", "backend_menus"]; Assert.DoesNotContain(commands, command => command.TrimStart().StartsWith("SELECT EXISTS", StringComparison.OrdinalIgnoreCase) && catalogTables.Any(table => command.Contains(table, StringComparison.OrdinalIgnoreCase))); } private static bool IsPlatformPermissionQuery(string command) { return command.Contains("platform_backend_role_permissions", StringComparison.OrdinalIgnoreCase) && command.Contains("SELECT DISTINCT", StringComparison.OrdinalIgnoreCase); } }