Files
whale-town-end/src/business/auth/README.md
moyin f7c3983cc1 refactor(auth): 移除Controller,专注于业务逻辑层
范围:src/business/auth/
涉及文件:
- src/business/auth/auth.module.ts
- src/business/auth/README.md

主要改进:
- 移除LoginController和RegisterController的导入和声明
- 调整模块结构,专注于业务逻辑层
- 更新README文档,明确Business Layer职责定位
- 完善依赖关系说明和架构层级描述
- 版本号从1.0.2升级到2.0.0(架构重构)
2026-01-14 12:00:19 +08:00

331 lines
11 KiB
Markdown
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.
# 认证业务模块 (Auth Business Module)
## 架构层级
**Business Layer业务层**
## 职责定位
业务层负责实现核心业务逻辑和流程控制:
1. **业务流程**:实现完整的业务流程和规则
2. **服务协调**:协调多个核心服务完成业务功能
3. **数据转换**:将核心层数据转换为业务数据
4. **业务验证**:实现业务规则验证
5. **事务管理**:处理跨服务的事务逻辑
## 模块组成
```
src/business/auth/
├── login.service.ts # 登录业务服务
├── register.service.ts # 注册业务服务
├── auth.module.ts # 业务模块配置
└── README.md # 模块文档
```
## 对外提供的接口
### LoginService
#### login(loginRequest: LoginRequest): Promise<ApiResponse<LoginResponse>>
处理用户登录请求验证用户凭据并生成JWT令牌支持Zulip账号验证和更新。
#### githubOAuth(oauthRequest: GitHubOAuthRequest): Promise<ApiResponse<LoginResponse>>
使用GitHub账户登录或注册自动创建用户账号并生成JWT令牌。
#### verificationCodeLogin(loginRequest: VerificationCodeLoginRequest): Promise<ApiResponse<LoginResponse>>
使用邮箱或手机号和验证码进行登录,无需密码即可完成认证。
#### sendPasswordResetCode(identifier: string): Promise<ApiResponse<{verification_code?: string; is_test_mode?: boolean}>>
向用户邮箱或手机发送密码重置验证码,支持测试模式和真实发送模式。
#### resetPassword(resetRequest: PasswordResetRequest): Promise<ApiResponse>
使用验证码重置用户密码,验证验证码有效性后更新密码。
#### changePassword(userId: bigint, oldPassword: string, newPassword: string): Promise<ApiResponse>
修改用户密码,需要验证旧密码正确性后才能更新为新密码。
#### refreshAccessToken(refreshToken: string): Promise<ApiResponse<TokenPair>>
使用有效的刷新令牌生成新的访问令牌,实现无感知的令牌续期。
#### sendLoginVerificationCode(identifier: string): Promise<ApiResponse<{verification_code?: string; is_test_mode?: boolean}>>
向用户邮箱或手机发送登录验证码,用于验证码登录功能。
### RegisterService
#### register(registerRequest: RegisterRequest): Promise<ApiResponse<RegisterResponse>>
处理用户注册请求创建游戏账号和Zulip账号支持邮箱验证和自动回滚。
#### sendEmailVerification(email: string): Promise<ApiResponse<{verification_code?: string; is_test_mode?: boolean}>>
向指定邮箱发送验证码,支持测试模式和真实发送模式。
#### verifyEmailCode(email: string, code: string): Promise<ApiResponse>
验证邮箱验证码的有效性,用于邮箱验证流程。
#### resendEmailVerification(email: string): Promise<ApiResponse<{verification_code?: string; is_test_mode?: boolean}>>
重新向指定邮箱发送验证码,用于验证码过期或未收到的情况。
## 依赖关系
```
Gateway Layer (auth.gateway.module)
↓ 使用
Business Layer (auth.module)
↓ 依赖
Core Layer (login_core.module, zulip_core.module)
```
## 使用的项目内部依赖
### LoginCoreService (来自 core/login_core)
核心登录服务提供用户认证、JWT令牌生成、密码验证、验证码管理等技术实现。
### ZulipAccountService (来自 core/zulip_core)
Zulip账号服务提供Zulip账号创建、API Key管理、账号验证等功能。
### ApiKeySecurityService (来自 core/zulip_core)
API Key安全服务负责Zulip API Key的加密存储和Redis缓存管理。
### ZulipAccountsService (来自 core/db/zulip_accounts)
Zulip账号数据访问服务提供游戏账号与Zulip账号的关联管理。
### Users (来自 core/db/users)
用户实体,定义用户数据结构和数据库映射关系。
## 核心原则
### 1. 专注业务逻辑不处理HTTP协议
```typescript
// ✅ 正确:返回统一的业务响应
async login(loginRequest: LoginRequest): Promise<ApiResponse<LoginResponse>> {
try {
// 1. 调用核心服务进行认证
const authResult = await this.loginCoreService.login(loginRequest);
// 2. 验证Zulip账号
await this.validateAndUpdateZulipApiKey(authResult.user);
// 3. 生成JWT令牌
const tokenPair = await this.loginCoreService.generateTokenPair(authResult.user);
// 4. 返回业务响应
return {
success: true,
data: { user: this.formatUserInfo(authResult.user), ...tokenPair },
message: '登录成功'
};
} catch (error) {
return {
success: false,
message: error.message,
error_code: 'LOGIN_FAILED'
};
}
}
```
### 2. 协调多个核心服务
```typescript
async register(registerRequest: RegisterRequest): Promise<ApiResponse<RegisterResponse>> {
// 1. 初始化Zulip管理员客户端
await this.initializeZulipAdminClient();
// 2. 调用核心服务进行注册
const authResult = await this.loginCoreService.register(registerRequest);
// 3. 创建Zulip账号
await this.createZulipAccountForUser(authResult.user, registerRequest.password);
// 4. 生成JWT令牌
const tokenPair = await this.loginCoreService.generateTokenPair(authResult.user);
// 5. 返回完整的业务响应
return { success: true, data: { ... }, message: '注册成功' };
}
```
### 3. 统一的响应格式
```typescript
interface ApiResponse<T = any> {
success: boolean;
data?: T;
message: string;
error_code?: string;
}
```
## 业务服务
### LoginService
负责登录相关的业务逻辑:
- `login()` - 用户登录
- `githubOAuth()` - GitHub OAuth登录
- `verificationCodeLogin()` - 验证码登录
- `sendPasswordResetCode()` - 发送密码重置验证码
- `resetPassword()` - 重置密码
- `changePassword()` - 修改密码
- `refreshAccessToken()` - 刷新访问令牌
- `sendLoginVerificationCode()` - 发送登录验证码
### RegisterService
负责注册相关的业务逻辑:
- `register()` - 用户注册
- `sendEmailVerification()` - 发送邮箱验证码
- `verifyEmailCode()` - 验证邮箱验证码
- `resendEmailVerification()` - 重新发送邮箱验证码
## 核心特性
### Zulip集成
- **自动创建Zulip账号**注册时同步创建Zulip聊天账号
- **API Key管理**安全存储和验证Zulip API Key
- **账号关联**建立游戏账号与Zulip账号的映射关系
- **失败回滚**Zulip账号创建失败时自动回滚游戏账号
### JWT令牌管理
- **双令牌机制**:访问令牌(短期)+ 刷新令牌(长期)
- **无感知续期**:通过刷新令牌自动更新访问令牌
- **令牌验证**:完整的令牌签名和过期时间验证
### 统一响应格式
- **ApiResponse接口**:统一的业务响应格式
- **错误代码**:标准化的错误代码定义
- **成功/失败标识**明确的success字段
### 数据转换和格式化
- **用户信息格式化**将Core层数据转换为业务数据
- **BigInt处理**自动将bigint类型转换为string
- **敏感信息过滤**:响应中不包含密码等敏感数据
### 完整的错误处理
- **业务异常捕获**:捕获所有业务逻辑异常
- **详细日志记录**记录操作ID、用户ID、错误信息、执行时间
- **友好错误消息**:返回用户可理解的错误提示
## 业务流程示例
### 用户注册流程
```
1. 接收注册请求
2. 初始化Zulip管理员客户端
3. 调用LoginCoreService.register()创建游戏用户
4. 创建Zulip账号并建立关联
├─ 创建Zulip账号
├─ 获取API Key
├─ 存储到Redis
└─ 创建数据库关联记录
5. 生成JWT令牌对
6. 返回注册成功响应
```
### 用户登录流程
```
1. 接收登录请求
2. 调用LoginCoreService.login()验证用户
3. 验证并更新Zulip API Key
├─ 查找Zulip账号关联
├─ 从Redis获取API Key
├─ 验证API Key有效性
└─ 如果无效,重新生成
4. 生成JWT令牌对
5. 返回登录成功响应
```
## 与其他层的交互
### 与Gateway层的交互
Gateway层调用Business层服务
```typescript
// Gateway Layer
@Post('login')
async login(@Body() loginDto: LoginDto, @Res() res: Response): Promise<void> {
const result = await this.loginService.login({
identifier: loginDto.identifier,
password: loginDto.password
});
this.handleResponse(result, res);
}
```
### 与Core层的交互
Business层调用Core层服务
```typescript
// Business Layer
async login(loginRequest: LoginRequest): Promise<ApiResponse<LoginResponse>> {
// 调用核心服务
const authResult = await this.loginCoreService.login(loginRequest);
const tokenPair = await this.loginCoreService.generateTokenPair(authResult.user);
// 返回业务响应
return { success: true, data: { ... } };
}
```
## 最佳实践
1. **业务逻辑集中**所有业务规则都在Business层实现
2. **服务协调**协调多个Core层服务完成复杂业务
3. **错误处理**:捕获异常并转换为业务错误
4. **日志记录**:记录关键业务操作和错误
5. **事务管理**:处理跨服务的数据一致性
6. **数据转换**将Core层数据转换为业务数据
## 潜在风险
### Zulip账号创建失败风险
- **风险描述**注册流程中Zulip账号创建可能失败
- **影响范围**:导致注册流程中断,已创建的游戏账号需要回滚
- **缓解措施**:完整的事务回滚机制和错误日志记录
### API Key验证失败风险
- **风险描述**登录时Zulip API Key可能已失效或不存在
- **影响范围**用户无法使用Zulip聊天功能
- **缓解措施**API Key验证失败不影响登录流程记录警告日志尝试重新生成
### 跨服务事务一致性风险
- **风险描述**涉及多个Core层服务的协调操作部分操作成功部分失败
- **影响范围**数据不一致如游戏账号创建成功但Zulip账号创建失败
- **缓解措施**:明确的操作顺序、完整的错误处理、自动回滚机制
### 业务逻辑复杂度风险
- **风险描述**:登录和注册流程涉及多个步骤和服务,代码复杂度高
- **影响范围**增加维护难度容易引入bug
- **缓解措施**详细的注释、完整的测试覆盖41个测试用例、清晰的日志记录
### 验证码发送失败风险
- **风险描述**:邮件服务不可用或配置错误导致验证码无法发送
- **影响范围**:用户无法完成邮箱验证、密码重置、验证码登录
- **缓解措施**:测试模式支持、详细的错误日志、邮件服务健康检查
## 注意事项
- Business层不应该处理HTTP协议
- Business层不应该直接访问数据库通过Core层
- Business层不应该包含技术实现细节
- 所有业务逻辑都应该有完善的错误处理
- 关键业务操作都应该有日志记录