feat: strengthen P0 security and operations

This commit is contained in:
2026-08-01 11:20:02 +08:00
parent f776056834
commit 84c2b0b21d
77 changed files with 24185 additions and 355 deletions

View File

@@ -19,6 +19,53 @@ namespace Tiku.IntegrationTests.Api;
public sealed class PlatformAdminEndpointTests
{
[Fact]
public async Task Platform_staff_password_reset_revokes_sessions_and_requires_change()
{
await using var factory = new ApiTestFactory(configurationOverrides: new Dictionary<string, string?>
{
["Tenancy:Resolution:PlatformHosts:0"] = "localhost"
});
var administrator = await SeedPlatformAdminAsync(factory);
var target = await SeedAdditionalPlatformUserAsync(factory);
using var targetClient = factory.CreateClient();
var targetTokens = await targetClient.LoginAsPlatformAsync(target.Email);
using var adminClient = factory.CreateClient();
adminClient.UseAccessToken(await adminClient.LoginAsPlatformAsync(administrator.Email));
var reset = await adminClient.PostAsJsonAsync(
$"/api/platform-admin/staff/{target.UserId}/password-reset",
new AdministrativePasswordResetDto
{
TemporaryPassword = "TemporaryPassword2026",
Reason = "Platform staff recovery verification"
});
Assert.Equal(HttpStatusCode.NoContent, reset.StatusCode);
targetClient.UseAccessToken(targetTokens);
Assert.Equal(HttpStatusCode.Unauthorized, (await targetClient.GetAsync("/api/me")).StatusCode);
targetClient.DefaultRequestHeaders.Authorization = null;
var login = await targetClient.PostAsJsonAsync(
"/api/auth/login/password",
new PasswordLoginDto
{
Realm = AuthRealm.Platform,
Identifier = target.Email,
Password = "TemporaryPassword2026"
});
Assert.Equal(HttpStatusCode.OK, login.StatusCode);
Assert.Contains("password_change_required", await login.Content.ReadAsStringAsync(), StringComparison.Ordinal);
using var scope = factory.CreateSystemScope("Verify platform administrative password reset");
var dbContext = scope.ServiceProvider.GetRequiredService<TikuDbContext>();
Assert.True(await dbContext.Users.Where(item => item.Id == target.UserId).Select(item => item.ForcePasswordChange).SingleAsync());
Assert.True(await dbContext.AuditLogs.AnyAsync(item =>
item.TenantId == null &&
item.ActorUserId == administrator.UserId &&
item.Action == "auth.password.reset_by_administrator" &&
item.TargetId == target.UserId.ToString()));
}
[Fact]
public async Task Platform_super_admin_can_load_every_platform_console_bootstrap_endpoint()
{
@@ -506,6 +553,43 @@ public sealed class PlatformAdminEndpointTests
return await SeedPlatformUserAsync(factory, BackendPermissions.Platform);
}
private static async Task<(Guid UserId, string Email)> SeedAdditionalPlatformUserAsync(ApiTestFactory factory)
{
var userId = Guid.NewGuid();
var roleId = Guid.NewGuid();
var email = $"platform-target-{Guid.NewGuid():N}@example.test";
await factory.SeedAsync(
new User
{
Id = userId,
Email = email,
NormalizedEmail = email.ToUpperInvariant(),
UserName = email,
NormalizedUserName = email.ToUpperInvariant(),
Name = "Platform Reset Target",
PrimaryRole = "platform_staff",
RawProfile = JsonDefaults.Object()
}.WithTestPassword(),
new PlatformBackendRole
{
Id = roleId,
Code = $"platform_reset_target_{roleId:N}",
Name = "Platform Reset Target",
Status = BackendRoleStatus.Active
},
new PlatformBackendRolePermission
{
RoleId = roleId,
PermissionCode = BackendPermissions.PlatformDashboardView
},
new PlatformBackendUserRole
{
UserId = userId,
RoleId = roleId
});
return (userId, email);
}
private static async Task<(Guid UserId, string Email)> SeedPlatformUserAsync(
ApiTestFactory factory,
IEnumerable<string> platformPermissions)