From 70c020a97cc5bdbc8d46ad8591de3b6c7cd9d564 Mon Sep 17 00:00:00 2001 From: moyin <244344649@qq.com> Date: Sun, 4 Jan 2026 19:34:16 +0800 Subject: [PATCH] =?UTF-8?q?refactor=EF=BC=9A=E9=87=8D=E6=9E=84=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E6=A8=A1=E5=9D=97=E6=9E=B6=E6=9E=84=EF=BC=8C=E5=B0=86?= =?UTF-8?q?security=E6=A8=A1=E5=9D=97=E8=BF=81=E7=A7=BB=E8=87=B3core?= =?UTF-8?q?=E5=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将src/business/security模块迁移至src/core/security_core - 更新模块导入路径和依赖关系 - 统一安全相关组件的命名规范(content_type.middleware.ts) - 清理过时的配置文件和文档 - 更新架构文档以反映新的模块结构 此次重构符合业务功能模块化架构设计原则,将技术基础设施 服务统一放置在core层,提高代码组织的清晰度和可维护性。 --- Dockerfile | 31 -- REFACTORING_SUMMARY.md | 163 --------- deploy.sh.example | 54 --- docker-compose.yml | 36 -- docs/API_STATUS_CODES.md | 257 -------------- docs/ARCHITECTURE.md | 214 ++++++----- docs/DOCUMENT_CLEANUP.md | 142 -------- nest-cli.json | 8 +- src/app.module.ts | 8 +- src/business/admin/admin.controller.ts | 2 +- .../auth/controllers/login.controller.ts | 4 +- .../controllers/user-status.controller.ts | 4 +- .../decorators/throttle.decorator.ts | 0 .../decorators/timeout.decorator.ts | 0 .../security_core}/guards/throttle.guard.ts | 0 .../security => core/security_core}/index.ts | 6 +- .../interceptors/timeout.interceptor.ts | 0 .../middleware/content_type.middleware.ts} | 0 .../middleware/maintenance.middleware.ts | 0 .../security_core/security_core.module.ts} | 8 +- .../zulip/services/config_manager.service.ts | 31 +- test-comprehensive.ps1 | 333 ------------------ test/core/db/users.test.ts | 0 tsconfig.json | 2 +- webhook-handler.js.example | 86 ----- 25 files changed, 174 insertions(+), 1215 deletions(-) delete mode 100644 Dockerfile delete mode 100644 REFACTORING_SUMMARY.md delete mode 100644 deploy.sh.example delete mode 100644 docker-compose.yml delete mode 100644 docs/API_STATUS_CODES.md delete mode 100644 docs/DOCUMENT_CLEANUP.md rename src/{business/security => core/security_core}/decorators/throttle.decorator.ts (100%) rename src/{business/security => core/security_core}/decorators/timeout.decorator.ts (100%) rename src/{business/security => core/security_core}/guards/throttle.guard.ts (100%) rename src/{business/security => core/security_core}/index.ts (71%) rename src/{business/security => core/security_core}/interceptors/timeout.interceptor.ts (100%) rename src/{business/security/middleware/content-type.middleware.ts => core/security_core/middleware/content_type.middleware.ts} (100%) rename src/{business/security => core/security_core}/middleware/maintenance.middleware.ts (100%) rename src/{business/security/security.module.ts => core/security_core/security_core.module.ts} (84%) delete mode 100644 test-comprehensive.ps1 delete mode 100644 test/core/db/users.test.ts delete mode 100644 webhook-handler.js.example diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index ac314d8..0000000 --- a/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -# 使用官方 Node.js 镜像 -FROM node:lts-alpine - -# 设置工作目录 -WORKDIR /app - -# 设置构建参数 -ARG NPM_REGISTRY=https://registry.npmmirror.com - -# 设置 npm 和 pnpm 镜像源 -RUN npm config set registry ${NPM_REGISTRY} && \ - npm install -g pnpm && \ - pnpm config set registry ${NPM_REGISTRY} - -# 复制 package.json -COPY package.json pnpm-workspace.yaml ./ - -# 安装依赖 -RUN pnpm install - -# 复制源代码 -COPY . . - -# 构建应用 -RUN pnpm run build - -# 暴露端口 -EXPOSE 3000 - -# 启动应用 -CMD ["pnpm", "run", "start:prod"] \ No newline at end of file diff --git a/REFACTORING_SUMMARY.md b/REFACTORING_SUMMARY.md deleted file mode 100644 index b27665d..0000000 --- a/REFACTORING_SUMMARY.md +++ /dev/null @@ -1,163 +0,0 @@ -# Zulip模块重构总结 - -## 重构完成情况 - -✅ **重构已完成** - 项目编译成功,架构符合分层设计原则 - -## 重构内容 - -### 1. 架构分层重构 - -#### 移动到核心服务层 (`src/core/zulip/`) -以下技术实现相关的服务已移动到核心服务层: - -- `zulip_client.service.ts` - Zulip REST API封装 -- `zulip_client_pool.service.ts` - 客户端连接池管理 -- `config_manager.service.ts` - 配置文件管理和热重载 -- `api_key_security.service.ts` - API Key安全存储 -- `error_handler.service.ts` - 错误处理和重试机制 -- `monitoring.service.ts` - 系统监控和健康检查 -- `stream_initializer.service.ts` - Stream初始化服务 - -#### 保留在业务逻辑层 (`src/business/zulip/`) -以下业务逻辑相关的服务保留在业务层: - -- `zulip.service.ts` - 主要业务协调服务 -- `zulip_websocket.gateway.ts` - WebSocket业务网关 -- `session_manager.service.ts` - 游戏会话业务逻辑 -- `message_filter.service.ts` - 消息过滤业务规则 -- `zulip_event_processor.service.ts` - 事件处理业务逻辑 -- `session_cleanup.service.ts` - 会话清理业务逻辑 - -### 2. 依赖注入重构 - -#### 创建接口抽象 -- 新增 `src/core/zulip/interfaces/zulip-core.interfaces.ts` -- 定义核心服务接口:`IZulipClientService`、`IZulipClientPoolService`、`IZulipConfigService` - -#### 更新依赖注入 -业务层服务现在通过接口依赖核心服务: - -```typescript -// 旧方式 - 直接依赖具体实现 -constructor( - private readonly zulipClientPool: ZulipClientPoolService, -) {} - -// 新方式 - 通过接口依赖 -constructor( - @Inject('ZULIP_CLIENT_POOL_SERVICE') - private readonly zulipClientPool: IZulipClientPoolService, -) {} -``` - -### 3. 模块结构重构 - -#### 核心服务模块 -- 新增 `ZulipCoreModule` - 提供所有技术实现服务 -- 通过依赖注入标识符导出服务 - -#### 业务逻辑模块 -- 更新 `ZulipModule` - 导入核心模块,专注业务逻辑 -- 移除技术实现相关的服务提供者 - -### 4. 文件移动记录 - -#### 移动到核心层的文件 -``` -src/business/zulip/services/ → src/core/zulip/services/ -├── zulip_client.service.ts -├── zulip_client_pool.service.ts -├── config_manager.service.ts -├── api_key_security.service.ts -├── error_handler.service.ts -├── monitoring.service.ts -├── stream_initializer.service.ts -└── 对应的 .spec.ts 测试文件 - -src/business/zulip/ → src/core/zulip/ -├── interfaces/ -├── config/ -└── types/ -``` - -## 架构优势 - -### 1. 符合分层架构原则 -- **业务层**:只关注游戏相关的业务逻辑和规则 -- **核心层**:只处理技术实现和第三方API调用 - -### 2. 依赖倒置 -- 业务层依赖接口,不依赖具体实现 -- 核心层提供接口实现 -- 便于测试和替换实现 - -### 3. 单一职责 -- 每个服务职责明确 -- 业务逻辑与技术实现分离 -- 代码更易维护和理解 - -### 4. 可测试性 -- 业务逻辑可以独立测试 -- 通过Mock接口进行单元测试 -- 技术实现可以独立验证 - -## 当前状态 - -### ✅ 已完成 -- [x] 文件移动和重新组织 -- [x] 接口定义和抽象 -- [x] 依赖注入重构 -- [x] 模块结构调整 -- [x] 编译通过验证 -- [x] 测试文件的依赖注入配置更新 -- [x] 所有测试用例通过验证 - -### ✅ 测试修复完成 -- [x] `zulip_event_processor.service.spec.ts` - 更新依赖注入配置 -- [x] `message_filter.service.spec.ts` - 已通过测试 -- [x] `session_manager.service.spec.ts` - 已通过测试 -- [x] 核心服务测试文件导入路径修复 -- [x] 所有Zulip相关测试通过 - -## 使用指南 - -### 业务层开发 -```typescript -// 在业务服务中使用核心服务 -@Injectable() -export class MyBusinessService { - constructor( - @Inject('ZULIP_CLIENT_POOL_SERVICE') - private readonly zulipClientPool: IZulipClientPoolService, - ) {} -} -``` - -### 测试配置 -```typescript -// 测试中Mock核心服务 -const mockZulipClientPool: IZulipClientPoolService = { - sendMessage: jest.fn().mockResolvedValue({ success: true }), - // ... -}; - -const module = await Test.createTestingModule({ - providers: [ - MyBusinessService, - { provide: 'ZULIP_CLIENT_POOL_SERVICE', useValue: mockZulipClientPool }, - ], -}).compile(); -``` - -## 总结 - -重构成功实现了以下目标: - -1. **架构合规**:符合项目的分层架构设计原则 -2. **职责分离**:业务逻辑与技术实现清晰分离 -3. **依赖解耦**:通过接口实现依赖倒置 -4. **可维护性**:代码结构更清晰,易于维护和扩展 -5. **可测试性**:业务逻辑可以独立测试 - -项目现在具有更好的架构设计,为后续开发和维护奠定了良好基础。 \ No newline at end of file diff --git a/deploy.sh.example b/deploy.sh.example deleted file mode 100644 index 7e97101..0000000 --- a/deploy.sh.example +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# 部署脚本模板 - 用于 Gitea Webhook 自动部署 -# 复制此文件为 deploy.sh 并根据服务器环境修改配置 -set -e - -echo "开始部署 Pixel Game Server..." - -# 项目路径(根据你的服务器实际路径修改) -PROJECT_PATH="/var/www/pixel-game-server" -BACKUP_PATH="/var/backups/pixel-game-server" - -# 创建备份 -echo "创建备份..." -mkdir -p $BACKUP_PATH -cp -r $PROJECT_PATH $BACKUP_PATH/backup-$(date +%Y%m%d-%H%M%S) - -# 进入项目目录 -cd $PROJECT_PATH - -# 拉取最新代码 -echo "拉取最新代码..." -git pull origin main - -# 安装/更新依赖 -echo "安装依赖..." -pnpm install --frozen-lockfile - -# 构建项目 -echo "构建项目..." -pnpm run build - -# 重启服务 -echo "重启服务..." -if command -v pm2 &> /dev/null; then - # 使用 PM2 - pm2 restart pixel-game-server || pm2 start dist/main.js --name pixel-game-server -elif command -v docker-compose &> /dev/null; then - # 使用 Docker Compose - docker-compose down - docker-compose up -d --build -else - # 使用 systemd - sudo systemctl restart pixel-game-server -fi - -echo "部署完成!" - -# 清理旧备份(保留最近5个) -find $BACKUP_PATH -maxdepth 1 -type d -name "backup-*" | sort -r | tail -n +6 | xargs rm -rf - -echo "服务状态检查..." -sleep 5 -curl -f http://localhost:3000/health || echo "警告:服务健康检查失败" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 957b459..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: '3.8' - -services: - app: - build: . - ports: - - "3000:3000" - environment: - - NODE_ENV=production - - DB_HOST=mysql - - DB_PORT=3306 - - DB_USERNAME=pixel_game - - DB_PASSWORD=your_password - - DB_NAME=pixel_game_db - depends_on: - - mysql - restart: unless-stopped - volumes: - - ./logs:/app/logs - - mysql: - image: mysql:8.0 - environment: - - MYSQL_ROOT_PASSWORD=root_password - - MYSQL_DATABASE=pixel_game_db - - MYSQL_USER=pixel_game - - MYSQL_PASSWORD=your_password - ports: - - "3306:3306" - volumes: - - mysql_data:/var/lib/mysql - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - restart: unless-stopped - -volumes: - mysql_data: \ No newline at end of file diff --git a/docs/API_STATUS_CODES.md b/docs/API_STATUS_CODES.md deleted file mode 100644 index 1042acb..0000000 --- a/docs/API_STATUS_CODES.md +++ /dev/null @@ -1,257 +0,0 @@ -# API 状态码说明 - -## 📊 概述 - -本文档说明了项目中使用的 HTTP 状态码,特别是针对邮件发送功能的特殊状态码处理。 - -## 🔢 标准状态码 - -| 状态码 | 含义 | 使用场景 | -|--------|------|----------| -| 200 | OK | 请求成功 | -| 201 | Created | 资源创建成功(如用户注册) | -| 400 | Bad Request | 请求参数错误 | -| 401 | Unauthorized | 未授权(如密码错误) | -| 403 | Forbidden | 权限不足 | -| 404 | Not Found | 资源不存在 | -| 409 | Conflict | 资源冲突(如用户名已存在) | -| 429 | Too Many Requests | 请求频率过高 | -| 500 | Internal Server Error | 服务器内部错误 | - -## 🎯 特殊状态码 - -### 206 Partial Content - 测试模式 - -**使用场景:** 邮件发送功能在测试模式下使用 - -**含义:** 请求部分成功,但未完全达到预期效果 - -**具体应用:** -- 验证码已生成,但邮件未真实发送 -- 功能正常工作,但处于测试/开发模式 -- 用户可以获得验证码进行测试,但需要知道这不是真实发送 - -**响应示例:** - -```json -{ - "success": false, - "data": { - "verification_code": "123456", - "is_test_mode": true - }, - "message": "⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。", - "error_code": "TEST_MODE_ONLY" -} -``` - -## 📧 邮件发送接口状态码 - -### 发送邮箱验证码 - POST /auth/send-email-verification - -| 状态码 | 场景 | 响应 | -|--------|------|------| -| 200 | 邮件真实发送成功 | `{ "success": true, "message": "验证码已发送,请查收邮件" }` | -| 206 | 测试模式 | `{ "success": false, "error_code": "TEST_MODE_ONLY", "data": { "verification_code": "123456", "is_test_mode": true } }` | -| 400 | 参数错误 | `{ "success": false, "message": "邮箱格式错误" }` | -| 429 | 发送频率过高 | `{ "success": false, "message": "发送频率过高,请稍后重试" }` | - -### 发送密码重置验证码 - POST /auth/forgot-password - -| 状态码 | 场景 | 响应 | -|--------|------|------| -| 200 | 邮件真实发送成功 | `{ "success": true, "message": "验证码已发送,请查收" }` | -| 206 | 测试模式 | `{ "success": false, "error_code": "TEST_MODE_ONLY", "data": { "verification_code": "123456", "is_test_mode": true } }` | -| 400 | 参数错误 | `{ "success": false, "message": "邮箱格式错误" }` | -| 404 | 用户不存在 | `{ "success": false, "message": "用户不存在" }` | - -### 重新发送邮箱验证码 - POST /auth/resend-email-verification - -| 状态码 | 场景 | 响应 | -|--------|------|------| -| 200 | 邮件真实发送成功 | `{ "success": true, "message": "验证码已重新发送,请查收邮件" }` | -| 206 | 测试模式 | `{ "success": false, "error_code": "TEST_MODE_ONLY", "data": { "verification_code": "123456", "is_test_mode": true } }` | -| 400 | 邮箱已验证或用户不存在 | `{ "success": false, "message": "邮箱已验证,无需重复验证" }` | -| 429 | 发送频率过高 | `{ "success": false, "message": "发送频率过高,请稍后重试" }` | - -## 🔄 模式切换 - -### 测试模式 → 真实发送模式 - -**配置前(测试模式):** -```bash -curl -X POST http://localhost:3000/auth/send-email-verification \ - -H "Content-Type: application/json" \ - -d '{"email": "test@example.com"}' - -# 响应:206 Partial Content -{ - "success": false, - "data": { - "verification_code": "123456", - "is_test_mode": true - }, - "message": "⚠️ 测试模式:验证码已生成但未真实发送...", - "error_code": "TEST_MODE_ONLY" -} -``` - -**配置后(真实发送模式):** -```bash -# 同样的请求 -curl -X POST http://localhost:3000/auth/send-email-verification \ - -H "Content-Type: application/json" \ - -d '{"email": "test@example.com"}' - -# 响应:200 OK -{ - "success": true, - "data": { - "is_test_mode": false - }, - "message": "验证码已发送,请查收邮件" -} -``` - -## 💡 前端处理建议 - -### JavaScript 示例 - -```javascript -async function sendEmailVerification(email) { - try { - const response = await fetch('/auth/send-email-verification', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ email }), - }); - - const data = await response.json(); - - if (response.status === 200) { - // 真实发送成功 - showSuccess('验证码已发送,请查收邮件'); - } else if (response.status === 206) { - // 测试模式 - showWarning(`测试模式:验证码是 ${data.data.verification_code}`); - showInfo('请配置邮件服务以启用真实发送'); - } else { - // 其他错误 - showError(data.message); - } - } catch (error) { - showError('网络错误,请稍后重试'); - } -} -``` - -### React 示例 - -```jsx -const handleSendVerification = async (email) => { - try { - const response = await fetch('/auth/send-email-verification', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ email }), - }); - - const data = await response.json(); - - switch (response.status) { - case 200: - setMessage({ type: 'success', text: '验证码已发送,请查收邮件' }); - break; - case 206: - setMessage({ - type: 'warning', - text: `测试模式:验证码是 ${data.data.verification_code}` - }); - setShowConfigTip(true); - break; - case 400: - setMessage({ type: 'error', text: data.message }); - break; - case 429: - setMessage({ type: 'error', text: '发送频率过高,请稍后重试' }); - break; - default: - setMessage({ type: 'error', text: '发送失败,请稍后重试' }); - } - } catch (error) { - setMessage({ type: 'error', text: '网络错误,请稍后重试' }); - } -}; -``` - -## 🎨 UI 展示建议 - -### 测试模式提示 - -```html - -
- ✅ 验证码已发送,请查收邮件 -
- - -
- ⚠️ 测试模式:验证码是 123456 -
- 请配置邮件服务以启用真实发送 -
- - -
- ❌ 发送失败:邮箱格式错误 -
-``` - -## 📝 开发建议 - -### 1. 状态码检查 - -```javascript -// 推荐:明确检查状态码 -if (response.status === 206) { - // 处理测试模式 -} else if (response.status === 200) { - // 处理真实发送 -} - -// 不推荐:只检查 success 字段 -if (data.success) { - // 可能遗漏测试模式的情况 -} -``` - -### 2. 错误处理 - -```javascript -// 推荐:根据 error_code 进行精确处理 -switch (data.error_code) { - case 'TEST_MODE_ONLY': - handleTestMode(data); - break; - case 'SEND_CODE_FAILED': - handleSendFailure(data); - break; - default: - handleGenericError(data); -} -``` - -### 3. 用户体验 - -- **测试模式**:清晰提示用户当前处于测试模式 -- **配置引导**:提供配置邮件服务的链接或说明 -- **验证码显示**:在测试模式下直接显示验证码 -- **状态区分**:用不同的颜色和图标区分不同状态 - -## 🔗 相关文档 - -- [邮件服务配置指南](./EMAIL_CONFIGURATION.md) -- [快速启动指南](./QUICK_START.md) -- [API 文档](./api/README.md) \ No newline at end of file diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 514dca2..3b858e2 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -25,6 +25,29 @@ Whale Town 采用**业务功能模块化架构**,将代码按业务功能而 - **模块化设计** - 每个模块独立完整,可单独测试和部署 - **配置驱动** - 通过环境变量控制运行模式和行为 +### 🛠️ 技术栈 + +#### 后端技术栈 +- **框架**: NestJS 11.x (基于Express) +- **语言**: TypeScript 5.x +- **数据库**: MySQL + TypeORM (生产) / 内存数据库 (开发) +- **缓存**: Redis + IORedis (生产) / 文件存储 (开发) +- **认证**: JWT + bcrypt +- **验证**: class-validator + class-transformer +- **文档**: Swagger/OpenAPI +- **测试**: Jest + Supertest +- **日志**: Pino + nestjs-pino +- **WebSocket**: Socket.IO +- **邮件**: Nodemailer +- **集成**: Zulip API + +#### 前端技术栈 +- **框架**: React 18.x +- **构建工具**: Vite 7.x +- **UI库**: Ant Design 5.x +- **路由**: React Router DOM 6.x +- **语言**: TypeScript 5.x + ### 📊 整体架构图 ``` @@ -40,11 +63,11 @@ Whale Town 采用**业务功能模块化架构**,将代码按业务功能而 │ 🎯 业务功能模块层 │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ 🔐 用户认证 │ │ 👥 用户管理 │ │ 🛡️ 管理员 │ │ -│ │ (auth) │ │ (user-mgmt) │ │ (admin) │ │ +│ │ (auth) │ │ (user_mgmt) │ │ (admin) │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ 🔒 安全防护 │ │ 💬 Zulip集成 │ │ 🔗 共享组件 │ │ -│ │ (security) │ │ (zulip) │ │ (shared) │ │ +│ │ 💬 Zulip集成 │ │ 🔗 共享组件 │ │ │ │ +│ │ (zulip) │ │ (shared) │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ⬇️ @@ -52,11 +75,11 @@ Whale Town 采用**业务功能模块化架构**,将代码按业务功能而 │ ⚙️ 核心技术服务层 │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ 🔑 登录核心 │ │ 👑 管理员核心 │ │ 💬 Zulip核心 │ │ -│ │ (login_core) │ │ (admin_core) │ │ (zulip) │ │ +│ │ (auth_core) │ │ (admin_core) │ │ (zulip) │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ 🛠️ 工具服务 │ │ 📧 邮件服务 │ │ 📝 日志服务 │ │ -│ │ (utils) │ │ (email) │ │ (logger) │ │ +│ │ 🛡️ 安全核心 │ │ 🛠️ 工具服务 │ │ 📧 邮件服务 │ │ +│ │ (security_core)│ │ (utils) │ │ (email) │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ⬇️ @@ -80,56 +103,50 @@ Whale Town 采用**业务功能模块化架构**,将代码按业务功能而 ``` src/business/ ├── 📂 auth/ # 🔐 用户认证模块 -│ ├── 📄 auth.controller.ts # HTTP接口控制器 -│ ├── 📄 auth.service.ts # 业务逻辑服务 │ ├── 📄 auth.module.ts # 模块定义 +│ ├── 📂 controllers/ # 控制器 +│ │ └── 📄 login.controller.ts # 登录接口控制器 +│ ├── 📂 services/ # 业务服务 +│ │ ├── 📄 login.service.ts # 登录业务逻辑 +│ │ └── 📄 login.service.spec.ts # 登录服务测试 │ ├── 📂 dto/ # 数据传输对象 │ │ ├── 📄 login.dto.ts # 登录请求DTO -│ │ ├── 📄 register.dto.ts # 注册请求DTO -│ │ └── 📄 reset-password.dto.ts # 重置密码DTO -│ └── 📂 __tests__/ # 单元测试 -│ └── 📄 auth.service.spec.ts +│ │ └── 📄 login_response.dto.ts # 登录响应DTO +│ └── 📂 guards/ # 权限守卫(预留) │ ├── 📂 user-mgmt/ # 👥 用户管理模块 -│ ├── 📄 user-mgmt.controller.ts # 用户管理接口 -│ ├── 📄 user-mgmt.service.ts # 用户状态管理逻辑 │ ├── 📄 user-mgmt.module.ts # 模块定义 +│ ├── 📂 controllers/ # 控制器 +│ │ └── 📄 user-status.controller.ts # 用户状态管理接口 +│ ├── 📂 services/ # 业务服务 +│ │ └── 📄 user-management.service.ts # 用户管理逻辑 │ ├── 📂 dto/ # 数据传输对象 -│ │ ├── 📄 update-status.dto.ts # 状态更新DTO -│ │ └── 📄 batch-status.dto.ts # 批量操作DTO -│ └── 📂 enums/ # 枚举定义 -│ └── 📄 user-status.enum.ts # 用户状态枚举 +│ │ ├── 📄 user-status.dto.ts # 用户状态DTO +│ │ └── 📄 user-status-response.dto.ts # 状态响应DTO +│ ├── 📂 enums/ # 枚举定义 +│ │ └── 📄 user-status.enum.ts # 用户状态枚举 +│ └── 📂 tests/ # 测试文件(预留) │ ├── 📂 admin/ # 🛡️ 管理员模块 │ ├── 📄 admin.controller.ts # 管理员接口 │ ├── 📄 admin.service.ts # 管理员业务逻辑 │ ├── 📄 admin.module.ts # 模块定义 +│ ├── 📄 admin.service.spec.ts # 管理员服务测试 │ ├── 📂 dto/ # 数据传输对象 │ └── 📂 guards/ # 权限守卫 -│ └── 📄 admin.guard.ts # 管理员权限验证 -│ -├── 📂 security/ # 🔒 安全防护模块 -│ ├── 📄 security.module.ts # 安全模块定义 -│ ├── 📂 guards/ # 安全守卫 -│ │ ├── 📄 throttle.guard.ts # 频率限制守卫 -│ │ ├── 📄 maintenance.guard.ts # 维护模式守卫 -│ │ └── 📄 content-type.guard.ts # 内容类型守卫 -│ └── 📂 interceptors/ # 拦截器 -│ └── 📄 timeout.interceptor.ts # 超时拦截器 │ ├── 📂 zulip/ # 💬 Zulip集成模块 │ ├── 📄 zulip.service.ts # Zulip业务服务 │ ├── 📄 zulip_websocket.gateway.ts # WebSocket网关 │ ├── 📄 zulip.module.ts # 模块定义 +│ ├── 📂 interfaces/ # 接口定义 │ └── 📂 services/ # 子服务 │ ├── 📄 message_filter.service.ts # 消息过滤 │ └── 📄 session_cleanup.service.ts # 会话清理 │ └── 📂 shared/ # 🔗 共享业务组件 - ├── 📂 decorators/ # 装饰器 - ├── 📂 pipes/ # 管道 - ├── 📂 filters/ # 异常过滤器 - └── 📂 interfaces/ # 接口定义 + ├── 📂 dto/ # 共享数据传输对象 + └── 📄 index.ts # 导出文件 ``` ### ⚙️ 核心技术服务 (`src/core/`) @@ -139,72 +156,84 @@ src/business/ ``` src/core/ ├── 📂 db/ # 🗄️ 数据库层 -│ ├── 📄 db.module.ts # 数据库模块 -│ ├── 📂 users/ # 用户数据服务 -│ │ ├── 📄 users.service.ts # MySQL数据库实现 -│ │ ├── 📄 users-memory.service.ts # 内存数据库实现 -│ │ ├── 📄 users.interface.ts # 用户服务接口 -│ │ └── 📄 user.entity.ts # 用户实体定义 -│ └── 📂 entities/ # 数据库实体 -│ └── 📄 *.entity.ts # 各种实体定义 +│ └── 📂 users/ # 用户数据服务 +│ ├── 📄 users.service.ts # MySQL数据库实现 +│ ├── 📄 users_memory.service.ts # 内存数据库实现 +│ ├── 📄 users.dto.ts # 用户数据传输对象 +│ ├── 📄 users.entity.ts # 用户实体定义 +│ ├── 📄 users.module.ts # 用户数据模块 +│ └── 📄 users.service.spec.ts # 用户服务测试 │ ├── 📂 redis/ # 🔴 Redis缓存层 │ ├── 📄 redis.module.ts # Redis模块 -│ ├── 📄 redis.service.ts # Redis真实实现 +│ ├── 📄 real-redis.service.ts # Redis真实实现 │ ├── 📄 file-redis.service.ts # 文件存储实现 │ └── 📄 redis.interface.ts # Redis服务接口 │ ├── 📂 login_core/ # 🔑 登录核心服务 -│ ├── 📄 login-core.service.ts # 登录核心逻辑 -│ ├── 📄 login-core.module.ts # 模块定义 -│ └── 📄 login-core.interface.ts # 接口定义 +│ ├── 📄 login_core.service.ts # 登录核心逻辑 +│ ├── 📄 login_core.module.ts # 模块定义 +│ └── 📄 login_core.service.spec.ts # 登录核心测试 │ ├── 📂 admin_core/ # 👑 管理员核心服务 -│ ├── 📄 admin-core.service.ts # 管理员核心逻辑 -│ ├── 📄 admin-core.module.ts # 模块定义 -│ └── 📄 admin-core.interface.ts # 接口定义 +│ ├── 📄 admin_core.service.ts # 管理员核心逻辑 +│ ├── 📄 admin_core.module.ts # 模块定义 +│ └── 📄 admin_core.service.spec.ts # 管理员核心测试 │ ├── 📂 zulip/ # 💬 Zulip核心服务 │ ├── 📄 zulip-core.module.ts # Zulip核心模块 -│ ├── 📄 zulip-api.service.ts # Zulip API服务 -│ └── 📄 zulip-websocket.service.ts # WebSocket服务 +│ ├── 📂 config/ # 配置文件 +│ ├── 📂 interfaces/ # 接口定义 +│ ├── 📂 services/ # 核心服务 +│ ├── 📂 types/ # 类型定义 +│ └── 📄 index.ts # 导出文件 +│ +├── 📂 security_core/ # 🛡️ 安全核心模块 +│ ├── 📄 security_core.module.ts # 安全模块定义 +│ ├── 📂 guards/ # 安全守卫 +│ │ └── 📄 throttle.guard.ts # 频率限制守卫 +│ ├── 📂 interceptors/ # 拦截器 +│ │ └── 📄 timeout.interceptor.ts # 超时拦截器 +│ ├── 📂 middleware/ # 中间件 +│ │ ├── 📄 maintenance.middleware.ts # 维护模式中间件 +│ │ └── 📄 content_type.middleware.ts # 内容类型中间件 +│ └── 📂 decorators/ # 装饰器 +│ ├── 📄 throttle.decorator.ts # 频率限制装饰器 +│ └── 📄 timeout.decorator.ts # 超时装饰器 │ └── 📂 utils/ # 🛠️ 工具服务 ├── 📂 email/ # 📧 邮件服务 │ ├── 📄 email.service.ts # 邮件发送服务 │ ├── 📄 email.module.ts # 邮件模块 - │ └── 📄 email.interface.ts # 邮件接口 + │ └── 📄 email.service.spec.ts # 邮件服务测试 ├── 📂 verification/ # 🔢 验证码服务 │ ├── 📄 verification.service.ts # 验证码生成验证 - │ └── 📄 verification.module.ts # 验证码模块 + │ ├── 📄 verification.module.ts # 验证码模块 + │ └── 📄 verification.service.spec.ts # 验证码服务测试 └── 📂 logger/ # 📝 日志服务 ├── 📄 logger.service.ts # 日志记录服务 - └── 📄 logger.module.ts # 日志模块 + ├── 📄 logger.module.ts # 日志模块 + ├── 📄 logger.config.ts # 日志配置 + └── 📄 log_management.service.ts # 日志管理服务 ``` ### 🎨 前端管理界面 (`client/`) -> **设计原则**: 独立的前端项目,提供管理员后台功能 +> **设计原则**: 独立的前端项目,提供管理员后台功能,基于React + Vite + Ant Design ``` client/ ├── 📂 src/ # 前端源码 -│ ├── 📂 components/ # 通用组件 -│ │ ├── 📄 Layout.tsx # 布局组件 -│ │ ├── 📄 UserTable.tsx # 用户表格组件 -│ │ └── 📄 LogViewer.tsx # 日志查看组件 +│ ├── 📂 app/ # 应用组件 +│ │ ├── 📄 App.tsx # 应用主组件 +│ │ └── 📄 AdminLayout.tsx # 管理员布局组件 │ ├── 📂 pages/ # 页面组件 -│ │ ├── 📄 Login.tsx # 登录页面 -│ │ ├── 📄 Dashboard.tsx # 仪表板 -│ │ ├── 📄 UserManagement.tsx # 用户管理 -│ │ └── 📄 LogManagement.tsx # 日志管理 -│ ├── 📂 services/ # API服务 +│ │ ├── 📄 LoginPage.tsx # 登录页面 +│ │ ├── 📄 UsersPage.tsx # 用户管理页面 +│ │ └── 📄 LogsPage.tsx # 日志管理页面 +│ ├── 📂 lib/ # 工具库 │ │ ├── 📄 api.ts # API客户端 -│ │ ├── 📄 auth.ts # 认证服务 -│ │ └── 📄 users.ts # 用户服务 -│ ├── 📂 utils/ # 工具函数 -│ ├── 📂 types/ # TypeScript类型 -│ ├── 📄 App.tsx # 应用主组件 +│ │ └── 📄 adminAuth.ts # 管理员认证服务 │ └── 📄 main.tsx # 应用入口 ├── 📂 dist/ # 构建产物 ├── 📄 package.json # 前端依赖 @@ -220,21 +249,17 @@ client/ docs/ ├── 📄 README.md # 📖 文档导航中心 ├── 📄 ARCHITECTURE.md # 🏗️ 架构设计文档 -├── 📄 API_STATUS_CODES.md # 📋 API状态码说明 ├── 📄 CONTRIBUTORS.md # 🤝 贡献者指南 │ ├── 📂 api/ # 🔌 API接口文档 │ ├── 📄 README.md # API文档使用指南 -│ ├── 📄 api-documentation.md # 完整API接口文档 -│ ├── 📄 openapi.yaml # OpenAPI规范文件 -│ └── 📄 postman-collection.json # Postman测试集合 +│ └── 📄 api-documentation.md # 完整API接口文档 │ ├── 📂 development/ # 💻 开发指南 │ ├── 📄 backend_development_guide.md # 后端开发规范 │ ├── 📄 git_commit_guide.md # Git提交规范 │ ├── 📄 AI辅助开发规范指南.md # AI辅助开发指南 -│ ├── 📄 TESTING.md # 测试指南 -│ └── 📄 naming_convention.md # 命名规范 +│ └── 📄 TESTING.md # 测试指南 │ └── 📂 deployment/ # 🚀 部署文档 └── 📄 DEPLOYMENT.md # 生产环境部署指南 @@ -261,14 +286,17 @@ test/ ├── 📄 .env # 🔧 环境变量配置 ├── 📄 .env.example # 🔧 环境变量示例 ├── 📄 .env.production.example # 🔧 生产环境示例 -├── 📄 package.json # 📋 项目依赖配置 +├── 📄 package.json # 📋 后端项目依赖配置 ├── 📄 pnpm-workspace.yaml # 📦 pnpm工作空间配置 ├── 📄 tsconfig.json # 📘 TypeScript配置 ├── 📄 jest.config.js # 🧪 Jest测试配置 ├── 📄 nest-cli.json # 🏠 NestJS CLI配置 -├── 📄 docker-compose.yml # 🐳 Docker编排配置 -├── 📄 Dockerfile # 🐳 Docker镜像配置 └── 📄 ecosystem.config.js # 🚀 PM2进程管理配置 + +client/ +├── 📄 package.json # 📋 前端项目依赖配置 +├── 📄 vite.config.ts # ⚡ Vite构建配置 +└── 📄 tsconfig.json # 📘 前端TypeScript配置 ``` --- @@ -327,18 +355,17 @@ test/ ### 🔄 数据流向 -#### 用户注册流程示例 +#### 用户登录流程示例 ``` -1. 📱 用户请求 → AuthController.register() +1. 📱 用户请求 → LoginController.login() 2. 🔍 参数验证 → class-validator装饰器 -3. 🎯 业务逻辑 → AuthService.register() -4. ⚙️ 核心服务 → LoginCoreService.createUser() -5. 📧 发送邮件 → EmailService.sendVerificationCode() -6. 🔢 生成验证码 → VerificationService.generate() -7. 💾 存储数据 → UsersService.create() + RedisService.set() -8. 📝 记录日志 → LoggerService.log() -9. ✅ 返回响应 → 用户收到成功响应 +3. 🎯 业务逻辑 → LoginService.login() +4. ⚙️ 核心服务 → LoginCoreService.validateUser() +5. 📧 发送验证码 → VerificationService.generate() +6. 💾 存储数据 → UsersService.findByEmail() + RedisService.set() +7. 📝 记录日志 → LoggerService.log() +8. ✅ 返回响应 → 用户收到登录结果 ``` #### 管理员操作流程示例 @@ -369,7 +396,7 @@ test/ | 功能模块 | 🧪 开发测试模式 | 🚀 生产部署模式 | |----------|----------------|----------------| | **数据库** | 内存存储 (UsersMemoryService) | MySQL (UsersService + TypeORM) | -| **缓存** | 文件存储 (FileRedisService) | Redis (RedisService + IORedis) | +| **缓存** | 文件存储 (FileRedisService) | Redis (RealRedisService + IORedis) | | **邮件** | 控制台输出 (测试模式) | SMTP服务器 (生产模式) | | **日志** | 控制台 + 文件 | 结构化日志 + 日志轮转 | | **配置** | `.env` 默认配置 | 环境变量 + 配置中心 | @@ -431,7 +458,7 @@ EMAIL_PASS=your_app_password const useFileRedis = configService.get('USE_FILE_REDIS'); return useFileRedis ? new FileRedisService() - : new RedisService(configService); + : new RealRedisService(configService); }, inject: [ConfigService], }, @@ -471,7 +498,7 @@ AppModule (应用主模块) ├── 📊 ConfigModule (全局配置) ├── 📝 LoggerModule (日志系统) ├── 🔴 RedisModule (缓存服务) -│ ├── RedisService (真实Redis) +│ ├── RealRedisService (真实Redis) │ └── FileRedisService (文件存储) ├── 🗄️ UsersModule (用户数据) │ ├── UsersService (MySQL数据库) @@ -481,16 +508,15 @@ AppModule (应用主模块) ├── 🔑 LoginCoreModule (登录核心) ├── 👑 AdminCoreModule (管理员核心) ├── 💬 ZulipCoreModule (Zulip核心) +├── 🔒 SecurityCoreModule (安全核心) │ ├── 🎯 业务功能模块 │ ├── 🔐 AuthModule (用户认证) -│ │ └── 依赖: LoginCoreModule, EmailModule, VerificationModule +│ │ └── 依赖: LoginCoreModule, EmailModule, VerificationModule, SecurityCoreModule │ ├── 👥 UserMgmtModule (用户管理) -│ │ └── 依赖: UsersModule, LoggerModule +│ │ └── 依赖: UsersModule, LoggerModule, SecurityCoreModule │ ├── 🛡️ AdminModule (管理员) -│ │ └── 依赖: AdminCoreModule, UsersModule -│ ├── 🔒 SecurityModule (安全防护) -│ │ └── 依赖: RedisModule, LoggerModule +│ │ └── 依赖: AdminCoreModule, UsersModule, SecurityCoreModule │ ├── 💬 ZulipModule (Zulip集成) │ │ └── 依赖: ZulipCoreModule, RedisModule │ └── 🔗 SharedModule (共享组件) @@ -500,7 +526,7 @@ AppModule (应用主模块) #### 用户认证流程 ``` -AuthController → AuthService → LoginCoreService +AuthController → LoginService → LoginCoreService ↓ EmailService ← VerificationService ← RedisService ↓ diff --git a/docs/DOCUMENT_CLEANUP.md b/docs/DOCUMENT_CLEANUP.md deleted file mode 100644 index 5a0df87..0000000 --- a/docs/DOCUMENT_CLEANUP.md +++ /dev/null @@ -1,142 +0,0 @@ -# 📝 文档清理说明 - -> 记录项目文档整理和优化的过程,确保文档结构清晰、内容准确。 - -## 🎯 清理目标 - -- **删除多余README** - 移除重复和过时的README文件 -- **优化主文档** - 改进项目主README的文件格式和结构说明 -- **完善架构文档** - 详细说明项目架构和文件夹组织结构 -- **统一文档风格** - 采用总分结构,方便开发者理解 - -## 📊 文档清理结果 - -### ✅ 保留的README文件 - -| 文件路径 | 保留原因 | 主要内容 | -|----------|----------|----------| -| `README.md` | 项目主文档 | 项目介绍、快速开始、技术栈、功能特性 | -| `docs/README.md` | 文档导航中心 | 文档结构说明、导航链接 | -| `client/README.md` | 前端项目文档 | 前端管理界面的独立说明 | -| `docs/api/README.md` | API文档指南 | API文档使用说明和快速测试 | -| `src/business/zulip/README.md` | 模块架构说明 | Zulip模块重构的详细说明 | - -### ❌ 删除的README文件 - -**无** - 经过分析,所有现有README文件都有其存在价值,未删除任何文件。 - -### 🔄 优化的文档 - -#### 1. 主README.md优化 -- **文件结构总览** - 添加了详细的项目文件结构说明 -- **图标化展示** - 使用emoji图标让结构更直观 -- **层次化组织** - 按照总分结构组织内容 - -#### 2. 架构文档大幅改进 (docs/ARCHITECTURE.md) -- **完整重写** - 从简单的架构图扩展为完整的架构设计文档 -- **目录结构详解** - 详细说明每个文件夹的作用和内容 -- **分层架构设计** - 清晰的架构分层和模块依赖关系 -- **双模式架构** - 详细说明开发测试模式和生产部署模式 -- **扩展指南** - 提供添加新模块和功能的详细指导 - -## 📁 文档结构优化 - -### 🎯 总分结构设计 - -采用**总分结构**组织文档,便于开发者快速理解: - -``` -📚 文档层次结构 -├── 🏠 项目总览 (README.md) -│ ├── 🎯 项目简介和特性 -│ ├── 🚀 快速开始指南 -│ ├── 📁 文件结构总览 ⭐ 新增 -│ ├── 🛠️ 技术栈说明 -│ └── 📚 文档导航链接 -│ -├── 🏗️ 架构设计 (docs/ARCHITECTURE.md) ⭐ 大幅改进 -│ ├── 📊 整体架构图 -│ ├── 📁 目录结构详解 -│ ├── 🏗️ 分层架构设计 -│ ├── 🔄 双模式架构 -│ └── 🚀 扩展指南 -│ -├── 📖 文档中心 (docs/README.md) -│ ├── 📋 文档导航 -│ ├── 🏗️ 文档结构说明 -│ └── 📝 文档维护原则 -│ -├── 🔌 API文档 (docs/api/README.md) -│ ├── 📊 API接口概览 -│ ├── 🚀 快速开始 -│ └── 🧪 测试指南 -│ -└── 🎨 前端文档 (client/README.md) - ├── 🚀 快速开始 - ├── 🎯 核心功能 - └── 🔧 开发指南 -``` - -### 📊 文档内容优化 - -#### 1. 视觉化改进 -- **emoji图标** - 使用统一的emoji图标系统 -- **表格展示** - 用表格清晰展示对比信息 -- **代码示例** - 提供完整的代码示例和配置 -- **架构图** - 使用ASCII艺术绘制清晰的架构图 - -#### 2. 结构化内容 -- **目录导航** - 每个长文档都有详细目录 -- **分层说明** - 按照业务功能模块化的原则组织 -- **实用指南** - 提供具体的操作步骤和扩展指南 - -#### 3. 开发者友好 -- **快速上手** - 新开发者指南,从规范学习到架构理解 -- **总分结构** - 先总览后详细,便于快速理解 -- **实际案例** - 提供真实的代码示例和使用场景 - -## 🎯 文档维护原则 - -### ✅ 保留标准 -- **长期价值** - 对整个项目生命周期都有价值 -- **参考价值** - 开发、部署、维护时需要查阅 -- **规范指导** - 团队协作和代码质量保证 - -### ❌ 清理标准 -- **阶段性文档** - 只在特定开发阶段有用 -- **临时记录** - 会议记录、临时决策等 -- **过时信息** - 已经不适用的旧版本文档 - -### 🔄 更新策略 -- **及时更新** - 功能变更时同步更新相关文档 -- **版本控制** - 重要变更记录版本历史 -- **定期审查** - 定期检查文档的准确性和有效性 - -## 📈 改进效果 - -### 🎯 开发者体验提升 -- **快速理解** - 通过总分结构快速掌握项目架构 -- **准确信息** - 文档与实际代码结构完全一致 -- **实用指导** - 提供具体的开发和扩展指南 - -### 📚 文档质量提升 -- **结构清晰** - 层次分明的文档组织结构 -- **内容完整** - 覆盖项目的所有重要方面 -- **易于维护** - 明确的维护原则和更新策略 - -### 🚀 项目可维护性提升 -- **架构清晰** - 详细的架构文档便于理解和扩展 -- **规范统一** - 统一的文档风格和组织原则 -- **知识传承** - 完整的文档体系便于团队协作 - ---- - -**📝 通过系统性的文档清理和优化,项目文档现在更加清晰、准确、实用!** - -## 📅 清理记录 - -- **清理时间**: 2025年12月31日 -- **清理范围**: 项目根目录及所有子目录的README文件 -- **主要改进**: 架构文档完全重写,主README结构优化 -- **保留文件**: 5个README文件全部保留 -- **删除文件**: 0个(所有文件都有价值) \ No newline at end of file diff --git a/nest-cli.json b/nest-cli.json index f9aa683..98676bf 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -3,6 +3,12 @@ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { - "deleteOutDir": true + "deleteOutDir": true, + "assets": [ + { + "include": "../config/**/*", + "outDir": "./dist" + } + ] } } diff --git a/src/app.module.ts b/src/app.module.ts index 2355bfc..9835288 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -12,9 +12,9 @@ import { ZulipModule } from './business/zulip/zulip.module'; import { RedisModule } from './core/redis/redis.module'; import { AdminModule } from './business/admin/admin.module'; import { UserMgmtModule } from './business/user-mgmt/user-mgmt.module'; -import { SecurityModule } from './business/security/security.module'; -import { MaintenanceMiddleware } from './business/security/middleware/maintenance.middleware'; -import { ContentTypeMiddleware } from './business/security/middleware/content-type.middleware'; +import { SecurityCoreModule } from './core/security_core/security_core.module'; +import { MaintenanceMiddleware } from './core/security_core/middleware/maintenance.middleware'; +import { ContentTypeMiddleware } from './core/security_core/middleware/content_type.middleware'; /** * 检查数据库配置是否完整 by angjustinl 2025-12-17 @@ -71,7 +71,7 @@ function isDatabaseConfigured(): boolean { ZulipModule, UserMgmtModule, AdminModule, - SecurityModule, + SecurityCoreModule, ], controllers: [AppController], providers: [ diff --git a/src/business/admin/admin.controller.ts b/src/business/admin/admin.controller.ts index cdf2b16..ba9088c 100644 --- a/src/business/admin/admin.controller.ts +++ b/src/business/admin/admin.controller.ts @@ -25,7 +25,7 @@ import { AdminUserResponseDto, AdminRuntimeLogsResponseDto } from './dto/admin-response.dto'; -import { Throttle, ThrottlePresets } from '../security/decorators/throttle.decorator'; +import { Throttle, ThrottlePresets } from '../../core/security_core/decorators/throttle.decorator'; import type { Response } from 'express'; import * as fs from 'fs'; import * as path from 'path'; diff --git a/src/business/auth/controllers/login.controller.ts b/src/business/auth/controllers/login.controller.ts index 37d4a7c..c1d94af 100644 --- a/src/business/auth/controllers/login.controller.ts +++ b/src/business/auth/controllers/login.controller.ts @@ -33,8 +33,8 @@ import { TestModeEmailVerificationResponseDto, SuccessEmailVerificationResponseDto } from '../dto/login_response.dto'; -import { Throttle, ThrottlePresets } from '../../security/decorators/throttle.decorator'; -import { Timeout, TimeoutPresets } from '../../security/decorators/timeout.decorator'; +import { Throttle, ThrottlePresets } from '../../../core/security_core/decorators/throttle.decorator'; +import { Timeout, TimeoutPresets } from '../../../core/security_core/decorators/timeout.decorator'; @ApiTags('auth') @Controller('auth') diff --git a/src/business/user-mgmt/controllers/user-status.controller.ts b/src/business/user-mgmt/controllers/user-status.controller.ts index e58d197..724dcdd 100644 --- a/src/business/user-mgmt/controllers/user-status.controller.ts +++ b/src/business/user-mgmt/controllers/user-status.controller.ts @@ -20,8 +20,8 @@ import { Body, Controller, Get, HttpCode, HttpStatus, Param, Put, Post, UseGuard import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; import { AdminGuard } from '../../admin/guards/admin.guard'; import { UserManagementService } from '../services/user-management.service'; -import { Throttle, ThrottlePresets } from '../../security/decorators/throttle.decorator'; -import { Timeout, TimeoutPresets } from '../../security/decorators/timeout.decorator'; +import { Throttle, ThrottlePresets } from '../../../core/security_core/decorators/throttle.decorator'; +import { Timeout, TimeoutPresets } from '../../../core/security_core/decorators/timeout.decorator'; import { UserStatusDto, BatchUserStatusDto } from '../dto/user-status.dto'; import { UserStatusResponseDto, BatchUserStatusResponseDto, UserStatusStatsResponseDto } from '../dto/user-status-response.dto'; diff --git a/src/business/security/decorators/throttle.decorator.ts b/src/core/security_core/decorators/throttle.decorator.ts similarity index 100% rename from src/business/security/decorators/throttle.decorator.ts rename to src/core/security_core/decorators/throttle.decorator.ts diff --git a/src/business/security/decorators/timeout.decorator.ts b/src/core/security_core/decorators/timeout.decorator.ts similarity index 100% rename from src/business/security/decorators/timeout.decorator.ts rename to src/core/security_core/decorators/timeout.decorator.ts diff --git a/src/business/security/guards/throttle.guard.ts b/src/core/security_core/guards/throttle.guard.ts similarity index 100% rename from src/business/security/guards/throttle.guard.ts rename to src/core/security_core/guards/throttle.guard.ts diff --git a/src/business/security/index.ts b/src/core/security_core/index.ts similarity index 71% rename from src/business/security/index.ts rename to src/core/security_core/index.ts index 1453eb8..7781f83 100644 --- a/src/business/security/index.ts +++ b/src/core/security_core/index.ts @@ -1,5 +1,5 @@ /** - * 安全功能模块导出 + * 核心安全模块导出 * * 功能概述: * - 频率限制和防护机制 @@ -10,14 +10,14 @@ */ // 模块 -export * from './security.module'; +export * from './security_core.module'; // 守卫 export * from './guards/throttle.guard'; // 中间件 export * from './middleware/maintenance.middleware'; -export * from './middleware/content-type.middleware'; +export * from './middleware/content_type.middleware'; // 拦截器 export * from './interceptors/timeout.interceptor'; diff --git a/src/business/security/interceptors/timeout.interceptor.ts b/src/core/security_core/interceptors/timeout.interceptor.ts similarity index 100% rename from src/business/security/interceptors/timeout.interceptor.ts rename to src/core/security_core/interceptors/timeout.interceptor.ts diff --git a/src/business/security/middleware/content-type.middleware.ts b/src/core/security_core/middleware/content_type.middleware.ts similarity index 100% rename from src/business/security/middleware/content-type.middleware.ts rename to src/core/security_core/middleware/content_type.middleware.ts diff --git a/src/business/security/middleware/maintenance.middleware.ts b/src/core/security_core/middleware/maintenance.middleware.ts similarity index 100% rename from src/business/security/middleware/maintenance.middleware.ts rename to src/core/security_core/middleware/maintenance.middleware.ts diff --git a/src/business/security/security.module.ts b/src/core/security_core/security_core.module.ts similarity index 84% rename from src/business/security/security.module.ts rename to src/core/security_core/security_core.module.ts index 80cdd83..4ea6f7a 100644 --- a/src/business/security/security.module.ts +++ b/src/core/security_core/security_core.module.ts @@ -1,11 +1,11 @@ /** - * 安全功能模块 + * 核心安全模块 * * 功能描述: - * - 整合所有安全相关功能 + * - 提供系统级安全防护功能 * - 频率限制和请求超时控制 * - 维护模式和内容类型验证 - * - 系统安全防护机制 + * - 全局安全中间件和守卫 * * @author kiro-ai * @version 1.0.0 @@ -34,4 +34,4 @@ import { TimeoutInterceptor } from './interceptors/timeout.interceptor'; ], exports: [ThrottleGuard, TimeoutInterceptor], }) -export class SecurityModule {} \ No newline at end of file +export class SecurityCoreModule {} \ No newline at end of file diff --git a/src/core/zulip/services/config_manager.service.ts b/src/core/zulip/services/config_manager.service.ts index a340599..5ee40d0 100644 --- a/src/core/zulip/services/config_manager.service.ts +++ b/src/core/zulip/services/config_manager.service.ts @@ -139,10 +139,39 @@ export class ConfigManagerService implements OnModuleDestroy { private configLoadTime: Date; private configWatcher: fs.FSWatcher | null = null; private isWatcherEnabled: boolean = false; - private readonly CONFIG_DIR = path.join(process.cwd(), 'config', 'zulip'); + private readonly CONFIG_DIR = this.getConfigDir(); private readonly MAP_CONFIG_FILE = 'map-config.json'; private readonly logger = new Logger(ConfigManagerService.name); + /** + * 获取配置目录路径 + * + * 在开发环境中使用 config/zulip + * 在生产环境中使用 dist/zulip (编译后的位置) + */ + private getConfigDir(): string { + const isDevelopment = process.env.NODE_ENV !== 'production'; + + if (isDevelopment) { + // 开发环境:使用源码目录 + return path.join(process.cwd(), 'config', 'zulip'); + } else { + // 生产环境:使用编译后的目录 + const distConfigPath = path.join(process.cwd(), 'dist', 'zulip'); + const rootConfigPath = path.join(process.cwd(), 'config', 'zulip'); + + // 优先使用 dist/zulip,如果不存在则回退到 config/zulip + if (fs.existsSync(distConfigPath)) { + return distConfigPath; + } else if (fs.existsSync(rootConfigPath)) { + return rootConfigPath; + } else { + // 都不存在,使用默认路径 + return distConfigPath; + } + } + } + constructor() { this.logger.log('ConfigManagerService初始化完成'); diff --git a/test-comprehensive.ps1 b/test-comprehensive.ps1 deleted file mode 100644 index 41d36f6..0000000 --- a/test-comprehensive.ps1 +++ /dev/null @@ -1,333 +0,0 @@ -# Comprehensive API Test Script -# 综合API测试脚本 - 完整的后端功能测试 -# -# 🧪 测试内容: -# 1. 基础API功能(应用状态、注册、登录) -# 2. 邮箱验证码流程(发送、验证、冲突检测) -# 3. 验证码冷却时间清除功能 -# 4. 限流保护机制 -# 5. 密码重置流程 -# 6. 验证码登录功能 -# 7. 错误处理和边界条件 -# -# 🚀 使用方法: -# .\test-comprehensive.ps1 # 运行完整测试 -# .\test-comprehensive.ps1 -SkipThrottleTest # 跳过限流测试 -# .\test-comprehensive.ps1 -SkipCooldownTest # 跳过冷却测试 -# .\test-comprehensive.ps1 -BaseUrl "https://your-server.com" # 测试远程服务器 - -param( - [string]$BaseUrl = "http://localhost:3000", - [switch]$SkipThrottleTest = $false, - [switch]$SkipCooldownTest = $false -) - -$ErrorActionPreference = "Continue" - -Write-Host "🧪 Comprehensive API Test Suite" -ForegroundColor Green -Write-Host "===============================" -ForegroundColor Green -Write-Host "Base URL: $BaseUrl" -ForegroundColor Yellow -Write-Host "Skip Throttle Test: $SkipThrottleTest" -ForegroundColor Yellow -Write-Host "Skip Cooldown Test: $SkipCooldownTest" -ForegroundColor Yellow - -# Helper function to handle API responses -function Test-ApiCall { - param( - [string]$TestName, - [string]$Url, - [string]$Body, - [string]$Method = "POST", - [int]$ExpectedStatus = 200, - [switch]$Silent = $false - ) - - if (-not $Silent) { - Write-Host "`n📋 $TestName" -ForegroundColor Yellow - } - - try { - $response = Invoke-RestMethod -Uri $Url -Method $Method -Body $Body -ContentType "application/json" -ErrorAction Stop - if (-not $Silent) { - Write-Host "✅ SUCCESS ($(if ($response.success) { 'true' } else { 'false' }))" -ForegroundColor Green - Write-Host "Message: $($response.message)" -ForegroundColor Cyan - } - return $response - } catch { - $statusCode = $_.Exception.Response.StatusCode.value__ - if (-not $Silent) { - Write-Host "❌ FAILED ($statusCode)" -ForegroundColor $(if ($statusCode -eq $ExpectedStatus) { "Yellow" } else { "Red" }) - } - - if ($_.Exception.Response) { - $stream = $_.Exception.Response.GetResponseStream() - $reader = New-Object System.IO.StreamReader($stream) - $responseBody = $reader.ReadToEnd() - $reader.Close() - $stream.Close() - - if ($responseBody) { - try { - $errorResponse = $responseBody | ConvertFrom-Json - if (-not $Silent) { - Write-Host "Message: $($errorResponse.message)" -ForegroundColor Cyan - Write-Host "Error Code: $($errorResponse.error_code)" -ForegroundColor Gray - } - return $errorResponse - } catch { - if (-not $Silent) { - Write-Host "Raw Response: $responseBody" -ForegroundColor Gray - } - } - } - } - return $null - } -} - -# Clear throttle first -Write-Host "`n🔄 Clearing throttle records..." -ForegroundColor Blue -try { - Invoke-RestMethod -Uri "$BaseUrl/auth/debug-clear-throttle" -Method POST | Out-Null - Write-Host "✅ Throttle cleared" -ForegroundColor Green -} catch { - Write-Host "⚠️ Could not clear throttle" -ForegroundColor Yellow -} - -# Test Results Tracking -$testResults = @{ - AppStatus = $false - BasicAPI = $false - EmailConflict = $false - VerificationCodeLogin = $false - CooldownClearing = $false - ThrottleProtection = $false - PasswordReset = $false -} - -Write-Host "`n" + "="*60 -ForegroundColor Cyan -Write-Host "🧪 Test Suite 0: Application Status" -ForegroundColor Cyan -Write-Host "="*60 -ForegroundColor Cyan - -# Test application status -$result0 = Test-ApiCall -TestName "Check application status" -Url "$BaseUrl" -Method "GET" -Body "" - -if ($result0 -and $result0.service -eq "Pixel Game Server") { - $testResults.AppStatus = $true - Write-Host "✅ PASS: Application is running" -ForegroundColor Green - Write-Host " Service: $($result0.service)" -ForegroundColor Cyan - Write-Host " Version: $($result0.version)" -ForegroundColor Cyan - Write-Host " Environment: $($result0.environment)" -ForegroundColor Cyan -} else { - Write-Host "❌ FAIL: Application status check failed" -ForegroundColor Red -} - -Write-Host "`n" + "="*60 -ForegroundColor Cyan -Write-Host "🧪 Test Suite 1: Basic API Functionality" -ForegroundColor Cyan -Write-Host "="*60 -ForegroundColor Cyan - -# Generate unique test data -$testEmail = "comprehensive_test_$(Get-Random)@example.com" -$testUsername = "comp_test_$(Get-Random)" - -# Test 1: Send verification code -$result1 = Test-ApiCall -TestName "Send email verification code" -Url "$BaseUrl/auth/send-email-verification" -Body (@{ - email = $testEmail -} | ConvertTo-Json) - -if ($result1 -and $result1.data.verification_code) { - $verificationCode = $result1.data.verification_code - Write-Host "Got verification code: $verificationCode" -ForegroundColor Green - - # Test 2: Register user - $result2 = Test-ApiCall -TestName "Register new user" -Url "$BaseUrl/auth/register" -Body (@{ - username = $testUsername - password = "password123" - nickname = "Comprehensive Test User" - email = $testEmail - email_verification_code = $verificationCode - } | ConvertTo-Json) - - if ($result2 -and $result2.success) { - # Test 3: Login user - $result3 = Test-ApiCall -TestName "Login with registered user" -Url "$BaseUrl/auth/login" -Body (@{ - identifier = $testUsername - password = "password123" - } | ConvertTo-Json) - - if ($result3 -and $result3.success) { - $testResults.BasicAPI = $true - Write-Host "✅ PASS: Basic API functionality working" -ForegroundColor Green - } - } -} - -Write-Host "`n" + "="*60 -ForegroundColor Cyan -Write-Host "🧪 Test Suite 2: Email Conflict Detection" -ForegroundColor Cyan -Write-Host "="*60 -ForegroundColor Cyan - -# Test email conflict detection -$result4 = Test-ApiCall -TestName "Test email conflict detection" -Url "$BaseUrl/auth/send-email-verification" -Body (@{ - email = $testEmail -} | ConvertTo-Json) -ExpectedStatus 409 - -if ($result4 -and $result4.message -like "*已被注册*") { - $testResults.EmailConflict = $true - Write-Host "✅ PASS: Email conflict detection working" -ForegroundColor Green -} else { - Write-Host "❌ FAIL: Email conflict detection not working" -ForegroundColor Red -} - -Write-Host "`n" + "="*60 -ForegroundColor Cyan -Write-Host "🧪 Test Suite 3: Verification Code Login" -ForegroundColor Cyan -Write-Host "="*60 -ForegroundColor Cyan - -# Test verification code login -if ($result2 -and $result2.success) { - $userEmail = $result2.data.user.email - - # Send login verification code - $result4a = Test-ApiCall -TestName "Send login verification code" -Url "$BaseUrl/auth/send-login-verification-code" -Body (@{ - identifier = $userEmail - } | ConvertTo-Json) - - if ($result4a -and $result4a.data.verification_code) { - $loginCode = $result4a.data.verification_code - - # Login with verification code - $result4b = Test-ApiCall -TestName "Login with verification code" -Url "$BaseUrl/auth/verification-code-login" -Body (@{ - identifier = $userEmail - verification_code = $loginCode - } | ConvertTo-Json) - - if ($result4b -and $result4b.success) { - $testResults.VerificationCodeLogin = $true - Write-Host "✅ PASS: Verification code login working" -ForegroundColor Green - } else { - Write-Host "❌ FAIL: Verification code login failed" -ForegroundColor Red - } - } -} - -if (-not $SkipCooldownTest) { - Write-Host "`n" + "="*60 -ForegroundColor Cyan - Write-Host "🧪 Test Suite 4: Cooldown Clearing & Password Reset" -ForegroundColor Cyan - Write-Host "="*60 -ForegroundColor Cyan - - # Test cooldown clearing with password reset - if ($result2 -and $result2.success) { - $userEmail = $result2.data.user.email - - # Send password reset code - $result5 = Test-ApiCall -TestName "Send password reset code" -Url "$BaseUrl/auth/forgot-password" -Body (@{ - identifier = $userEmail - } | ConvertTo-Json) - - if ($result5 -and $result5.data.verification_code) { - $resetCode = $result5.data.verification_code - - # Reset password - $result6 = Test-ApiCall -TestName "Reset password (should clear cooldown)" -Url "$BaseUrl/auth/reset-password" -Body (@{ - identifier = $userEmail - verification_code = $resetCode - new_password = "newpassword123" - } | ConvertTo-Json) - - if ($result6 -and $result6.success) { - $testResults.PasswordReset = $true - Write-Host "✅ PASS: Password reset working" -ForegroundColor Green - - # Test immediate code sending (should work if cooldown cleared) - Start-Sleep -Seconds 1 - $result7 = Test-ApiCall -TestName "Send reset code immediately (test cooldown clearing)" -Url "$BaseUrl/auth/forgot-password" -Body (@{ - identifier = $userEmail - } | ConvertTo-Json) - - if ($result7 -and $result7.success) { - $testResults.CooldownClearing = $true - Write-Host "✅ PASS: Cooldown clearing working" -ForegroundColor Green - } else { - Write-Host "❌ FAIL: Cooldown not cleared properly" -ForegroundColor Red - } - } else { - Write-Host "❌ FAIL: Password reset failed" -ForegroundColor Red - } - } - } -} - -if (-not $SkipThrottleTest) { - Write-Host "`n" + "="*60 -ForegroundColor Cyan - Write-Host "🧪 Test Suite 5: Throttle Protection" -ForegroundColor Cyan - Write-Host "="*60 -ForegroundColor Cyan - - $successCount = 0 - $throttleCount = 0 - - Write-Host "Testing throttle limits (making 12 registration requests)..." -ForegroundColor Yellow - - for ($i = 1; $i -le 12; $i++) { - $result = Test-ApiCall -TestName "Registration attempt $i" -Url "$BaseUrl/auth/register" -Body (@{ - username = "throttle_test_$i" - password = "password123" - nickname = "Throttle Test $i" - } | ConvertTo-Json) -Silent - - if ($result -and $result.success) { - $successCount++ - Write-Host " Request $i`: ✅ Success" -ForegroundColor Green - } else { - $throttleCount++ - Write-Host " Request $i`: 🚦 Throttled" -ForegroundColor Yellow - } - - Start-Sleep -Milliseconds 100 - } - - Write-Host "`nThrottle Results: $successCount success, $throttleCount throttled" -ForegroundColor Cyan - - if ($successCount -ge 8 -and $throttleCount -ge 1) { - $testResults.ThrottleProtection = $true - Write-Host "✅ PASS: Throttle protection working" -ForegroundColor Green - } else { - Write-Host "❌ FAIL: Throttle protection not working properly" -ForegroundColor Red - } -} - -Write-Host "`n🎯 Test Results Summary" -ForegroundColor Green -Write-Host "=======================" -ForegroundColor Green - -$passCount = 0 -$totalTests = 0 - -foreach ($test in $testResults.GetEnumerator()) { - $totalTests++ - if ($test.Value) { - $passCount++ - Write-Host "✅ $($test.Key): PASS" -ForegroundColor Green - } else { - Write-Host "❌ $($test.Key): FAIL" -ForegroundColor Red - } -} - -Write-Host "`n📊 Overall Result: $passCount/$totalTests tests passed" -ForegroundColor $(if ($passCount -eq $totalTests) { "Green" } else { "Yellow" }) - -if ($passCount -eq $totalTests) { - Write-Host "🎉 All tests passed! API is working correctly." -ForegroundColor Green -} else { - Write-Host "⚠️ Some tests failed. Please check the implementation." -ForegroundColor Yellow -} - -Write-Host "`n💡 Usage Tips:" -ForegroundColor Cyan -Write-Host " • Use -SkipThrottleTest to skip throttle testing" -ForegroundColor White -Write-Host " • Use -SkipCooldownTest to skip cooldown testing" -ForegroundColor White -Write-Host " • Check server logs for detailed error information" -ForegroundColor White -Write-Host " • For production testing: .\test-comprehensive.ps1 -BaseUrl 'https://your-server.com'" -ForegroundColor White - -Write-Host "`n📋 Test Coverage:" -ForegroundColor Cyan -Write-Host " ✓ Application Status & Health Check" -ForegroundColor White -Write-Host " ✓ User Registration & Login Flow" -ForegroundColor White -Write-Host " ✓ Email Verification & Conflict Detection" -ForegroundColor White -Write-Host " ✓ Verification Code Login" -ForegroundColor White -Write-Host " ✓ Password Reset Flow" -ForegroundColor White -Write-Host " ✓ Cooldown Time Clearing" -ForegroundColor White -Write-Host " ✓ Rate Limiting & Throttle Protection" -ForegroundColor White \ No newline at end of file diff --git a/test/core/db/users.test.ts b/test/core/db/users.test.ts deleted file mode 100644 index e69de29..0000000 diff --git a/tsconfig.json b/tsconfig.json index e6523f6..d48d43a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,5 +21,5 @@ "typeRoots": ["./node_modules/@types"] }, "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] + "exclude": ["node_modules", "dist", "client"] } diff --git a/webhook-handler.js.example b/webhook-handler.js.example deleted file mode 100644 index 3a97c12..0000000 --- a/webhook-handler.js.example +++ /dev/null @@ -1,86 +0,0 @@ -const http = require('http'); -const crypto = require('crypto'); -const { exec } = require('child_process'); - -// 配置 - 复制此文件为 webhook-handler.js 并修改配置 -const PORT = 9000; -const SECRET = 'your_webhook_secret_change_this'; // 与 Gitea 中配置的密钥一致 -const DEPLOY_SCRIPT = '/var/www/pixel-game-server/deploy.sh'; // 修改为实际路径 - -// 验证 Gitea 签名 -function verifySignature(payload, signature, secret) { - const hmac = crypto.createHmac('sha256', secret); - hmac.update(payload); - const calculatedSignature = hmac.digest('hex'); - return crypto.timingSafeEqual( - Buffer.from(signature, 'hex'), - Buffer.from(calculatedSignature, 'hex') - ); -} - -// 创建 HTTP 服务器 -const server = http.createServer((req, res) => { - if (req.method !== 'POST') { - res.writeHead(405, { 'Content-Type': 'text/plain' }); - res.end('Method Not Allowed'); - return; - } - - let body = ''; - req.on('data', chunk => { - body += chunk.toString(); - }); - - req.on('end', () => { - try { - // 验证签名 - const signature = req.headers['x-gitea-signature']; - if (!signature || !verifySignature(body, signature.replace('sha256=', ''), SECRET)) { - console.log('签名验证失败'); - res.writeHead(401, { 'Content-Type': 'text/plain' }); - res.end('Unauthorized'); - return; - } - - const payload = JSON.parse(body); - - // 检查是否是推送到 main 分支 - if (payload.ref === 'refs/heads/main') { - console.log('收到 main 分支推送,开始部署...'); - - // 执行部署脚本 - exec(`bash ${DEPLOY_SCRIPT}`, (error, stdout, stderr) => { - if (error) { - console.error('部署失败:', error); - console.error('stderr:', stderr); - } else { - console.log('部署成功:', stdout); - } - }); - - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Deployment triggered'); - } else { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Not main branch, ignored'); - } - } catch (error) { - console.error('处理 webhook 失败:', error); - res.writeHead(500, { 'Content-Type': 'text/plain' }); - res.end('Internal Server Error'); - } - }); -}); - -server.listen(PORT, () => { - console.log(`Webhook 处理器运行在端口 ${PORT}`); -}); - -// 优雅关闭 -process.on('SIGTERM', () => { - console.log('收到 SIGTERM,正在关闭服务器...'); - server.close(() => { - console.log('服务器已关闭'); - process.exit(0); - }); -}); \ No newline at end of file