Commit Graph

114 Commits

Author SHA1 Message Date
qinglong 63cd38cf22 fix: 手动更新按钮始终显示 — 有更新时变绿色'立即更新' 2026-06-13 21:39:30 +08:00
qinglong 70695b171e fix: 版本号显示 — 始终设 current_version + 顶栏按钮显示版本 2026-06-13 21:34:21 +08:00
qinglong 94d56d8210 fix: 版本检查 — 后端设置 checked 字段 + 前端 info 合并显示
- UpdateService.status 增加 checked/current_version/latest_version
- _check_version 成功后设置 checked=True
- 设置页 update-notes 合并版本信息和时间戳 (替代 innerHTML 覆盖)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 21:29:35 +08:00
qinglong 68717daefb feat: Sentinel 支持自定义 API 路径前缀 (base_path)
- 节点编辑对话框新增「API 路径前缀」字段 (默认 /SenSu)
- 后端保存/读取 base_path
- API 响应包含 base_path 供前端回显

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 21:19:25 +08:00
qinglong 67d0f00525 fix: 版本更新 — 自动检查 + 手动备份 + 创建备份按钮
1. 设置页加载时自动触发版本检查
2. POST /api/updates/backup — 手动创建备份
3. 备份管理区新增「+ 创建备份」按钮
4. 顶栏版本按钮: checkTopUpdate 每10min轮询

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 21:08:54 +08:00
qinglong 95a2f375e8 security: Sentinel 配置文件模板化 — config.yaml 不入库
- config.yaml → .gitignore (含 API Key 不入库)
- config.yaml.example 模板 (空节点列表)
- 首次启动自动从模板复制
- 所有插件 config.yaml 统一保护

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 21:04:52 +08:00
AskaEth 1301aeb9b7 fix: 启动脚本绑定 venv Python + 缺依赖自动安装
- start.bat: 改用 .venv\Scripts\python.exe,缺依赖时自动 pip install
- start.sh: 优先 .venv/bin/python3,fallback 到系统 python3/python
- 两个脚本均不再依赖 uv,使用标准 python -m venv + pip

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-13 21:02:01 +08:00
qinglong ead7d2056b chore: 移除临时开发文档 (进度/踩坑/备份/结构) — docs/ gitignore + 白名单 2026-06-13 20:59:05 +08:00
qinglong ff693465f6 docs: README + API_Auth + Security_Plan + Plugin_Guide 更新至 v0.7.0
- README: 新功能列表、start.sh、架构图
- API_Auth_Flow: 新增 API Key 认证章节
- Security_Hardening_Plan: 标记全部完成
- Plugin_Dev_Guide: 新增插件导入安装章节

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 20:56:50 +08:00
qinglong 3e106001ed feat: 无头启动脚本 start.sh / start.bat (依赖检测 + 配置模板复制) 2026-06-13 20:55:28 +08:00
qinglong 279ddfbdc9 fix: SystemMonitor.refresh() 移除不存在的 _refresh_stats 调用 2026-06-13 20:54:35 +08:00
qinglong eba035db64 chore: 移除自动生成的配置文件 (多用户协作冲突) 2026-06-13 20:53:26 +08:00
qinglong 3724021d81 style: Sentinel MEM 详情右对齐到标签旁 (12.8/14.8 GB) 2026-06-13 20:50:13 +08:00
qinglong faf695e361 style: 状态emoji(🔄) → 纯文本符号(✓✗↻) 2026-06-13 20:49:17 +08:00
qinglong 30bc4cc945 chore: 删除合并残留 main.py.clean/orig + gitignore *.orig *.clean 2026-06-13 20:47:48 +08:00
qinglong 899bef7781 feat: 设备卡片显示系统名+版本 + 项目根 version.json
- SystemInfoCollector.platform 新增 release 字段 (内核版本)
- Sentinel 卡片每台设备显示: Linux 6.12.23 | aarch64
- 数据刷新时同步更新系统信息行
- 项目根 version.json: 本地版本清单

当前版本检测:
  UpdateService 每6h从 {repo}/raw/branch/{branch}/version.json 拉取
  对比 base_config.yaml 的 framework.version
  远程 > 本地 → 顶栏绿色按钮 + 设置页更新提示

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 20:47:22 +08:00
qinglong c8f2cb7b98 fix: Sentinel 编辑节点时 api_key 留空 → 保留旧值 2026-06-13 20:44:44 +08:00
qinglong cc50ecb813 fix: Windows兼容 + Textual 8.x + MD3 SVG图标替代emoji
1. Windows: reuse_port 仅非win32平台启用
2. Textual 8.2.7: refresh() 加 **kwargs 兼容 repaint 参数
3. WebUI: 设置页/插件页 emoji → SVG (fill:currentColor 日夜间适配)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 20:42:22 +08:00
qinglong 9a9a2975de feat: WebUI 版本检测 — 顶栏按钮 + 设置页备份/回滚/更新管理
顶栏:
- 版本号按钮, 有更新时变绿色并显示新版本号
- 每10分钟自动检查

设置页新增「版本与更新」区域:
- 当前版本 + 更新状态徽章
- 检查更新 / 立即更新 按钮
- 备份列表 + 手动回滚

API:
- GET /api/updates/backups — 备份列表
- POST /api/updates/rollback — 执行回滚

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 20:39:28 +08:00
qinglong c20417ff93 feat: 更新服务 — ZIP下载/备份/回滚/重启
UpdateService:
- 分支感知: 从 base_config 读取 branch, 拼接 archive/{branch}.zip
- 定时检查: 每6h 拉取 version.json 比对版本
- 更新前自动打包备份 (zip, 保留最新5个)
- 保护用户配置: base_config.yaml / plugins/*/config.yaml / data/
- 子进程 pip install 依赖

API:
- GET /api/updates — 更新状态
- POST /api/updates/check — 手动检查
- POST /api/updates/apply — 执行更新

回滚:
- python main.py --rollback  — 恢复到最新备份
- 无备份时提示

重启:
- .restart_flag 信号文件 → 优雅退出 → systemd 拉起

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 20:32:42 +08:00
qinglong 6e0ed23012 fix: 页面 HTML 加载加 ?t= 缓存破坏 + app.js 版本号 0704→0705 2026-06-13 18:49:49 +08:00
qinglong 9c1a1d40e4 style: 导入卡片间距 gap 12→16px + align stretch 等高 2026-06-13 18:46:57 +08:00
qinglong d0206121b1 fix: 统计卡片'安装失败'→'启动失败' + 合并 error_count 计数 2026-06-13 18:44:20 +08:00
qinglong e16250c7e7 style: 插件导入卡片 CSS — 等高 / 文件按钮 / 纵向布局 2026-06-13 18:43:30 +08:00
qinglong b2021a45ce feat: 插件管理 — 导入安装 + 统计面板
新增 API:
- GET /api/plugins/stats — 统计 (总计/已启用/已停用/安装失败)
- POST /api/plugins/import — ZIP上传 或 Git clone 安装
  - 自动 pip install -r requirements.txt (子进程隔离)
  - 自动加载插件 (isolated 模式, 崩溃不影响框架)
  - 安装失败记录到 _IMPORT_FAILS

前端:
- 横版统计卡片 (总数/启用/停用/失败)
- ZIP 上传按钮 + Git URL 输入
- 安装状态实时反馈

安全:
- 所有端点 panel_auth 保护
- 子进程安装 (pip/git), 超时120s
- 仅接受 .zip 文件
- 目录冲突检测

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:39:38 +08:00
qinglong a2bd6486a0 fix: 动画改用 setInterval (兼容动态 script 加载) + try-catch 保护 2026-06-13 18:29:11 +08:00
qinglong c4b44e0fd2 fix: 仪表盘动画改为模块方法 _animateNumber (避免全局作用域问题) 2026-06-13 18:26:38 +08:00
qinglong 81ebbc3e45 feat: WebUI 首页仪表盘 — CPU/MEM/进程内存 数字跳动动画
- animateNumber(): 900ms ease-out 缓动, 存储前值于 data-val
- CPU%、MEM%、进程内存 三个指标使用跳动动画
- 与 Sentinel 卡片动画风格统一

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:21:05 +08:00
qinglong 3ca001b938 fix: 进度条平滑过渡 — force reflow 技巧确保 CSS transition 生效
- 临时关 transition → 设旧值 → offsetWidth reflow → 开 transition → 设新值
- DOM 复用: 首次 innerHTML 创建, 后续只改属性
- 进度条从旧值滑到新值, 不再闪现

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:19:07 +08:00
qinglong 417213096f fix: Sentinel 清除占位卡片 + 动画延长至 1s 2026-06-13 18:17:26 +08:00
qinglong f3a6e5fbcd feat: Sentinel 数字跳动动画 + 进度条平滑过渡
- 数字 count-up/down: requestAnimationFrame + ease-out cubic, 350ms
- 中间值过渡: 15%→22% 会显示 15.2,16.1,17.5...22.0
- 进度条: CSS transition 自动处理宽度变化
- 卡片 DOM 复用: 更新值而非重建 innerHTML

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:12:37 +08:00
qinglong 1d0f227267 fix: API Key 删除/创建去掉 CSRF — panel_token HttpOnly 前端无法读取
SameSite=Lax cookie 已防跨站 POST/DELETE, 无需额外 CSRF header
前端 JS 无法读取 HttpOnly cookie, 无法设置 X-CSRF-Token

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:07:47 +08:00
qinglong 51c1ee84f0 feat: Sentinel 卡片数据刷新动画
- 卡片更新时背景闪烁 (card-flash keyframe)
- 进度条平滑过渡 (cubic-bezier .6s)
- 数值涨跌颜色: 绿涨↑ 红跌↓ 不变灰色
- 渐变进度条背景
- 存储前值用于趋势对比

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:06:06 +08:00
qinglong c416b04798 fix: Sentinel 改用前端轮询替代 SSE (解决 EventSource 认证问题)
SSE 跨 panel_auth 认证层不可靠 → 改用 setInterval 每 2s fetch /sentinel/api/nodes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 18:00:34 +08:00
qinglong a21e092207 fix: Sentinel SSE URL — /SenSu/plugin/... → /plugin/... (匹配实际路由) 2026-06-13 17:56:57 +08:00
qinglong b53410bc77 fix: Sentinel SSE 每次轮询都推送 (实时性) + isolation 默认 false + 文档
Sentinel:
- poll_interval 3s→2s, 每次轮询都推 SSE (不再等状态变化)
- 解决稳定状态下数据更新不实时问题

插件系统:
- 默认 isolation: false (避免插件 WebUI 不显示)
- example_plugin 显式设置 isolation: false
- 插件开发指南: settings 示例增加 isolation 说明

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 17:54:39 +08:00
qinglong af16549524 chore: 清理误提交的 base_config.yaml.bak 2026-06-13 17:46:33 +08:00
qinglong 5e06c17b52 fix: WebSocket 鉴权 — Cookie 优先 (支持 HttpOnly)
根因: panel_token 是 HttpOnly cookie, JS getCookie() 读不到
→ 前端 WS ?token= 参数为空 → 认证失败 → 仪表盘无数据

修复:
- _ws_auth_wrapper: Cookie 优先 → query token 备用 → API Key
- 浏览器同源 WS 自动发送 Cookie, 无需 ?token=
- dashboard.js / logs.js 移除多余的 getCookie+?token=

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 17:45:58 +08:00
qinglong 557135c376 security: 配置文件模板化 — base_config.yaml 不再入库
- base_config.yaml → .gitignore (含真实密码不入库)
- 新增 base_config.yaml.example 模板 (password: CHANGE_ME)
- InitService: 检测缺失时自动从模板复制
- 首次启动自动创建配置文件

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 15:20:14 +08:00
qinglong a2361cf452 fix: Sentinel WebUI — 合并为单页面(仪表盘+节点管理Tab)
插件 Web 页面 key 必须匹配 plugin_name (/plugin/sentinel)
改为单页面 Tab 切换: 仪表盘 + 节点管理

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 15:17:17 +08:00
qinglong 634496d975 security: Sentinel 路由鉴权 + API Key CSRF + SSRF 防护
修复:
- Sentinel 路由 require_auth=False → True (严重: 未认证可访问)
- API Key 创建/删除加 csrf_protect=True
- SSRF 防护: 测试连接仅允许 http/https scheme
- 插件网络鉴权: 已加载插件自动放行 (不再要求 plugin.network.access)
- Sentinel 权限列表补充 plugin.network.access

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 15:13:56 +08:00
qinglong 5e74b0aad7 feat: 🛡️ Sentinel 集群监控插件 + API Key 系统 + 框架设置页
== API Key 系统 ==
- services/web_panel/routes/apikeys.py: CRUD + 权限模板 + 过期控制
- panel_auth + _check_plugin_auth 双重验证 (Session → API Key)
- 模板: readonly(只读) / monitor(监控) / full(管理)
- 持久化到 SenSuDB + 过期自动清理

== WebUI 框架设置页 ==
- static/web_panel/pages/settings.html: API Key 管理界面
- 创建对话框 (名称/权限/TTL), 列表表格, 一键删除

== 热重载修复 ==
- PluginService._reload_plugin: 路由器冻结时跳过 (避免破坏已注册路由)

== 🛡️ Sentinel 插件 ==
- 多节点 SenSu 集群性能监控
- 后台 urllib+run_in_executor 轮询 (避免事件循环死锁)
- SSE 实时推送仪表盘
- 节点管理页 (增删改+连接测试+备注)
- 路径: /sentinel/api/nodes

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 15:05:38 +08:00
qinglong 66ad51002c feat: WebUI 框架设置页面 + API Key 管理 UI
新增:
- static/web_panel/pages/settings.html — API Key CRUD 界面
- 侧边栏 '框架设置' 导航项 (齿轮图标)
- BUILTIN_PAGES 增加 'settings'
- UI 功能: 创建对话框(名称/权限/过期), 列表表格, 一键删除

权限模板:
- readonly — framework.status.read + plugin.info.read
- monitor — + framework.event.subscribe
- full — admin (全部)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 14:28:59 +08:00
qinglong b92b1cc4fc security: API Key 权限范围 + 过期时间 + 用量追踪
增强:
- 权限模板: readonly / monitor / full
- 每 key 独立权限列表, 注入 user['perms']
- 可选过期时间 (ttl 参数)
- 过期 key 自动清理 (加载时 + 验证时)
- request_count 用量追踪
- 标记 is_api_key = True

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 14:27:07 +08:00
qinglong 9f6eb29820 feat: API Key 系统 — CRUD + panel_auth 集成 + 持久化
新增:
- services/web_panel/routes/apikeys.py — 创建/列表/删除 API Key
- panel_auth() 双重验证: Session Store → API Key fallback
- _check_plugin_auth() 支持 API Key
- API Key 持久化到 SenSuDB (config_kv 表)
- 格式: sk- + 48 hex chars
- 脱敏显示 (前8后4)
- 删除后立即失效 (401)

WebPanelManager 注册 apikeys 路由

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 14:25:55 +08:00
qinglong e88d472c63 docs: API 认证与数据访问全流程文档 2026-06-13 14:14:34 +08:00
qinglong 2da52e80d0 security: P3+ — 面板密码哈希 + 上传类型白名单 + CSRF Token
面板密码安全:
- 支持哈希存储 (password_hash/password_salt)
- 登录使用 secrets.compare_digest 时序安全比较
- 回退明文兼容旧配置
- 默认密码 admin 时打印 CRITICAL 警告

文件上传安全:
- 拒绝危险扩展名: .exe/.dll/.so/.sh/.bat/.ps1 等
- 拒绝敏感文件名: .htaccess/Makefile/Dockerfile 等
- 上传时检查并返回 403

CSRF 防护:
- panel_auth(csrf_protect=True) 参数
- 写操作需 X-CSRF-Token header 匹配 session token
- 保护范围: 文件删除/写入/创建/上传/重命名 + 项目启停 + 代理管理

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 14:07:38 +08:00
qinglong d835b66ca9 chore: gitignore data/ 目录 (运行时数据,不应入库) 2026-06-13 13:57:12 +08:00
qinglong ff02b2e16d security: P3 — 插件隔离默认开启 + SenSuDB 注册 + 审计日志
- plugins.isolation 默认 true (生产环境进程隔离)
- main.py 注册 SenSuDB 服务
- WebPanelManager 注入 sensu_db 到 app context
- 文件删除/写入操作写入审计日志 (audit_log 表)
- 修复 Session 持久化所需的数据库依赖

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 13:56:58 +08:00
qinglong c1d2767f52 fix: web 命令端点 execute_command → process_command (方法名错误)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-13 13:54:37 +08:00