import { Controller, Get, Post, Body, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse, } from '@nestjs/swagger'; import { TotpService } from '@/application/services/totp.service'; import { CurrentUser, CurrentUserPayload } from '@/shared/decorators'; import { JwtAuthGuard } from '@/shared/guards/jwt-auth.guard'; class SetupTotpResponseDto { secret: string; qrCodeUrl: string; manualEntryKey: string; } class TotpStatusResponseDto { isEnabled: boolean; isSetup: boolean; enabledAt: Date | null; } class EnableTotpDto { code: string; } class DisableTotpDto { code: string; } class VerifyTotpDto { code: string; } @ApiTags('TOTP') @Controller('totp') @UseGuards(JwtAuthGuard) @ApiBearerAuth() export class TotpController { constructor(private readonly totpService: TotpService) {} @Get('status') @ApiOperation({ summary: '获取 TOTP 状态', description: '查询当前用户的 TOTP 启用状态', }) @ApiResponse({ status: 200, type: TotpStatusResponseDto }) async getStatus( @CurrentUser() user: CurrentUserPayload, ): Promise { return this.totpService.getTotpStatus(BigInt(user.userId)); } @Post('setup') @ApiOperation({ summary: '设置 TOTP', description: '生成 TOTP 密钥,返回二维码和手动输入密钥', }) @ApiResponse({ status: 201, type: SetupTotpResponseDto }) async setup( @CurrentUser() user: CurrentUserPayload, ): Promise { return this.totpService.setupTotp(BigInt(user.userId)); } @Post('enable') @ApiOperation({ summary: '启用 TOTP', description: '验证码正确后启用 TOTP 二次验证', }) @ApiResponse({ status: 200, description: 'TOTP 已启用' }) async enable( @CurrentUser() user: CurrentUserPayload, @Body() dto: EnableTotpDto, ): Promise<{ success: boolean; message: string }> { await this.totpService.enableTotp(BigInt(user.userId), dto.code); return { success: true, message: 'TOTP 已启用' }; } @Post('disable') @ApiOperation({ summary: '禁用 TOTP', description: '验证码正确后禁用 TOTP 二次验证', }) @ApiResponse({ status: 200, description: 'TOTP 已禁用' }) async disable( @CurrentUser() user: CurrentUserPayload, @Body() dto: DisableTotpDto, ): Promise<{ success: boolean; message: string }> { await this.totpService.disableTotp(BigInt(user.userId), dto.code); return { success: true, message: 'TOTP 已禁用' }; } @Post('verify') @ApiOperation({ summary: '验证 TOTP', description: '验证 TOTP 验证码是否正确', }) @ApiResponse({ status: 200, description: '验证结果' }) async verify( @CurrentUser() user: CurrentUserPayload, @Body() dto: VerifyTotpDto, ): Promise<{ valid: boolean }> { const valid = await this.totpService.verifyTotp( BigInt(user.userId), dto.code, ); return { valid }; } }