feat: 完善管理员系统和用户管理模块

- 更新管理员控制器和数据库管理功能
- 完善管理员操作日志系统
- 添加全面的属性测试覆盖
- 优化用户管理和用户档案服务
- 更新代码检查规范文档

功能改进:
- 增强管理员权限验证
- 完善操作日志记录
- 优化数据库管理接口
- 提升系统安全性和可维护性
This commit is contained in:
moyin
2026-01-09 17:05:08 +08:00
parent 8816b29b0a
commit 5f662ef091
30 changed files with 3881 additions and 599 deletions

View File

@@ -22,13 +22,13 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AdminDatabaseController } from '../../controllers/admin_database.controller';
import { DatabaseManagementService } from '../../services/database_management.service';
import { AdminOperationLogService } from '../../services/admin_operation_log.service';
import { AdminOperationLogInterceptor } from '../../admin_operation_log.interceptor';
import { AdminDatabaseExceptionFilter } from '../../admin_database_exception.filter';
import { AdminGuard } from '../../admin.guard';
import { UserStatus } from '../../../../core/db/users/user_status.enum';
import { AdminDatabaseController } from './admin_database.controller';
import { DatabaseManagementService } from './database_management.service';
import { AdminOperationLogService } from './admin_operation_log.service';
import { AdminOperationLogInterceptor } from './admin_operation_log.interceptor';
import { AdminDatabaseExceptionFilter } from './admin_database_exception.filter';
import { AdminGuard } from './admin.guard';
import { UserStatus } from '../user_mgmt/user_status.enum';
import {
PropertyTestRunner,
PropertyTestGenerators,
@@ -40,8 +40,160 @@ describe('Property Test: API响应格式一致性', () => {
let app: INestApplication;
let module: TestingModule;
let controller: AdminDatabaseController;
let mockDatabaseService: any;
beforeAll(async () => {
mockDatabaseService = {
getUserList: jest.fn().mockImplementation((limit, offset) => {
return Promise.resolve({
success: true,
data: {
items: [],
total: 0,
limit: limit || 20,
offset: offset || 0,
has_more: false
},
message: '获取用户列表成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getUserById: jest.fn().mockImplementation((id) => {
const user = PropertyTestGenerators.generateUser();
return Promise.resolve({
success: true,
data: { ...user, id: id.toString() },
message: '获取用户详情成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
createUser: jest.fn().mockImplementation((userData) => {
return Promise.resolve({
success: true,
data: { ...userData, id: '1' },
message: '创建用户成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
updateUser: jest.fn().mockImplementation((id, updateData) => {
const user = PropertyTestGenerators.generateUser();
return Promise.resolve({
success: true,
data: { ...user, ...updateData, id: id.toString() },
message: '更新用户成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
deleteUser: jest.fn().mockImplementation((id) => {
return Promise.resolve({
success: true,
data: { deleted: true, id: id.toString() },
message: '删除用户成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
searchUsers: jest.fn().mockImplementation((searchTerm, limit) => {
return Promise.resolve({
success: true,
data: {
items: [],
total: 0,
limit: limit || 20,
offset: 0,
has_more: false
},
message: '搜索用户成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getUserProfileList: jest.fn().mockImplementation((limit, offset) => {
return Promise.resolve({
success: true,
data: {
items: [],
total: 0,
limit: limit || 20,
offset: offset || 0,
has_more: false
},
message: '获取用户档案列表成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getUserProfileById: jest.fn().mockImplementation((id) => {
const profile = PropertyTestGenerators.generateUserProfile();
return Promise.resolve({
success: true,
data: { ...profile, id: id.toString() },
message: '获取用户档案详情成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getUserProfilesByMap: jest.fn().mockImplementation((map, limit, offset) => {
return Promise.resolve({
success: true,
data: {
items: [],
total: 0,
limit: limit || 20,
offset: offset || 0,
has_more: false
},
message: '按地图获取用户档案成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getZulipAccountList: jest.fn().mockImplementation((limit, offset) => {
return Promise.resolve({
success: true,
data: {
items: [],
total: 0,
limit: limit || 20,
offset: offset || 0,
has_more: false
},
message: '获取Zulip账号列表成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getZulipAccountById: jest.fn().mockImplementation((id) => {
const account = PropertyTestGenerators.generateZulipAccount();
return Promise.resolve({
success: true,
data: { ...account, id: id.toString() },
message: '获取Zulip账号详情成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
}),
getZulipAccountStatistics: jest.fn().mockImplementation(() => {
return Promise.resolve({
success: true,
data: {
active: 0,
inactive: 0,
suspended: 0,
error: 0,
total: 0
},
message: '获取Zulip账号统计成功',
timestamp: new Date().toISOString(),
request_id: 'test_' + Date.now()
});
})
};
module = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
@@ -51,7 +203,10 @@ describe('Property Test: API响应格式一致性', () => {
],
controllers: [AdminDatabaseController],
providers: [
DatabaseManagementService,
{
provide: DatabaseManagementService,
useValue: mockDatabaseService
},
{
provide: AdminOperationLogService,
useValue: {
@@ -69,71 +224,6 @@ describe('Property Test: API响应格式一致性', () => {
useValue: {
intercept: jest.fn().mockImplementation((context, next) => next.handle())
}
},
{
provide: 'UsersService',
useValue: {
findAll: jest.fn().mockResolvedValue([]),
findOne: jest.fn().mockImplementation(() => {
const user = PropertyTestGenerators.generateUser();
return Promise.resolve({ ...user, id: BigInt(1) });
}),
create: jest.fn().mockImplementation((userData) => {
return Promise.resolve({ ...userData, id: BigInt(1) });
}),
update: jest.fn().mockImplementation((id, updateData) => {
const user = PropertyTestGenerators.generateUser();
return Promise.resolve({ ...user, ...updateData, id });
}),
remove: jest.fn().mockResolvedValue(undefined),
search: jest.fn().mockResolvedValue([]),
count: jest.fn().mockResolvedValue(0)
}
},
{
provide: 'IUserProfilesService',
useValue: {
findAll: jest.fn().mockResolvedValue([]),
findOne: jest.fn().mockImplementation(() => {
const profile = PropertyTestGenerators.generateUserProfile();
return Promise.resolve({ ...profile, id: BigInt(1) });
}),
create: jest.fn().mockImplementation((profileData) => {
return Promise.resolve({ ...profileData, id: BigInt(1) });
}),
update: jest.fn().mockImplementation((id, updateData) => {
const profile = PropertyTestGenerators.generateUserProfile();
return Promise.resolve({ ...profile, ...updateData, id });
}),
remove: jest.fn().mockResolvedValue(undefined),
findByMap: jest.fn().mockResolvedValue([]),
count: jest.fn().mockResolvedValue(0)
}
},
{
provide: 'ZulipAccountsService',
useValue: {
findMany: jest.fn().mockResolvedValue({ accounts: [] }),
findById: jest.fn().mockImplementation(() => {
const account = PropertyTestGenerators.generateZulipAccount();
return Promise.resolve({ ...account, id: '1' });
}),
create: jest.fn().mockImplementation((accountData) => {
return Promise.resolve({ ...accountData, id: '1' });
}),
update: jest.fn().mockImplementation((id, updateData) => {
const account = PropertyTestGenerators.generateZulipAccount();
return Promise.resolve({ ...account, ...updateData, id });
}),
delete: jest.fn().mockResolvedValue(undefined),
getStatusStatistics: jest.fn().mockResolvedValue({
active: 0,
inactive: 0,
suspended: 0,
error: 0,
total: 0
})
}
}
]
})