refactor:重构业务层服务架构

- 重构共享模块,移除冗余DTO定义
- 优化Zulip服务模块,重新组织控制器结构
- 更新用户管理和认证服务
- 移除过时的登录服务测试文件
This commit is contained in:
moyin
2026-01-08 23:05:13 +08:00
parent c2a1c6862d
commit 0f37130832
16 changed files with 38 additions and 54 deletions

View File

@@ -0,0 +1,581 @@
/**
* Zulip账号关联管理控制器
*
* 功能描述:
* - 提供Zulip账号关联管理的REST API接口
* - 支持CRUD操作和批量管理
* - 提供账号验证和统计功能
*
* @author angjustinl
* @version 1.0.0
* @since 2025-01-07
*/
import {
Controller,
Get,
Post,
Put,
Delete,
Body,
Param,
Query,
UseGuards,
HttpStatus,
HttpCode,
Inject,
} from '@nestjs/common';
import {
ApiTags,
ApiOperation,
ApiResponse,
ApiBearerAuth,
ApiParam,
ApiQuery,
} from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
import { ZulipAccountsService } from '../../core/db/zulip_accounts/zulip_accounts.service';
import { ZulipAccountsMemoryService } from '../../core/db/zulip_accounts/zulip_accounts_memory.service';
import {
CreateZulipAccountDto,
UpdateZulipAccountDto,
QueryZulipAccountDto,
ZulipAccountResponseDto,
ZulipAccountListResponseDto,
ZulipAccountStatsResponseDto,
BatchUpdateStatusDto,
BatchUpdateResponseDto,
VerifyAccountDto,
VerifyAccountResponseDto,
} from '../../core/db/zulip_accounts/zulip_accounts.dto';
@ApiTags('zulip-accounts')
@Controller('zulip-accounts')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')
export class ZulipAccountsController {
constructor(
@Inject('ZulipAccountsService')
private readonly zulipAccountsService: ZulipAccountsService | ZulipAccountsMemoryService,
) {}
/**
* 创建Zulip账号关联
*/
@Post()
@ApiOperation({
summary: '创建Zulip账号关联',
description: '为游戏用户创建与Zulip账号的关联关系'
})
@ApiResponse({
status: 201,
description: '创建成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 400,
description: '请求参数错误',
})
@ApiResponse({
status: 409,
description: '关联已存在',
})
@HttpCode(HttpStatus.CREATED)
async create(@Body() createDto: CreateZulipAccountDto): Promise<ZulipAccountResponseDto> {
return this.zulipAccountsService.create(createDto);
}
/**
* 获取所有Zulip账号关联
*/
@Get()
@ApiOperation({
summary: '查询Zulip账号关联列表',
description: '根据条件查询Zulip账号关联列表'
})
@ApiQuery({
name: 'gameUserId',
required: false,
description: '游戏用户ID',
example: '12345'
})
@ApiQuery({
name: 'zulipUserId',
required: false,
description: 'Zulip用户ID',
example: 67890
})
@ApiQuery({
name: 'zulipEmail',
required: false,
description: 'Zulip邮箱地址',
example: 'user@example.com'
})
@ApiQuery({
name: 'status',
required: false,
description: '账号状态',
enum: ['active', 'inactive', 'suspended', 'error']
})
@ApiQuery({
name: 'includeGameUser',
required: false,
description: '是否包含游戏用户信息',
type: Boolean,
example: false
})
@ApiResponse({
status: 200,
description: '查询成功',
type: ZulipAccountListResponseDto,
})
async findMany(@Query() queryDto: QueryZulipAccountDto): Promise<ZulipAccountListResponseDto> {
return this.zulipAccountsService.findMany(queryDto);
}
/**
* 根据ID获取Zulip账号关联
*/
@Get(':id')
@ApiOperation({
summary: '根据ID获取Zulip账号关联',
description: '根据关联记录ID获取详细信息'
})
@ApiParam({
name: 'id',
description: '关联记录ID',
example: '1'
})
@ApiQuery({
name: 'includeGameUser',
required: false,
description: '是否包含游戏用户信息',
type: Boolean,
example: false
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 404,
description: '记录不存在',
})
async findById(
@Param('id') id: string,
@Query('includeGameUser') includeGameUser?: boolean,
): Promise<ZulipAccountResponseDto> {
return this.zulipAccountsService.findById(id, includeGameUser);
}
/**
* 根据游戏用户ID获取Zulip账号关联
*/
@Get('game-user/:gameUserId')
@ApiOperation({
summary: '根据游戏用户ID获取Zulip账号关联',
description: '根据游戏用户ID获取关联的Zulip账号信息'
})
@ApiParam({
name: 'gameUserId',
description: '游戏用户ID',
example: '12345'
})
@ApiQuery({
name: 'includeGameUser',
required: false,
description: '是否包含游戏用户信息',
type: Boolean,
example: false
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 404,
description: '关联不存在',
})
async findByGameUserId(
@Param('gameUserId') gameUserId: string,
@Query('includeGameUser') includeGameUser?: boolean,
): Promise<ZulipAccountResponseDto | null> {
return this.zulipAccountsService.findByGameUserId(gameUserId, includeGameUser);
}
/**
* 根据Zulip用户ID获取账号关联
*/
@Get('zulip-user/:zulipUserId')
@ApiOperation({
summary: '根据Zulip用户ID获取账号关联',
description: '根据Zulip用户ID获取关联的游戏账号信息'
})
@ApiParam({
name: 'zulipUserId',
description: 'Zulip用户ID',
example: '67890'
})
@ApiQuery({
name: 'includeGameUser',
required: false,
description: '是否包含游戏用户信息',
type: Boolean,
example: false
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 404,
description: '关联不存在',
})
async findByZulipUserId(
@Param('zulipUserId') zulipUserId: string,
@Query('includeGameUser') includeGameUser?: boolean,
): Promise<ZulipAccountResponseDto | null> {
return this.zulipAccountsService.findByZulipUserId(parseInt(zulipUserId), includeGameUser);
}
/**
* 根据Zulip邮箱获取账号关联
*/
@Get('zulip-email/:zulipEmail')
@ApiOperation({
summary: '根据Zulip邮箱获取账号关联',
description: '根据Zulip邮箱地址获取关联的游戏账号信息'
})
@ApiParam({
name: 'zulipEmail',
description: 'Zulip邮箱地址',
example: 'user@example.com'
})
@ApiQuery({
name: 'includeGameUser',
required: false,
description: '是否包含游戏用户信息',
type: Boolean,
example: false
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 404,
description: '关联不存在',
})
async findByZulipEmail(
@Param('zulipEmail') zulipEmail: string,
@Query('includeGameUser') includeGameUser?: boolean,
): Promise<ZulipAccountResponseDto | null> {
return this.zulipAccountsService.findByZulipEmail(zulipEmail, includeGameUser);
}
/**
* 更新Zulip账号关联
*/
@Put(':id')
@ApiOperation({
summary: '更新Zulip账号关联',
description: '根据ID更新Zulip账号关联信息'
})
@ApiParam({
name: 'id',
description: '关联记录ID',
example: '1'
})
@ApiResponse({
status: 200,
description: '更新成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 404,
description: '记录不存在',
})
async update(
@Param('id') id: string,
@Body() updateDto: UpdateZulipAccountDto,
): Promise<ZulipAccountResponseDto> {
return this.zulipAccountsService.update(id, updateDto);
}
/**
* 根据游戏用户ID更新关联
*/
@Put('game-user/:gameUserId')
@ApiOperation({
summary: '根据游戏用户ID更新关联',
description: '根据游戏用户ID更新Zulip账号关联信息'
})
@ApiParam({
name: 'gameUserId',
description: '游戏用户ID',
example: '12345'
})
@ApiResponse({
status: 200,
description: '更新成功',
type: ZulipAccountResponseDto,
})
@ApiResponse({
status: 404,
description: '关联不存在',
})
async updateByGameUserId(
@Param('gameUserId') gameUserId: string,
@Body() updateDto: UpdateZulipAccountDto,
): Promise<ZulipAccountResponseDto> {
return this.zulipAccountsService.updateByGameUserId(gameUserId, updateDto);
}
/**
* 删除Zulip账号关联
*/
@Delete(':id')
@ApiOperation({
summary: '删除Zulip账号关联',
description: '根据ID删除Zulip账号关联记录'
})
@ApiParam({
name: 'id',
description: '关联记录ID',
example: '1'
})
@ApiResponse({
status: 200,
description: '删除成功',
schema: {
type: 'object',
properties: {
success: { type: 'boolean', example: true },
message: { type: 'string', example: '删除成功' }
}
}
})
@ApiResponse({
status: 404,
description: '记录不存在',
})
async delete(@Param('id') id: string): Promise<{ success: boolean; message: string }> {
await this.zulipAccountsService.delete(id);
return { success: true, message: '删除成功' };
}
/**
* 根据游戏用户ID删除关联
*/
@Delete('game-user/:gameUserId')
@ApiOperation({
summary: '根据游戏用户ID删除关联',
description: '根据游戏用户ID删除Zulip账号关联记录'
})
@ApiParam({
name: 'gameUserId',
description: '游戏用户ID',
example: '12345'
})
@ApiResponse({
status: 200,
description: '删除成功',
schema: {
type: 'object',
properties: {
success: { type: 'boolean', example: true },
message: { type: 'string', example: '删除成功' }
}
}
})
@ApiResponse({
status: 404,
description: '关联不存在',
})
async deleteByGameUserId(@Param('gameUserId') gameUserId: string): Promise<{ success: boolean; message: string }> {
await this.zulipAccountsService.deleteByGameUserId(gameUserId);
return { success: true, message: '删除成功' };
}
/**
* 获取需要验证的账号列表
*/
@Get('management/verification-needed')
@ApiOperation({
summary: '获取需要验证的账号列表',
description: '获取超过指定时间未验证的账号列表'
})
@ApiQuery({
name: 'maxAge',
required: false,
description: '最大验证间隔毫秒默认24小时',
example: 86400000
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountListResponseDto,
})
async findAccountsNeedingVerification(
@Query('maxAge') maxAge?: number,
): Promise<ZulipAccountListResponseDto> {
return this.zulipAccountsService.findAccountsNeedingVerification(maxAge);
}
/**
* 获取错误状态的账号列表
*/
@Get('management/error-accounts')
@ApiOperation({
summary: '获取错误状态的账号列表',
description: '获取处于错误状态的账号列表'
})
@ApiQuery({
name: 'maxRetryCount',
required: false,
description: '最大重试次数默认3次',
example: 3
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountListResponseDto,
})
async findErrorAccounts(
@Query('maxRetryCount') maxRetryCount?: number,
): Promise<ZulipAccountListResponseDto> {
return this.zulipAccountsService.findErrorAccounts(maxRetryCount);
}
/**
* 批量更新账号状态
*/
@Put('management/batch-status')
@ApiOperation({
summary: '批量更新账号状态',
description: '批量更新多个账号的状态'
})
@ApiResponse({
status: 200,
description: '更新成功',
type: BatchUpdateResponseDto,
})
async batchUpdateStatus(@Body() batchDto: BatchUpdateStatusDto): Promise<BatchUpdateResponseDto> {
return this.zulipAccountsService.batchUpdateStatus(batchDto.ids, batchDto.status);
}
/**
* 获取账号状态统计
*/
@Get('management/statistics')
@ApiOperation({
summary: '获取账号状态统计',
description: '获取各种状态的账号数量统计'
})
@ApiResponse({
status: 200,
description: '获取成功',
type: ZulipAccountStatsResponseDto,
})
async getStatusStatistics(): Promise<ZulipAccountStatsResponseDto> {
return this.zulipAccountsService.getStatusStatistics();
}
/**
* 验证账号有效性
*/
@Post('management/verify')
@ApiOperation({
summary: '验证账号有效性',
description: '验证指定游戏用户的Zulip账号关联是否有效'
})
@ApiResponse({
status: 200,
description: '验证完成',
type: VerifyAccountResponseDto,
})
async verifyAccount(@Body() verifyDto: VerifyAccountDto): Promise<VerifyAccountResponseDto> {
return this.zulipAccountsService.verifyAccount(verifyDto.gameUserId);
}
/**
* 检查邮箱是否已存在
*/
@Get('validation/email-exists/:email')
@ApiOperation({
summary: '检查邮箱是否已存在',
description: '检查指定的Zulip邮箱是否已被其他账号使用'
})
@ApiParam({
name: 'email',
description: 'Zulip邮箱地址',
example: 'user@example.com'
})
@ApiQuery({
name: 'excludeId',
required: false,
description: '排除的记录ID用于更新时检查',
example: '1'
})
@ApiResponse({
status: 200,
description: '检查完成',
schema: {
type: 'object',
properties: {
exists: { type: 'boolean', example: false },
email: { type: 'string', example: 'user@example.com' }
}
}
})
async checkEmailExists(
@Param('email') email: string,
@Query('excludeId') excludeId?: string,
): Promise<{ exists: boolean; email: string }> {
const exists = await this.zulipAccountsService.existsByEmail(email, excludeId);
return { exists, email };
}
/**
* 检查Zulip用户ID是否已存在
*/
@Get('validation/zulip-user-exists/:zulipUserId')
@ApiOperation({
summary: '检查Zulip用户ID是否已存在',
description: '检查指定的Zulip用户ID是否已被其他账号使用'
})
@ApiParam({
name: 'zulipUserId',
description: 'Zulip用户ID',
example: '67890'
})
@ApiQuery({
name: 'excludeId',
required: false,
description: '排除的记录ID用于更新时检查',
example: '1'
})
@ApiResponse({
status: 200,
description: '检查完成',
schema: {
type: 'object',
properties: {
exists: { type: 'boolean', example: false },
zulipUserId: { type: 'number', example: 67890 }
}
}
})
async checkZulipUserIdExists(
@Param('zulipUserId') zulipUserId: string,
@Query('excludeId') excludeId?: string,
): Promise<{ exists: boolean; zulipUserId: number }> {
const zulipUserIdNum = parseInt(zulipUserId);
const exists = await this.zulipAccountsService.existsByZulipUserId(zulipUserIdNum, excludeId);
return { exists, zulipUserId: zulipUserIdNum };
}
}