Files
whale-town-end/src/gateway/auth/register.controller.ts
moyin 73e3e0153c refactor(auth): 重构认证模块架构 - 将Gateway层组件从Business层分离
范围:src/gateway/auth/, src/business/auth/, src/app.module.ts
涉及文件:
- 新增:src/gateway/auth/ 目录及所有文件
- 移动:Controller、Guard、Decorator、DTO从business层移至gateway层
- 修改:src/business/auth/index.ts(移除Gateway层组件导出)
- 修改:src/app.module.ts(使用AuthGatewayModule替代AuthModule)

主要改进:
- 明确Gateway层和Business层的职责边界
- Controller、Guard、Decorator属于Gateway层职责
- Business层专注于业务逻辑和服务
- 符合分层架构设计原则
2026-01-14 13:07:11 +08:00

286 lines
8.1 KiB
TypeScript
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.
/**
* 注册网关控制器
*
* 架构层级Gateway Layer网关层
*
* 功能描述:
* - 处理用户注册相关的HTTP请求和响应
* - 提供RESTful API接口
* - 数据验证和格式化
* - 邮箱验证功能
*
* 职责分离:
* - 专注于HTTP协议处理和请求响应
* - 调用业务层服务完成具体功能
* - 处理API文档和参数验证
* - 不包含业务逻辑,只做数据转换和路由
*
* 依赖关系:
* - 依赖 Business Layer 的 RegisterService
* - 使用 DTO 进行数据验证
*
* API端点
* - POST /auth/register - 用户注册
* - POST /auth/send-email-verification - 发送邮箱验证码
* - POST /auth/verify-email - 验证邮箱验证码
* - POST /auth/resend-email-verification - 重新发送邮箱验证码
*
* @author moyin
* @version 2.0.0
* @since 2026-01-14
* @lastModified 2026-01-14
*/
import {
Controller,
Post,
Body,
HttpStatus,
ValidationPipe,
UsePipes,
Logger,
Res
} from '@nestjs/common';
import {
ApiTags,
ApiOperation,
ApiResponse as SwaggerApiResponse,
ApiBody
} from '@nestjs/swagger';
import { Response } from 'express';
import { RegisterService } from '../../business/auth/register.service';
import {
RegisterDto,
EmailVerificationDto,
SendEmailVerificationDto
} from './dto/login.dto';
import {
RegisterResponseDto,
CommonResponseDto,
TestModeEmailVerificationResponseDto,
SuccessEmailVerificationResponseDto
} from './dto/login_response.dto';
import { Throttle, ThrottlePresets } from '../../core/security_core/throttle.decorator';
import { Timeout, TimeoutPresets } from '../../core/security_core/timeout.decorator';
// 错误代码到HTTP状态码的映射
const ERROR_STATUS_MAP = {
REGISTER_FAILED: HttpStatus.BAD_REQUEST,
TEST_MODE_ONLY: HttpStatus.PARTIAL_CONTENT,
SEND_EMAIL_VERIFICATION_FAILED: HttpStatus.BAD_REQUEST,
EMAIL_VERIFICATION_FAILED: HttpStatus.BAD_REQUEST,
RESEND_EMAIL_VERIFICATION_FAILED: HttpStatus.BAD_REQUEST,
INVALID_VERIFICATION_CODE: HttpStatus.BAD_REQUEST,
} as const;
@ApiTags('auth')
@Controller('auth')
export class RegisterController {
private readonly logger = new Logger(RegisterController.name);
constructor(private readonly registerService: RegisterService) {}
/**
* 通用响应处理方法
*
* 职责:
* - 根据业务结果设置HTTP状态码
* - 处理不同类型的错误响应
* - 统一响应格式和错误处理
*
* @param result 业务服务返回的结果
* @param res Express响应对象
* @param successStatus 成功时的HTTP状态码默认为200
* @private
*/
private handleResponse(result: any, res: Response, successStatus: HttpStatus = HttpStatus.OK): void {
if (result.success) {
res.status(successStatus).json(result);
return;
}
const statusCode = this.getErrorStatusCode(result);
res.status(statusCode).json(result);
}
/**
* 根据错误代码和消息获取HTTP状态码
*
* @param result 业务服务返回的结果
* @returns HTTP状态码
* @private
*/
private getErrorStatusCode(result: any): HttpStatus {
if (result.error_code && ERROR_STATUS_MAP[result.error_code as keyof typeof ERROR_STATUS_MAP]) {
return ERROR_STATUS_MAP[result.error_code as keyof typeof ERROR_STATUS_MAP];
}
if (result.message?.includes('已存在') || result.message?.includes('已被注册')) {
return HttpStatus.CONFLICT;
}
if (result.message?.includes('用户不存在')) {
return HttpStatus.NOT_FOUND;
}
return HttpStatus.BAD_REQUEST;
}
/**
* 用户注册
*
* @param registerDto 注册数据
* @param res Express响应对象
*/
@ApiOperation({
summary: '用户注册',
description: '创建新用户账户'
})
@ApiBody({ type: RegisterDto })
@SwaggerApiResponse({
status: 201,
description: '注册成功',
type: RegisterResponseDto
})
@SwaggerApiResponse({
status: 400,
description: '请求参数错误'
})
@SwaggerApiResponse({
status: 409,
description: '用户名或邮箱已存在'
})
@SwaggerApiResponse({
status: 429,
description: '注册请求过于频繁'
})
@Throttle(ThrottlePresets.REGISTER)
@Timeout(TimeoutPresets.NORMAL)
@Post('register')
@UsePipes(new ValidationPipe({ transform: true }))
async register(@Body() registerDto: RegisterDto, @Res() res: Response): Promise<void> {
const result = await this.registerService.register({
username: registerDto.username,
password: registerDto.password,
nickname: registerDto.nickname,
email: registerDto.email,
phone: registerDto.phone,
email_verification_code: registerDto.email_verification_code
});
this.handleResponse(result, res, HttpStatus.CREATED);
}
/**
* 发送邮箱验证码
*
* @param sendEmailVerificationDto 发送验证码数据
* @param res Express响应对象
*/
@ApiOperation({
summary: '发送邮箱验证码',
description: '向指定邮箱发送验证码'
})
@ApiBody({ type: SendEmailVerificationDto })
@SwaggerApiResponse({
status: 200,
description: '验证码发送成功(真实发送模式)',
type: SuccessEmailVerificationResponseDto
})
@SwaggerApiResponse({
status: 206,
description: '测试模式:验证码已生成但未真实发送',
type: TestModeEmailVerificationResponseDto
})
@SwaggerApiResponse({
status: 400,
description: '请求参数错误'
})
@SwaggerApiResponse({
status: 429,
description: '发送频率过高'
})
@Throttle(ThrottlePresets.SEND_CODE_PER_EMAIL)
@Timeout(TimeoutPresets.EMAIL_SEND)
@Post('send-email-verification')
@UsePipes(new ValidationPipe({ transform: true }))
async sendEmailVerification(
@Body() sendEmailVerificationDto: SendEmailVerificationDto,
@Res() res: Response
): Promise<void> {
const result = await this.registerService.sendEmailVerification(sendEmailVerificationDto.email);
this.handleResponse(result, res);
}
/**
* 验证邮箱验证码
*
* @param emailVerificationDto 邮箱验证数据
* @param res Express响应对象
*/
@ApiOperation({
summary: '验证邮箱验证码',
description: '使用验证码验证邮箱'
})
@ApiBody({ type: EmailVerificationDto })
@SwaggerApiResponse({
status: 200,
description: '邮箱验证成功',
type: CommonResponseDto
})
@SwaggerApiResponse({
status: 400,
description: '验证码错误或已过期'
})
@Post('verify-email')
@UsePipes(new ValidationPipe({ transform: true }))
async verifyEmail(@Body() emailVerificationDto: EmailVerificationDto, @Res() res: Response): Promise<void> {
const result = await this.registerService.verifyEmailCode(
emailVerificationDto.email,
emailVerificationDto.verification_code
);
this.handleResponse(result, res);
}
/**
* 重新发送邮箱验证码
*
* @param sendEmailVerificationDto 发送验证码数据
* @param res Express响应对象
*/
@ApiOperation({
summary: '重新发送邮箱验证码',
description: '重新向指定邮箱发送验证码'
})
@ApiBody({ type: SendEmailVerificationDto })
@SwaggerApiResponse({
status: 200,
description: '验证码重新发送成功',
type: SuccessEmailVerificationResponseDto
})
@SwaggerApiResponse({
status: 206,
description: '测试模式:验证码已生成但未真实发送',
type: TestModeEmailVerificationResponseDto
})
@SwaggerApiResponse({
status: 400,
description: '邮箱已验证或用户不存在'
})
@SwaggerApiResponse({
status: 429,
description: '发送频率过高'
})
@Throttle(ThrottlePresets.SEND_CODE)
@Post('resend-email-verification')
@UsePipes(new ValidationPipe({ transform: true }))
async resendEmailVerification(
@Body() sendEmailVerificationDto: SendEmailVerificationDto,
@Res() res: Response
): Promise<void> {
const result = await this.registerService.resendEmailVerification(sendEmailVerificationDto.email);
this.handleResponse(result, res);
}
}