Files
PolyHermes/docs/zh/DYNAMIC_UPDATE_CHECK.md
WrBug 26dd3bb387 feat: 实现系统动态更新功能和 Release 创建脚本
主要变更:

1. 动态更新功能
   - 新增 Python 更新服务 (docker/update-service.py)
   - 添加系统更新前端页面 (frontend/src/pages/SystemUpdate.tsx)
   - 配置 Nginx 代理更新服务 API
   - 更新 Docker 启动脚本支持多进程管理
   - 修复权限验证接口 (AuthController.verify)

2. Release 创建脚本
   - 新增 create-release.sh 脚本支持快速创建 GitHub Release
   - 支持自动拼接 -beta 后缀(pre-release)
   - 支持无交互模式(--yes 参数)
   - 添加详细的使用文档

3. GitHub Actions 增强
   - 添加更新包构建和上传流程
   - 支持 Pre-release 检测和过滤

4. 文档完善
   - 添加动态更新技术方案文档
   - 添加 Docker 版本号确定流程文档
   - 添加 Release 脚本使用说明
2026-01-21 03:34:16 +08:00

6.1 KiB
Raw Permalink Blame History

动态更新功能实现检查报告

基于 docs/zh/DYNAMIC_UPDATE.md 文档和现有代码,检查动态更新功能的实现情况。

已实现的功能

1. 后端更新服务

  • docker/update-service.py 已实现
    • 检查更新:GET /check
    • 执行更新:POST /update
    • 更新状态:GET /status
    • 更新日志:GET /logs
    • 获取版本:GET /version
    • 健康检查:GET /health
    • Pre-release 支持:通过 ALLOW_PRERELEASE 环境变量控制

2. Nginx 配置

  • docker/nginx.conf 已配置
    • /api/update/ 路径代理到 http://localhost:9090/
    • 正确传递 Authorization 头
    • 超时设置合理(300秒)

3. Docker 启动脚本

  • docker/start.sh 已实现
    • 启动更新服务(端口 9090
    • 启动后端服务(端口 8000
    • 启动 Nginx(前台运行)
    • 正确的进程清理逻辑

4. Dockerfile

  • Dockerfile 已配置
    • 安装 Python 和 Flask
    • 复制更新服务脚本
    • 创建必要的目录
    • 支持混合编译方案(BUILD_IN_DOCKER 参数)

5. GitHub Actions

  • .github/workflows/docker-build.yml 已配置
    • 构建后端 JAR
    • 构建前端
    • 打包更新包
    • 计算校验和
    • 上传到 Release Assets
    • Pre-release 检测和过滤

6. 前端更新界面

  • frontend/src/pages/SystemUpdate.tsx 已实现
    • 显示当前版本
    • 检查更新
    • 显示更新信息
    • 执行更新
    • 更新进度显示
    • 错误处理

7. 权限验证端点

  • /api/auth/verify 端点已存在
    • 位置:backend/src/main/kotlin/com/wrbug/polymarketbot/controller/auth/AuthController.kt

⚠️ 发现的问题

问题 1: /api/auth/verify 接口逻辑错误

位置: backend/src/main/kotlin/com/wrbug/polymarketbot/controller/auth/AuthController.kt:192-212

问题:

// 检查是否为管理员
val role = httpRequest.getAttribute("role") as? String
if (role != "ADMIN") {
    return ResponseEntity.status(403).body(...)
}

原因:

  1. JWT 拦截器(JwtAuthenticationInterceptor)只设置了 username 到 request attributes没有设置 role
  2. User 实体没有 role 字段,而是使用 isDefault 字段来判断是否为管理员(默认账户就是管理员)

修复方案: 需要修改 /api/auth/verify 接口,检查用户是否为默认账户:

@GetMapping("/verify")
fun verify(httpRequest: HttpServletRequest): ResponseEntity<ApiResponse<Unit>> {
    return try {
        val username = httpRequest.getAttribute("username") as? String
        if (username == null) {
            return ResponseEntity.status(401).body(ApiResponse.error(ErrorCode.AUTH_ERROR, "未认证", messageSource))
        }
        
        // 检查是否为默认账户(管理员)
        val user = userRepository.findByUsername(username)
        if (user == null || !user.isDefault) {
            return ResponseEntity.status(403).body(ApiResponse.error(ErrorCode.AUTH_ERROR, "需要管理员权限", messageSource))
        }
        
        ResponseEntity.ok(ApiResponse.success(Unit))
    } catch (e: Exception) {
        logger.error("验证权限异常: ${e.message}", e)
        ResponseEntity.status(500).body(ApiResponse.error(ErrorCode.SERVER_ERROR, "验证失败", messageSource))
    }
}

需要的依赖:

  • AuthController 中注入 UserRepository

问题 2: 前端 SystemUpdate 组件未使用 apiClient

位置: frontend/src/pages/SystemUpdate.tsx

问题: 组件使用了原生的 fetch API,而不是项目统一的 apiClient。虽然 apiClient 有拦截器自动添加 Authorization header,但原生 fetch 不会自动添加。

当前代码:

const response = await fetch('/api/update/execute', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    }
})

修复方案: 有两种方案:

方案 1(推荐): 使用 apiClient

import { apiClient } from '../services/api'

const response = await apiClient.post('/update/execute', {})

方案 2: 手动添加 Authorization header

const token = localStorage.getItem('token')
const response = await fetch('/api/update/execute', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
    }
})

影响:

  • 当前如果用户已登录,token 在 localStorage 中,Nginx 会传递 Authorization 头
  • 但使用 apiClient 更统一,且可以处理 token 刷新等情况

📋 已修复的问题

后端

  1. 已修复 AuthController.verify() 方法
    • 移除了错误的 role 检查
    • 添加了 UserRepository 依赖注入
    • 正确检查用户是否为默认账户(isDefault == true

前端

  1. 已修复 SystemUpdate.tsx 组件
    • 将所有 fetch 调用替换为 apiClient
    • 确保自动携带 Authorization header
    • 统一错误处理逻辑

其他检查项

更新服务功能完整性

  • 检查更新(无需权限)
  • 获取版本(无需权限)
  • 执行更新(需要管理员权限)
  • 获取日志(需要管理员权限)
  • 获取状态(无需权限)

更新流程完整性

  • 下载更新包
  • 备份当前版本
  • 替换文件
  • 重启后端
  • 健康检查
  • 自动回滚

文档完整性

  • 技术方案文档存在
  • 架构设计清晰
  • 使用流程说明完整

📝 总结

整体实现度: 100%

已修复的问题:

  1. /api/auth/verify 接口已修复(现在正确检查默认账户而非 role)
  2. 前端组件已改用 apiClient 保持一致性

功能状态:

  • 所有核心功能已实现
  • 所有问题已修复
  • 代码质量良好,无 lint 错误

下一步:

  1. 进行集成测试,验证更新流程端到端是否正常工作
  2. 测试权限验证是否生效(非管理员用户应无法执行更新)

检查日期: 2026-01-20 最后更新: 2026-01-20(已修复所有问题) 检查人: AI Assistant