qinglong
|
10630f3b8f
|
fix: 插件路由注册时从配置文件fallback读取面板路径,解决初始化顺序导致的路径缺失
|
2026-06-14 20:15:27 +08:00 |
|
qinglong
|
6c6c88b22a
|
fix: 插件API路由统一加面板前缀(/SenSu),解决反代后插件页面空白
|
2026-06-14 20:14:22 +08:00 |
|
qinglong
|
d626a0631a
|
fix: RotatingFileHandler强制UTF-8编码避免Windows GBK日志乱码
|
2026-06-14 19:06:32 +08:00 |
|
qinglong
|
2c5cd57ad4
|
fix: venv改为懒加载,兼容嵌入式CPython无venv模块
|
2026-06-14 19:02:27 +08:00 |
|
qinglong
|
f40b87ea52
|
fix: 仪表盘版本号从version.json读取,修复硬编码v0.6.0
|
2026-06-14 16:24:41 +08:00 |
|
qinglong
|
3f5b01f817
|
refactor: 版本号从version.json读取 配置模板删version字段
|
2026-06-14 16:03:04 +08:00 |
|
qinglong
|
b708c210c7
|
fix: 静态HTML添加no-cache头 + app.js→app_v2.js
|
2026-06-14 11:55:06 +08:00 |
|
qinglong
|
ae553b564d
|
fix: 静态文件no-cache + app.js重命名防缓存
|
2026-06-14 11:54:18 +08:00 |
|
qinglong
|
f532a63a49
|
fix: 插件页面强制no-cache + app.js v0712
|
2026-06-14 11:45:07 +08:00 |
|
qinglong
|
cb5f900c39
|
feat: 更新页面实时日志 — SSE轮询 + logs/updates_logs 文件记录
|
2026-06-14 10:45:08 +08:00 |
|
qinglong
|
b3a6f73db4
|
fix: 更新后同步版本号到base_config.yaml
|
2026-06-14 10:42:01 +08:00 |
|
qinglong
|
27115942ea
|
fix: InitService自动合并模板新增字段(解决旧config缺branch问题)
|
2026-06-14 10:39:03 +08:00 |
|
qinglong
|
fb8bf393f2
|
fix: UpdateService默认分支 main→dev (version.json在dev)
|
2026-06-14 10:37:39 +08:00 |
|
qinglong
|
c65a9916c2
|
fix: Windows负载 — psutil.getloadavg() + 全0显示N/A
|
2026-06-14 10:32:51 +08:00 |
|
qinglong
|
7fe9e4f6cd
|
fix: 插件加载失败计入统计 — LOAD_FAILURES + 合并fail_details
|
2026-06-14 10:26:36 +08:00 |
|
qinglong
|
00c97e4af2
|
fix: PluginService自动从.example模板创建config.yaml (Windows兼容)
根因: Sentinel的config.yaml被gitignore, 首次运行时
load_plugin()要求config.yaml存在才能继续, 但Sentinel的
自动复制逻辑在initialize()中, 太晚了。
修复: PluginService.load_plugin()检测缺失时自动复制模板
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-14 10:24:08 +08:00 |
|
qinglong
|
cb6beca067
|
Revert "fix: Windows分区设备名 — 用盘符(C:)替代设备路径"
This reverts commit 7cdae4d954.
|
2026-06-14 10:02:09 +08:00 |
|
qinglong
|
7cdae4d954
|
fix: Windows分区设备名 — 用盘符(C:)替代设备路径
|
2026-06-14 09:58:50 +08:00 |
|
qinglong
|
528410d3e9
|
feat: 磁盘分区列 — 多分区/进度条/overflow/过滤虚拟FS
SystemInfoCollector:
- _get_partitions(): psutil disk_partitions + 过滤虚拟FS
- 跳过 tmpfs/devtmpfs/proc/sysfs/cgroup等22种
- 无psutil时 fallback到根分区
前端4列: 160px 1fr 0.8fr 1fr
- col-disk: 分区名/挂载点/进度条/百分比
- max-height:200px overflow:auto
- 跨平台兼容
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-14 09:31:52 +08:00 |
|
qinglong
|
b1b7cd0563
|
feat: 横版col-extra — 负载/SWAP/磁盘/温度/流量/进程 6项指标
SystemInfoCollector 新增:
- swap: SWAP用量 (psutil + /proc/meminfo fallback)
- disk: 磁盘用量
- temperature: CPU温度 (psutil + /sys/class/thermal fallback)
Sentinel col-extra 显示:
负载 | SWAP | 磁盘 | 温度 | 累计流量 | 进程RSS
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-14 09:19:37 +08:00 |
|
qinglong
|
9818d1c965
|
fix: UpdateService启动时立即设置current_version
|
2026-06-14 09:08:41 +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
|
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
|
279ddfbdc9
|
fix: SystemMonitor.refresh() 移除不存在的 _refresh_stats 调用
|
2026-06-13 20:54:35 +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
|
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
|
d0206121b1
|
fix: 统计卡片'安装失败'→'启动失败' + 合并 error_count 计数
|
2026-06-13 18:44:20 +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
|
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
|
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
|
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
|
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
|
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
|
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
|
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 |
|
qinglong
|
fcac02d920
|
security: P2 生产深度加固 — 路径/鉴权/脱敏/校验/持久化/过期
4.3 文件管理器路径收紧:
- 默认移除 Path('/') 全文件系统访问
- 仅允许项目目录 + data/ + 环境变量 SENSU_FILE_ROOTS 指定路径
3.4 插件路由鉴权修复:
- _check_plugin_auth 增加 panel_token 用户身份验证
- 先验证用户登录, 再检查插件权限
4.2 错误脱敏:
- security middleware 捕获异常 → 通用 'Internal server error'
- 堆栈详情仅写入日志, 不暴露给客户端
4.4 命令参数校验:
- POST /api/command 拒绝 shell 元字符 (;&|`$(){}!#~<>)
- 防止命令注入
4.5 Session 持久化:
- 登录/退出时保存到 SenSuDB.config_kv
- 框架重启后自动恢复已持久化会话
4.6 Token 过期: 24h → 2h
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-13 13:50:51 +08:00 |
|
qinglong
|
2f9063d6d4
|
fix: 登录频率限制 bug — lock_until=0 导致计数被清零
根因: 初始 lock_until=0 时 now >= 0 + 60 恒为真, 每次请求都清除计数
修复: lock_until 改用 None 表示未锁定, 仅非 None 时做过期判断
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-13 13:46:29 +08:00 |
|
qinglong
|
f7b4908322
|
security: 公网生产环境加固 — P0/P1 全部修复
API 认证 (16 个未保护端点 → 全部加 panel_auth):
- 文件管理器: 11 端点 (list/mkdir/delete/upload/download/read/write/...)
- 项目管理: 6 端点 (list/run/stop/logs/stdin/page), 修复硬编码路径前缀
- 代理管理: 3 端点 (list/add/remove)
- 系统状态: 2 HTTP + 1 WS (token 校验)
- 插件页面: 3 端点 (page/sse/event)
- 内部路由: 3 端点 (plugins/commands/data)
认证系统加固:
- 密码哈希: 固定盐 → 每用户独立 secrets.token_hex(16) 随机盐
- 默认密码警告: 启动时检测并打印 critical 级别日志
- 登录频率限制: 5 次失败 / IP → 锁定 60 秒, 返回 429
基础设施:
- 安全响应头: X-Content-Type-Options/X-Frame-Options/X-XSS-Protection/Referrer-Policy
- WebSocket 鉴权: query string token 校验
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-13 13:37:14 +08:00 |
|
qinglong
|
2dc3c16787
|
fix: 系统监控改用 asyncio task 驱动,抗 Android 后台挂起
- SystemMonitor/PluginStatusPanel: 移除 set_interval, 改用外部 refresh()
- TuiService._refresh_monitors(): asyncio.sleep(2) 循环刷新
- asyncio.sleep 在 Android 恢复前台后能正常续跑
- shutdown 时 cancel refresh task
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-13 12:50:06 +08:00 |
|
qinglong
|
10d1a1fcb1
|
fix: 标题栏 背景改 + 行高加到2 增强可见性
|
2026-06-13 12:18:50 +08:00 |
|
qinglong
|
feca81842b
|
fix: 回到 grid 布局 + 顶部留空行 — 5行: 空/标题/状态栏/主区/输入
grid-rows: 1 1 auto 1fr 3
- Row 1: 空白行
- Row 2: 标题栏 (Static, bold)
- Row 3: 状态栏 (auto 高度)
- Row 4: 主显示区 (1fr 填满剩余)
- Row 5: 输入栏 (固定3行)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-13 12:17:30 +08:00 |
|
qinglong
|
ae8586bc4a
|
fix: 用 Static 标题栏替代 Textual Header,确保始终显示
- 自定义 #title-bar (dock top, height 1, bold)
- 移除不可靠的 Header widget
- _setup_title 更新 title_bar 内容
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-13 12:00:36 +08:00 |
|
qinglong
|
18f9fcfcd3
|
fix: Header dock top 防止被 monitor-area 遮挡
|
2026-06-13 11:56:58 +08:00 |
|