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