forked from datawhale/whale-town-end
chore: 更新项目配置和核心服务
- 更新package.json和jest配置 - 更新main.ts启动配置 - 完善用户管理和数据库服务 - 更新安全核心模块 - 优化Zulip核心服务 配置改进: - 统一项目依赖管理 - 优化测试配置 - 完善服务模块化架构
This commit is contained in:
@@ -33,6 +33,7 @@ import { UserStatus } from './user_status.enum';
|
||||
import { validate } from 'class-validator';
|
||||
import { plainToClass } from 'class-transformer';
|
||||
import { BaseUsersService } from './base_users.service';
|
||||
import { USER_ROLES, QUERY_LIMITS, ERROR_MESSAGES, DATABASE_CONSTANTS, ValidationUtils, PerformanceMonitor } from './users.constants';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService extends BaseUsersService {
|
||||
@@ -49,11 +50,9 @@ export class UsersService extends BaseUsersService {
|
||||
*
|
||||
* 技术实现:
|
||||
* 1. 验证输入数据的格式和完整性
|
||||
* 2. 使用class-validator进行DTO数据验证
|
||||
* 3. 创建用户实体并设置默认值
|
||||
* 4. 保存用户数据到数据库
|
||||
* 5. 记录操作日志和性能指标
|
||||
* 6. 返回创建成功的用户实体
|
||||
* 2. 创建用户实体并设置默认值
|
||||
* 3. 保存用户数据到数据库
|
||||
* 4. 记录操作日志和性能指标
|
||||
*
|
||||
* @param createUserDto 创建用户的数据传输对象,包含用户基本信息
|
||||
* @returns 创建成功的用户实体,包含自动生成的ID和时间戳
|
||||
@@ -71,7 +70,7 @@ export class UsersService extends BaseUsersService {
|
||||
* ```
|
||||
*/
|
||||
async create(createUserDto: CreateUserDto): Promise<Users> {
|
||||
const startTime = Date.now();
|
||||
const monitor = PerformanceMonitor.create();
|
||||
|
||||
this.logger.log('开始创建用户', {
|
||||
operation: 'create',
|
||||
@@ -82,55 +81,25 @@ export class UsersService extends BaseUsersService {
|
||||
|
||||
try {
|
||||
// 验证DTO
|
||||
const dto = plainToClass(CreateUserDto, createUserDto);
|
||||
const validationErrors = await validate(dto);
|
||||
|
||||
if (validationErrors.length > 0) {
|
||||
const errorMessages = validationErrors.map(error =>
|
||||
Object.values(error.constraints || {}).join(', ')
|
||||
).join('; ');
|
||||
|
||||
this.logger.warn('用户创建失败:数据验证失败', {
|
||||
operation: 'create',
|
||||
username: createUserDto.username,
|
||||
email: createUserDto.email,
|
||||
validationErrors: errorMessages
|
||||
});
|
||||
|
||||
throw new BadRequestException(`数据验证失败: ${errorMessages}`);
|
||||
}
|
||||
await this.validateCreateUserDto(createUserDto);
|
||||
|
||||
// 创建用户实体
|
||||
const user = new Users();
|
||||
user.username = createUserDto.username;
|
||||
user.email = createUserDto.email || null;
|
||||
user.phone = createUserDto.phone || null;
|
||||
user.password_hash = createUserDto.password_hash || null;
|
||||
user.nickname = createUserDto.nickname;
|
||||
user.github_id = createUserDto.github_id || null;
|
||||
user.avatar_url = createUserDto.avatar_url || null;
|
||||
user.role = createUserDto.role || 1;
|
||||
user.email_verified = createUserDto.email_verified || false;
|
||||
user.status = createUserDto.status || UserStatus.ACTIVE;
|
||||
const user = this.buildUserEntity(createUserDto);
|
||||
|
||||
// 保存到数据库
|
||||
const savedUser = await this.usersRepository.save(user);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
this.logger.log('用户创建成功', {
|
||||
operation: 'create',
|
||||
userId: savedUser.id.toString(),
|
||||
username: savedUser.username,
|
||||
email: savedUser.email,
|
||||
duration,
|
||||
duration: monitor.getDuration(),
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
return savedUser;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
if (error instanceof BadRequestException) {
|
||||
throw error;
|
||||
}
|
||||
@@ -140,14 +109,60 @@ export class UsersService extends BaseUsersService {
|
||||
username: createUserDto.username,
|
||||
email: createUserDto.email,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
duration,
|
||||
duration: monitor.getDuration(),
|
||||
timestamp: new Date().toISOString()
|
||||
}, error instanceof Error ? error.stack : undefined);
|
||||
|
||||
throw new BadRequestException('用户创建失败,请稍后重试');
|
||||
throw new BadRequestException(ERROR_MESSAGES.USER_CREATE_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证创建用户DTO
|
||||
*
|
||||
* @param createUserDto 用户数据
|
||||
* @throws BadRequestException 当数据验证失败时
|
||||
*/
|
||||
private async validateCreateUserDto(createUserDto: CreateUserDto): Promise<void> {
|
||||
const dto = plainToClass(CreateUserDto, createUserDto);
|
||||
const validationErrors = await validate(dto);
|
||||
|
||||
if (validationErrors.length > 0) {
|
||||
const errorMessages = ValidationUtils.formatValidationErrors(validationErrors);
|
||||
|
||||
this.logger.warn('用户创建失败:数据验证失败', {
|
||||
operation: 'create',
|
||||
username: createUserDto.username,
|
||||
email: createUserDto.email,
|
||||
validationErrors: errorMessages
|
||||
});
|
||||
|
||||
throw new BadRequestException(`${ERROR_MESSAGES.VALIDATION_FAILED}: ${errorMessages}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建用户实体
|
||||
*
|
||||
* @param createUserDto 用户数据
|
||||
* @returns 用户实体
|
||||
*/
|
||||
private buildUserEntity(createUserDto: CreateUserDto): Users {
|
||||
const user = new Users();
|
||||
user.username = createUserDto.username;
|
||||
user.email = createUserDto.email || null;
|
||||
user.phone = createUserDto.phone || null;
|
||||
user.password_hash = createUserDto.password_hash || null;
|
||||
user.nickname = createUserDto.nickname;
|
||||
user.github_id = createUserDto.github_id || null;
|
||||
user.avatar_url = createUserDto.avatar_url || null;
|
||||
user.role = createUserDto.role || USER_ROLES.NORMAL_USER;
|
||||
user.email_verified = createUserDto.email_verified || false;
|
||||
user.status = createUserDto.status || UserStatus.ACTIVE;
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新用户(带重复检查)
|
||||
*
|
||||
@@ -171,15 +186,13 @@ export class UsersService extends BaseUsersService {
|
||||
* ```
|
||||
*/
|
||||
async createWithDuplicateCheck(createUserDto: CreateUserDto): Promise<Users> {
|
||||
const startTime = Date.now();
|
||||
const monitor = PerformanceMonitor.create();
|
||||
|
||||
this.logger.log('开始创建用户(带重复检查)', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
this.logStart('创建用户(带重复检查)', {
|
||||
username: createUserDto.username,
|
||||
email: createUserDto.email,
|
||||
phone: createUserDto.phone,
|
||||
github_id: createUserDto.github_id,
|
||||
timestamp: new Date().toISOString()
|
||||
github_id: createUserDto.github_id
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -189,34 +202,17 @@ export class UsersService extends BaseUsersService {
|
||||
// 调用普通的创建方法
|
||||
const user = await this.create(createUserDto);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
this.logger.log('用户创建成功(带重复检查)', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
this.logSuccess('创建用户(带重复检查)', {
|
||||
userId: user.id.toString(),
|
||||
username: user.username,
|
||||
duration,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
username: user.username
|
||||
}, monitor.getDuration());
|
||||
|
||||
return user;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
if (error instanceof ConflictException || error instanceof BadRequestException) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.error('用户创建系统异常(带重复检查)', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
this.handleServiceError(error, '创建用户(带重复检查)', {
|
||||
username: createUserDto.username,
|
||||
email: createUserDto.email,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
duration,
|
||||
timestamp: new Date().toISOString()
|
||||
}, error instanceof Error ? error.stack : undefined);
|
||||
|
||||
throw new BadRequestException('用户创建失败,请稍后重试');
|
||||
duration: monitor.getDuration()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,63 +223,84 @@ export class UsersService extends BaseUsersService {
|
||||
* @throws ConflictException 当发现重复数据时
|
||||
*/
|
||||
private async validateUniqueness(createUserDto: CreateUserDto): Promise<void> {
|
||||
// 检查用户名是否已存在
|
||||
if (createUserDto.username) {
|
||||
await this.checkUsernameUniqueness(createUserDto.username);
|
||||
await this.checkEmailUniqueness(createUserDto.email);
|
||||
await this.checkPhoneUniqueness(createUserDto.phone);
|
||||
await this.checkGithubIdUniqueness(createUserDto.github_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户名唯一性
|
||||
*/
|
||||
private async checkUsernameUniqueness(username?: string): Promise<void> {
|
||||
if (username) {
|
||||
const existingUser = await this.usersRepository.findOne({
|
||||
where: { username: createUserDto.username }
|
||||
where: { username }
|
||||
});
|
||||
if (existingUser) {
|
||||
this.logger.warn('用户创建失败:用户名已存在', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
username: createUserDto.username,
|
||||
operation: 'uniqueness_check',
|
||||
username,
|
||||
existingUserId: existingUser.id.toString()
|
||||
});
|
||||
throw new ConflictException('用户名已存在');
|
||||
throw new ConflictException(ERROR_MESSAGES.USERNAME_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查邮箱是否已存在
|
||||
if (createUserDto.email) {
|
||||
/**
|
||||
* 检查邮箱唯一性
|
||||
*/
|
||||
private async checkEmailUniqueness(email?: string): Promise<void> {
|
||||
if (email) {
|
||||
const existingEmail = await this.usersRepository.findOne({
|
||||
where: { email: createUserDto.email }
|
||||
where: { email }
|
||||
});
|
||||
if (existingEmail) {
|
||||
this.logger.warn('用户创建失败:邮箱已存在', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
email: createUserDto.email,
|
||||
operation: 'uniqueness_check',
|
||||
email,
|
||||
existingUserId: existingEmail.id.toString()
|
||||
});
|
||||
throw new ConflictException('邮箱已存在');
|
||||
throw new ConflictException(ERROR_MESSAGES.EMAIL_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查手机号是否已存在
|
||||
if (createUserDto.phone) {
|
||||
/**
|
||||
* 检查手机号唯一性
|
||||
*/
|
||||
private async checkPhoneUniqueness(phone?: string): Promise<void> {
|
||||
if (phone) {
|
||||
const existingPhone = await this.usersRepository.findOne({
|
||||
where: { phone: createUserDto.phone }
|
||||
where: { phone }
|
||||
});
|
||||
if (existingPhone) {
|
||||
this.logger.warn('用户创建失败:手机号已存在', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
phone: createUserDto.phone,
|
||||
operation: 'uniqueness_check',
|
||||
phone,
|
||||
existingUserId: existingPhone.id.toString()
|
||||
});
|
||||
throw new ConflictException('手机号已存在');
|
||||
throw new ConflictException(ERROR_MESSAGES.PHONE_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查GitHub ID是否已存在
|
||||
if (createUserDto.github_id) {
|
||||
/**
|
||||
* 检查GitHub ID唯一性
|
||||
*/
|
||||
private async checkGithubIdUniqueness(githubId?: string): Promise<void> {
|
||||
if (githubId) {
|
||||
const existingGithub = await this.usersRepository.findOne({
|
||||
where: { github_id: createUserDto.github_id }
|
||||
where: { github_id: githubId }
|
||||
});
|
||||
if (existingGithub) {
|
||||
this.logger.warn('用户创建失败:GitHub ID已存在', {
|
||||
operation: 'createWithDuplicateCheck',
|
||||
github_id: createUserDto.github_id,
|
||||
operation: 'uniqueness_check',
|
||||
github_id: githubId,
|
||||
existingUserId: existingGithub.id.toString()
|
||||
});
|
||||
throw new ConflictException('GitHub ID已存在');
|
||||
throw new ConflictException(ERROR_MESSAGES.GITHUB_ID_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,15 +313,15 @@ export class UsersService extends BaseUsersService {
|
||||
* @param includeDeleted 是否包含已删除用户,默认false
|
||||
* @returns 用户列表
|
||||
*/
|
||||
async findAll(limit: number = 100, offset: number = 0, includeDeleted: boolean = false): Promise<Users[]> {
|
||||
// Temporarily removed deleted_at filtering since the column doesn't exist in the database
|
||||
async findAll(limit: number = QUERY_LIMITS.DEFAULT_LIMIT, offset: number = 0, includeDeleted: boolean = false): Promise<Users[]> {
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
const whereCondition = {};
|
||||
|
||||
return await this.usersRepository.find({
|
||||
where: whereCondition,
|
||||
take: limit,
|
||||
skip: offset,
|
||||
order: { created_at: 'DESC' }
|
||||
order: { created_at: DATABASE_CONSTANTS.ORDER_DESC }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -317,7 +334,7 @@ export class UsersService extends BaseUsersService {
|
||||
* @throws NotFoundException 当用户不存在时
|
||||
*/
|
||||
async findOne(id: bigint, includeDeleted: boolean = false): Promise<Users> {
|
||||
// Temporarily removed deleted_at filtering since the column doesn't exist in the database
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
const whereCondition = { id };
|
||||
|
||||
const user = await this.usersRepository.findOne({
|
||||
@@ -339,7 +356,7 @@ export class UsersService extends BaseUsersService {
|
||||
* @returns 用户实体或null
|
||||
*/
|
||||
async findByUsername(username: string, includeDeleted: boolean = false): Promise<Users | null> {
|
||||
// Temporarily removed deleted_at filtering since the column doesn't exist in the database
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
const whereCondition = { username };
|
||||
|
||||
return await this.usersRepository.findOne({
|
||||
@@ -355,7 +372,7 @@ export class UsersService extends BaseUsersService {
|
||||
* @returns 用户实体或null
|
||||
*/
|
||||
async findByEmail(email: string, includeDeleted: boolean = false): Promise<Users | null> {
|
||||
// Temporarily removed deleted_at filtering since the column doesn't exist in the database
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
const whereCondition = { email };
|
||||
|
||||
return await this.usersRepository.findOne({
|
||||
@@ -371,7 +388,7 @@ export class UsersService extends BaseUsersService {
|
||||
* @returns 用户实体或null
|
||||
*/
|
||||
async findByGithubId(githubId: string, includeDeleted: boolean = false): Promise<Users | null> {
|
||||
// Temporarily removed deleted_at filtering since the column doesn't exist in the database
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
const whereCondition = { github_id: githubId };
|
||||
|
||||
return await this.usersRepository.findOne({
|
||||
@@ -407,7 +424,7 @@ export class UsersService extends BaseUsersService {
|
||||
* ```
|
||||
*/
|
||||
async update(id: bigint, updateData: Partial<CreateUserDto>): Promise<Users> {
|
||||
const startTime = Date.now();
|
||||
const monitor = PerformanceMonitor.create();
|
||||
|
||||
this.logger.log('开始更新用户信息', {
|
||||
operation: 'update',
|
||||
@@ -421,70 +438,7 @@ export class UsersService extends BaseUsersService {
|
||||
const existingUser = await this.findOne(id);
|
||||
|
||||
// 2. 检查更新数据的唯一性约束 - 防止违反数据库唯一约束
|
||||
|
||||
// 2.1 检查用户名唯一性 - 只有当用户名确实发生变化时才检查
|
||||
if (updateData.username && updateData.username !== existingUser.username) {
|
||||
const usernameExists = await this.usersRepository.findOne({
|
||||
where: { username: updateData.username }
|
||||
});
|
||||
if (usernameExists) {
|
||||
this.logger.warn('用户更新失败:用户名已存在', {
|
||||
operation: 'update',
|
||||
userId: id.toString(),
|
||||
conflictUsername: updateData.username,
|
||||
existingUserId: usernameExists.id.toString()
|
||||
});
|
||||
throw new ConflictException('用户名已存在');
|
||||
}
|
||||
}
|
||||
|
||||
// 2.2 检查邮箱唯一性 - 只有当邮箱确实发生变化时才检查
|
||||
if (updateData.email && updateData.email !== existingUser.email) {
|
||||
const emailExists = await this.usersRepository.findOne({
|
||||
where: { email: updateData.email }
|
||||
});
|
||||
if (emailExists) {
|
||||
this.logger.warn('用户更新失败:邮箱已存在', {
|
||||
operation: 'update',
|
||||
userId: id.toString(),
|
||||
conflictEmail: updateData.email,
|
||||
existingUserId: emailExists.id.toString()
|
||||
});
|
||||
throw new ConflictException('邮箱已存在');
|
||||
}
|
||||
}
|
||||
|
||||
// 2.3 检查手机号唯一性 - 只有当手机号确实发生变化时才检查
|
||||
if (updateData.phone && updateData.phone !== existingUser.phone) {
|
||||
const phoneExists = await this.usersRepository.findOne({
|
||||
where: { phone: updateData.phone }
|
||||
});
|
||||
if (phoneExists) {
|
||||
this.logger.warn('用户更新失败:手机号已存在', {
|
||||
operation: 'update',
|
||||
userId: id.toString(),
|
||||
conflictPhone: updateData.phone,
|
||||
existingUserId: phoneExists.id.toString()
|
||||
});
|
||||
throw new ConflictException('手机号已存在');
|
||||
}
|
||||
}
|
||||
|
||||
// 2.4 检查GitHub ID唯一性 - 只有当GitHub ID确实发生变化时才检查
|
||||
if (updateData.github_id && updateData.github_id !== existingUser.github_id) {
|
||||
const githubExists = await this.usersRepository.findOne({
|
||||
where: { github_id: updateData.github_id }
|
||||
});
|
||||
if (githubExists) {
|
||||
this.logger.warn('用户更新失败:GitHub ID已存在', {
|
||||
operation: 'update',
|
||||
userId: id.toString(),
|
||||
conflictGithubId: updateData.github_id,
|
||||
existingUserId: githubExists.id.toString()
|
||||
});
|
||||
throw new ConflictException('GitHub ID已存在');
|
||||
}
|
||||
}
|
||||
await this.checkUpdateUniqueness(id, updateData);
|
||||
|
||||
// 3. 合并更新数据 - 使用Object.assign将新数据合并到现有实体
|
||||
Object.assign(existingUser, updateData);
|
||||
@@ -492,20 +446,16 @@ export class UsersService extends BaseUsersService {
|
||||
// 4. 保存更新后的用户信息 - TypeORM会自动更新updated_at字段
|
||||
const updatedUser = await this.usersRepository.save(existingUser);
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
this.logger.log('用户信息更新成功', {
|
||||
operation: 'update',
|
||||
userId: id.toString(),
|
||||
updateFields: Object.keys(updateData),
|
||||
duration,
|
||||
duration: monitor.getDuration(),
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
return updatedUser;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
if (error instanceof NotFoundException || error instanceof ConflictException) {
|
||||
throw error;
|
||||
}
|
||||
@@ -515,11 +465,11 @@ export class UsersService extends BaseUsersService {
|
||||
userId: id.toString(),
|
||||
updateData,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
duration,
|
||||
duration: monitor.getDuration(),
|
||||
timestamp: new Date().toISOString()
|
||||
}, error instanceof Error ? error.stack : undefined);
|
||||
|
||||
throw new BadRequestException('用户更新失败,请稍后重试');
|
||||
throw new BadRequestException(ERROR_MESSAGES.USER_UPDATE_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +501,7 @@ export class UsersService extends BaseUsersService {
|
||||
* ```
|
||||
*/
|
||||
async remove(id: bigint): Promise<{ affected: number; message: string }> {
|
||||
const startTime = Date.now();
|
||||
const monitor = PerformanceMonitor.create();
|
||||
|
||||
this.logger.log('开始删除用户', {
|
||||
operation: 'remove',
|
||||
@@ -571,20 +521,16 @@ export class UsersService extends BaseUsersService {
|
||||
message: `成功删除ID为 ${id} 的用户`
|
||||
};
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
this.logger.log('用户删除成功', {
|
||||
operation: 'remove',
|
||||
userId: id.toString(),
|
||||
affected: deleteResult.affected,
|
||||
duration,
|
||||
duration: monitor.getDuration(),
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
return deleteResult;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
if (error instanceof NotFoundException) {
|
||||
throw error;
|
||||
}
|
||||
@@ -593,11 +539,38 @@ export class UsersService extends BaseUsersService {
|
||||
operation: 'remove',
|
||||
userId: id.toString(),
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
duration,
|
||||
duration: monitor.getDuration(),
|
||||
timestamp: new Date().toISOString()
|
||||
}, error instanceof Error ? error.stack : undefined);
|
||||
|
||||
throw new BadRequestException('用户删除失败,请稍后重试');
|
||||
throw new BadRequestException(ERROR_MESSAGES.USER_DELETE_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查更新数据的唯一性约束
|
||||
*
|
||||
* @param id 用户ID
|
||||
* @param updateData 更新数据
|
||||
* @throws ConflictException 当发现冲突时
|
||||
*/
|
||||
private async checkUpdateUniqueness(id: bigint, updateData: Partial<CreateUserDto>): Promise<void> {
|
||||
const existingUser = await this.findOne(id);
|
||||
|
||||
if (updateData.username && updateData.username !== existingUser.username) {
|
||||
await this.checkUsernameUniqueness(updateData.username);
|
||||
}
|
||||
|
||||
if (updateData.email && updateData.email !== existingUser.email) {
|
||||
await this.checkEmailUniqueness(updateData.email);
|
||||
}
|
||||
|
||||
if (updateData.phone && updateData.phone !== existingUser.phone) {
|
||||
await this.checkPhoneUniqueness(updateData.phone);
|
||||
}
|
||||
|
||||
if (updateData.github_id && updateData.github_id !== existingUser.github_id) {
|
||||
await this.checkGithubIdUniqueness(updateData.github_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,9 +582,7 @@ export class UsersService extends BaseUsersService {
|
||||
*/
|
||||
async softRemove(id: bigint): Promise<Users> {
|
||||
const user = await this.findOne(id);
|
||||
// Temporarily disabled soft delete since deleted_at column doesn't exist
|
||||
// user.deleted_at = new Date();
|
||||
// For now, just return the user without modification
|
||||
// 注意:软删除功能暂未实现,当前仅返回用户实体
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -661,12 +632,12 @@ export class UsersService extends BaseUsersService {
|
||||
* @returns 用户列表
|
||||
*/
|
||||
async findByRole(role: number, includeDeleted: boolean = false): Promise<Users[]> {
|
||||
// Temporarily removed deleted_at filtering since the column doesn't exist in the database
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
const whereCondition = { role };
|
||||
|
||||
return await this.usersRepository.find({
|
||||
where: whereCondition,
|
||||
order: { created_at: 'DESC' }
|
||||
order: { created_at: DATABASE_CONSTANTS.ORDER_DESC }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -700,8 +671,8 @@ export class UsersService extends BaseUsersService {
|
||||
* const adminUsers = await usersService.search('admin');
|
||||
* ```
|
||||
*/
|
||||
async search(keyword: string, limit: number = 20, includeDeleted: boolean = false): Promise<Users[]> {
|
||||
const startTime = Date.now();
|
||||
async search(keyword: string, limit: number = QUERY_LIMITS.DEFAULT_SEARCH_LIMIT, includeDeleted: boolean = false): Promise<Users[]> {
|
||||
const monitor = PerformanceMonitor.create();
|
||||
|
||||
this.logStart('搜索用户', { keyword, limit, includeDeleted });
|
||||
|
||||
@@ -709,37 +680,35 @@ export class UsersService extends BaseUsersService {
|
||||
// 1. 构建查询 - 使用QueryBuilder支持复杂的WHERE条件
|
||||
const queryBuilder = this.usersRepository.createQueryBuilder('user');
|
||||
|
||||
// 2. 添加搜索条件 - 在用户名和昵称中进行模糊匹配
|
||||
// 添加搜索条件 - 在用户名和昵称中进行模糊匹配
|
||||
let whereClause = 'user.username LIKE :keyword OR user.nickname LIKE :keyword';
|
||||
|
||||
// 3. 添加软删除过滤条件 - temporarily disabled since deleted_at column doesn't exist
|
||||
// if (!includeDeleted) {
|
||||
// whereClause += ' AND user.deleted_at IS NULL';
|
||||
// }
|
||||
// 注意:软删除功能暂未实现,includeDeleted参数预留用于未来扩展
|
||||
|
||||
const result = await queryBuilder
|
||||
.where(whereClause, {
|
||||
keyword: `%${keyword}%` // 前后加%实现模糊匹配
|
||||
})
|
||||
.orderBy('user.created_at', 'DESC') // 按创建时间倒序
|
||||
.orderBy('user.created_at', DATABASE_CONSTANTS.ORDER_DESC) // 按创建时间倒序
|
||||
.limit(limit) // 限制返回数量
|
||||
.getMany();
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
this.logSuccess('搜索用户', {
|
||||
keyword,
|
||||
limit,
|
||||
includeDeleted,
|
||||
resultCount: result.length
|
||||
}, duration);
|
||||
}, monitor.getDuration());
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// 搜索异常使用特殊处理,返回空数组而不抛出异常
|
||||
return this.handleSearchError(error, '搜索用户', { keyword, limit, includeDeleted, duration });
|
||||
return this.handleSearchError(error, '搜索用户', {
|
||||
keyword,
|
||||
limit,
|
||||
includeDeleted,
|
||||
duration: monitor.getDuration()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user