build-flow.api/tests/BuildFlow.Platform.Tests/Roles/AssignPermissionsCommandHandlerTests.cs
xiangning 16ba77f69f feat(platform): 实现权限版本控制即时失效旧token机制
- 在JWT中添加permver权限版本号claim,用于实时权限变更检测
- 实现PermissionVersionMiddleware中间件,在认证后授权前校验权限版本
- 修改AssignPermissionsCommandHandler,角色权限变更时自增相关用户权限版本号
- 修改AssignRolesCommandHandler,用户角色变更时自增权限版本号强制重登录
- 集成Redis存储权限版本镜像,支持分布式环境下的版本同步
- 添加PermissionVersion字段到User实体,用于存储权限版本号
- 实现分布式登录失败计数与账号锁定功能,增强安全防护
- 配置文件中新增AccessTokenMinutes和RefreshTokenDays可配置项
- 更新CORS策略配置,添加127.0.0.1本地访问支持
- 完善异常处理,统一使用ErrorCode枚举进行错误码管理
- 添加SOP测试单元设计文档,规范端到端测试流程
2026-07-07 17:18:05 +08:00

70 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using FluentAssertions;
using NSubstitute;
using BuildFlow.Platform.Application.Roles.Commands;
using BuildFlow.Platform.Application.Roles.Handlers;
using BuildFlow.Platform.Domain.Common;
using BuildFlow.Shared.Domain.Exceptions;
namespace BuildFlow.Platform.Tests.Roles;
/// <summary>
/// 分配权限 Command 处理器单元测试。覆盖分配成功 + 该角色所有用户版本号批量自增、权限不存在拒绝。
/// </summary>
public class AssignPermissionsCommandHandlerTests
{
[Fact]
public async Task Handle_ValidAssignment_ShouldBumpAllAffectedUsersVersion()
{
// Arrange:角色 A 关联两个用户,分配权限后两者版本号都应自增
var db = PlatformTestDb.CreateDbContext();
var roleId = Guid.NewGuid();
var permId = Guid.NewGuid();
var user1Id = Guid.NewGuid();
var user2Id = Guid.NewGuid();
db.Roles.Add(PlatformTestDb.WithAudit(new BuildFlow.Platform.Domain.Entities.Role { Id = roleId, Name = "Admin" }));
db.Permissions.Add(PlatformTestDb.WithAudit(new BuildFlow.Platform.Domain.Entities.Permission
{
Id = permId,
Name = "用户管理",
Code = "user:read",
}));
await PlatformTestDb.SeedUserAsync(db, user1Id, "u1", permissionVersion: 1);
await PlatformTestDb.SeedUserAsync(db, user2Id, "u2", permissionVersion: 1);
db.UserRoles.Add(new BuildFlow.Platform.Domain.Entities.UserRole { UserId = user1Id, RoleId = roleId, CreatedBy = "t", UpdatedBy = "t" });
db.UserRoles.Add(new BuildFlow.Platform.Domain.Entities.UserRole { UserId = user2Id, RoleId = roleId, CreatedBy = "t", UpdatedBy = "t" });
await db.SaveChangesAsync();
var versionStore = Substitute.For<IPermissionVersionStore>();
var handler = new AssignPermissionsCommandHandler(db, versionStore);
// Act
await handler.Handle(new AssignPermissionsCommand(roleId, [permId]), CancellationToken.None);
// Assert:两个受影响用户的版本号都自增(1 → 2)
var users = await db.Users.Where(u => u.Id == user1Id || u.Id == user2Id).ToListAsync();
users.Should().AllSatisfy(u => u.PermissionVersion.Should().Be(2));
await versionStore.Received(1).BumpAsync(
Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user1Id) && ids.Contains(user2Id)),
Arg.Any<CancellationToken>());
}
[Fact]
public async Task Handle_NonExistentPermission_ShouldThrowNotFound()
{
// Arrange
var db = PlatformTestDb.CreateDbContext();
var roleId = Guid.NewGuid();
db.Roles.Add(PlatformTestDb.WithAudit(new BuildFlow.Platform.Domain.Entities.Role { Id = roleId, Name = "Empty" }));
await db.SaveChangesAsync();
var handler = new AssignPermissionsCommandHandler(db, Substitute.For<IPermissionVersionStore>());
// Act
var act = () => handler.Handle(new AssignPermissionsCommand(roleId, [Guid.NewGuid()]), CancellationToken.None);
// Assert
await act.Should().ThrowAsync<NotFoundException>()
.WithMessage("*部分权限不存在*");
}
}