范围: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(架构重构)
331 lines
11 KiB
Markdown
331 lines
11 KiB
Markdown
# 认证业务模块 (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层不应该包含技术实现细节
|
||
- 所有业务逻辑都应该有完善的错误处理
|
||
- 关键业务操作都应该有日志记录
|