Files
whale-town-end/src/gateway/auth/dto/login.dto.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

454 lines
11 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.
/**
* 登录业务数据传输对象
*
* 功能描述:
* - 定义登录相关API的请求数据结构
* - 提供数据验证规则和错误提示
* - 确保API接口的数据格式一致性
*
* 职责分离:
* - 专注于数据结构定义和验证规则
* - 提供Swagger文档生成支持
* - 确保类型安全和数据完整性
*
* 最近修改:
* - 2026-01-07: 代码规范优化 - 文件夹扁平化,移除单文件文件夹结构
* - 2026-01-07: 代码规范优化 - 更新注释规范,修正作者信息
*
* @author moyin
* @version 1.0.2
* @since 2025-12-17
* @lastModified 2026-01-07
*/
import {
IsString,
IsEmail,
IsPhoneNumber,
IsNotEmpty,
Length,
IsOptional,
Matches,
IsNumberString
} from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
/**
* 登录请求DTO
*/
export class LoginDto {
/**
* 登录标识符
* 支持用户名、邮箱或手机号登录
*/
@ApiProperty({
description: '登录标识符,支持用户名、邮箱或手机号',
example: 'testuser',
minLength: 1,
maxLength: 100
})
@IsString({ message: '登录标识符必须是字符串' })
@IsNotEmpty({ message: '登录标识符不能为空' })
@Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
identifier: string;
/**
* 密码
*/
@ApiProperty({
description: '用户密码',
example: 'password123',
minLength: 1,
maxLength: 128
})
@IsString({ message: '密码必须是字符串' })
@IsNotEmpty({ message: '密码不能为空' })
@Length(1, 128, { message: '密码长度需在1-128字符之间' })
password: string;
}
/**
* 注册请求DTO
*/
export class RegisterDto {
/**
* 用户名
*/
@ApiProperty({
description: '用户名,只能包含字母、数字和下划线',
example: 'testuser',
minLength: 1,
maxLength: 50,
pattern: '^[a-zA-Z0-9_]+$'
})
@IsString({ message: '用户名必须是字符串' })
@IsNotEmpty({ message: '用户名不能为空' })
@Length(1, 50, { message: '用户名长度需在1-50字符之间' })
@Matches(/^[a-zA-Z0-9_]+$/, { message: '用户名只能包含字母、数字和下划线' })
username: string;
/**
* 密码
*/
@ApiProperty({
description: '密码必须包含字母和数字长度8-128字符',
example: 'password123',
minLength: 8,
maxLength: 128
})
@IsString({ message: '密码必须是字符串' })
@IsNotEmpty({ message: '密码不能为空' })
@Length(8, 128, { message: '密码长度需在8-128字符之间' })
@Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '密码必须包含字母和数字' })
password: string;
/**
* 昵称
*/
@ApiProperty({
description: '用户昵称',
example: '测试用户',
minLength: 1,
maxLength: 50
})
@IsString({ message: '昵称必须是字符串' })
@IsNotEmpty({ message: '昵称不能为空' })
@Length(1, 50, { message: '昵称长度需在1-50字符之间' })
nickname: string;
/**
* 邮箱(可选)
*/
@ApiProperty({
description: '邮箱地址(可选)',
example: 'test@example.com',
required: false
})
@IsOptional()
@IsEmail({}, { message: '邮箱格式不正确' })
email?: string;
/**
* 手机号(可选)
*/
@ApiProperty({
description: '手机号码(可选)',
example: '+8613800138000',
required: false
})
@IsOptional()
@IsPhoneNumber(null, { message: '手机号格式不正确' })
phone?: string;
/**
* 邮箱验证码(当提供邮箱时必填)
*/
@ApiProperty({
description: '邮箱验证码,当提供邮箱时必填',
example: '123456',
pattern: '^\\d{6}$',
required: false
})
@IsOptional()
@IsString({ message: '验证码必须是字符串' })
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
email_verification_code?: string;
}
/**
* GitHub OAuth登录请求DTO
*/
export class GitHubOAuthDto {
/**
* GitHub用户ID
*/
@ApiProperty({
description: 'GitHub用户ID',
example: '12345678',
minLength: 1,
maxLength: 100
})
@IsString({ message: 'GitHub ID必须是字符串' })
@IsNotEmpty({ message: 'GitHub ID不能为空' })
@Length(1, 100, { message: 'GitHub ID长度需在1-100字符之间' })
github_id: string;
/**
* 用户名
*/
@ApiProperty({
description: 'GitHub用户名',
example: 'octocat',
minLength: 1,
maxLength: 50
})
@IsString({ message: '用户名必须是字符串' })
@IsNotEmpty({ message: '用户名不能为空' })
@Length(1, 50, { message: '用户名长度需在1-50字符之间' })
username: string;
/**
* 昵称
*/
@ApiProperty({
description: 'GitHub显示名称',
example: 'The Octocat',
minLength: 1,
maxLength: 50
})
@IsString({ message: '昵称必须是字符串' })
@IsNotEmpty({ message: '昵称不能为空' })
@Length(1, 50, { message: '昵称长度需在1-50字符之间' })
nickname: string;
/**
* 邮箱(可选)
*/
@ApiProperty({
description: 'GitHub邮箱地址可选',
example: 'octocat@github.com',
required: false
})
@IsOptional()
@IsEmail({}, { message: '邮箱格式不正确' })
email?: string;
/**
* 头像URL可选
*/
@ApiProperty({
description: 'GitHub头像URL可选',
example: 'https://github.com/images/error/octocat_happy.gif',
required: false
})
@IsOptional()
@IsString({ message: '头像URL必须是字符串' })
avatar_url?: string;
}
/**
* 忘记密码请求DTO
*/
export class ForgotPasswordDto {
/**
* 邮箱或手机号
*/
@ApiProperty({
description: '邮箱或手机号',
example: 'test@example.com',
minLength: 1,
maxLength: 100
})
@IsString({ message: '标识符必须是字符串' })
@IsNotEmpty({ message: '邮箱或手机号不能为空' })
@Length(1, 100, { message: '标识符长度需在1-100字符之间' })
identifier: string;
}
/**
* 重置密码请求DTO
*/
export class ResetPasswordDto {
/**
* 邮箱或手机号
*/
@ApiProperty({
description: '邮箱或手机号',
example: 'test@example.com',
minLength: 1,
maxLength: 100
})
@IsString({ message: '标识符必须是字符串' })
@IsNotEmpty({ message: '邮箱或手机号不能为空' })
@Length(1, 100, { message: '标识符长度需在1-100字符之间' })
identifier: string;
/**
* 验证码
*/
@ApiProperty({
description: '6位数字验证码',
example: '123456',
pattern: '^\\d{6}$'
})
@IsString({ message: '验证码必须是字符串' })
@IsNotEmpty({ message: '验证码不能为空' })
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
verification_code: string;
/**
* 新密码
*/
@ApiProperty({
description: '新密码必须包含字母和数字长度8-128字符',
example: 'newpassword123',
minLength: 8,
maxLength: 128
})
@IsString({ message: '新密码必须是字符串' })
@IsNotEmpty({ message: '新密码不能为空' })
@Length(8, 128, { message: '新密码长度需在8-128字符之间' })
@Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '新密码必须包含字母和数字' })
new_password: string;
}
/**
* 修改密码请求DTO
*/
export class ChangePasswordDto {
/**
* 用户ID
* 实际应用中应从JWT令牌中获取这里为了演示放在请求体中
*/
@ApiProperty({
description: '用户ID实际应用中应从JWT令牌中获取',
example: '1'
})
@IsNumberString({}, { message: '用户ID必须是数字字符串' })
@IsNotEmpty({ message: '用户ID不能为空' })
user_id: string;
/**
* 旧密码
*/
@ApiProperty({
description: '当前密码',
example: 'oldpassword123',
minLength: 1,
maxLength: 128
})
@IsString({ message: '旧密码必须是字符串' })
@IsNotEmpty({ message: '旧密码不能为空' })
@Length(1, 128, { message: '旧密码长度需在1-128字符之间' })
old_password: string;
/**
* 新密码
*/
@ApiProperty({
description: '新密码必须包含字母和数字长度8-128字符',
example: 'newpassword123',
minLength: 8,
maxLength: 128
})
@IsString({ message: '新密码必须是字符串' })
@IsNotEmpty({ message: '新密码不能为空' })
@Length(8, 128, { message: '新密码长度需在8-128字符之间' })
@Matches(/^(?=.*[a-zA-Z])(?=.*\d)/, { message: '新密码必须包含字母和数字' })
new_password: string;
}
/**
* 邮箱验证请求DTO
*/
export class EmailVerificationDto {
/**
* 邮箱地址
*/
@ApiProperty({
description: '邮箱地址',
example: 'test@example.com'
})
@IsEmail({}, { message: '邮箱格式不正确' })
@IsNotEmpty({ message: '邮箱不能为空' })
email: string;
/**
* 验证码
*/
@ApiProperty({
description: '6位数字验证码',
example: '123456',
pattern: '^\\d{6}$'
})
@IsString({ message: '验证码必须是字符串' })
@IsNotEmpty({ message: '验证码不能为空' })
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
verification_code: string;
}
/**
* 发送邮箱验证码请求DTO
*/
export class SendEmailVerificationDto {
/**
* 邮箱地址
*/
@ApiProperty({
description: '邮箱地址',
example: 'test@example.com'
})
@IsEmail({}, { message: '邮箱格式不正确' })
@IsNotEmpty({ message: '邮箱不能为空' })
email: string;
}
/**
* 验证码登录请求DTO
*/
export class VerificationCodeLoginDto {
/**
* 登录标识符
* 支持邮箱或手机号登录
*/
@ApiProperty({
description: '登录标识符,支持邮箱或手机号',
example: 'test@example.com',
minLength: 1,
maxLength: 100
})
@IsString({ message: '登录标识符必须是字符串' })
@IsNotEmpty({ message: '登录标识符不能为空' })
@Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
identifier: string;
/**
* 验证码
*/
@ApiProperty({
description: '6位数字验证码',
example: '123456',
pattern: '^\\d{6}$'
})
@IsString({ message: '验证码必须是字符串' })
@IsNotEmpty({ message: '验证码不能为空' })
@Matches(/^\d{6}$/, { message: '验证码必须是6位数字' })
verification_code: string;
}
/**
* 发送登录验证码请求DTO
*/
export class SendLoginVerificationCodeDto {
/**
* 登录标识符
* 支持邮箱或手机号
*/
@ApiProperty({
description: '登录标识符,支持邮箱或手机号',
example: 'test@example.com',
minLength: 1,
maxLength: 100
})
@IsString({ message: '登录标识符必须是字符串' })
@IsNotEmpty({ message: '登录标识符不能为空' })
@Length(1, 100, { message: '登录标识符长度需在1-100字符之间' })
identifier: string;
}
/**
* 刷新令牌请求DTO
*/
export class RefreshTokenDto {
/**
* 刷新令牌
*/
@ApiProperty({
description: 'JWT刷新令牌',
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
minLength: 1
})
@IsString({ message: '刷新令牌必须是字符串' })
@IsNotEmpty({ message: '刷新令牌不能为空' })
refresh_token: string;
}