Переглянути джерело

✅ test(auth): 添加角色权限验证测试

- 添加角色权限验证集成测试,覆盖不同角色用户的令牌生成与验证
- 测试管理员和普通用户角色的令牌是否包含正确角色信息

🐛 fix(auth): 修复登录错误提示问题

- 添加账户禁用错误的捕获和处理
- 根据不同错误类型返回更准确的错误消息:账户已禁用或用户名密码错误
yourname 2 місяців тому
батько
коміт
1c423818f7

+ 53 - 0
src/server/api/auth/__tests__/auth.integration.test.ts

@@ -247,6 +247,59 @@ describe('认证API集成测试 (使用hono/testing)', () => {
     });
   });
 
+  describe('角色权限验证测试', () => {
+    it('应该为不同角色的用户生成包含正确角色信息的令牌', async () => {
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      if (!dataSource) throw new Error('Database not initialized');
+
+      // 创建管理员角色
+      const adminRole = await TestDataFactory.createTestRole(dataSource, {
+        name: 'admin',
+        permissions: ['user:create', 'user:delete', 'user:update']
+      });
+
+      // 创建普通用户角色
+      const userRole = await TestDataFactory.createTestRole(dataSource, {
+        name: 'user',
+        permissions: ['user:read']
+      });
+
+      // 创建管理员用户
+      const adminUser = await TestDataFactory.createTestUser(dataSource, {
+        username: 'admin_user',
+        password: 'TestPassword123!',
+        email: 'admin@example.com'
+      });
+
+      // 创建普通用户
+      const regularUser = await TestDataFactory.createTestUser(dataSource, {
+        username: 'regular_user',
+        password: 'TestPassword123!',
+        email: 'regular@example.com'
+      });
+
+      // 分配角色
+      await userService.assignRoles(adminUser.id, [adminRole.id]);
+      await userService.assignRoles(regularUser.id, [userRole.id]);
+
+      // 重新加载用户以确保角色信息正确加载
+      const adminUserWithRoles = await userService.getUserById(adminUser.id);
+      const regularUserWithRoles = await userService.getUserById(regularUser.id);
+
+      // 生成令牌并验证角色信息
+      const adminToken = authService.generateToken(adminUserWithRoles!);
+      const regularToken = authService.generateToken(regularUserWithRoles!);
+
+      // 验证管理员令牌包含admin角色
+      const adminDecoded = authService.verifyToken(adminToken);
+      expect(adminDecoded.roles).toContain('admin');
+
+      // 验证普通用户令牌包含user角色
+      const regularDecoded = authService.verifyToken(regularToken);
+      expect(regularDecoded.roles).toContain('user');
+    });
+  });
+
   describe('错误处理测试', () => {
     it('应该正确处理认证失败错误', async () => {
       const loginData = {

+ 4 - 2
src/server/api/auth/login/password.ts

@@ -78,11 +78,13 @@ const app = new OpenAPIHono<AuthContext>().openapi(loginRoute, async (c) => {
   } catch (error) {
     // 认证相关错误返回401
     if (error instanceof Error &&
-        (error.message.includes('User not found') || error.message.includes('Invalid password'))) {
+        (error.message.includes('User not found') ||
+         error.message.includes('Invalid password') ||
+         error.message.includes('User account is disabled'))) {
       return c.json(
         {
           code: 401,
-          message: '用户名或密码错误'
+          message: error.message.includes('User account is disabled') ? '账户已禁用' : '用户名或密码错误'
         },
         401
       )