Commit Graph

49 Commits

  • feat(admin): 实例「管理」菜单改为悬浮图层展开
    绝对定位悬浮层(从按钮下方浮出),不再撑高卡片/顶走下方内容;展开时卡片 overflow:visible
    + z-index:5(盖住下方/同列卡片,仍低于弹窗);加点击外部 / 点击菜单项自动关闭。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • chore(docker): 00-woc-identity 也用显式 chmod 755(补齐 #17)
    PR #17 把脚本权限改为显式 755/644 以摆脱构建机 umask 影响,但它之后才加的
    00-woc-identity 钩子仍是 chmod +x,是唯一漏网。该钩子由 root 运行(711 也能跑、
    非功能性问题),此处仅为与其余几行统一、彻底做到与 umask 无关。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • docs(readme): 备注 NAS/飞牛首次建实例镜像拉取超时的解法
    NAS 自带的 Docker Hub 加速通常只覆盖界面手动拉取,不覆盖面板经 docker.sock 触发的拉取,
    导致首次新建实例直连 registry-1.docker.io 超时。README 快速开始加提示:先手动拉一次
    gloridust/wechat-on-cloud:latest(本地有了面板就复用不再联网),或配守护进程镜像加速 /
    换 WOC_IMAGE_PREFIX 到国内源。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • docs(readme): 方式B 改为仅凭 docker-compose.yml 部署,无需 clone 仓库
    compose 用 image: 拉官方镜像、数据落到旁边自动建的 ./data-panel,不依赖仓库其它文件
    (已在空目录验证 docker compose config 通过)。方式B 改为:命令行 curl 单文件 / 飞牛(fnOS)·
    群晖等 NAS 直接粘贴 docker-compose.yml 到 Compose 一键部署界面;并说明改密码/端口/镜像源
    可用 .env 或 NAS 环境变量,无需 clone。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • feat(ci/telegram): 发布通知自动置顶 + 取消上一个 release 的置顶
    tg-notify.mjs:release/手动触发发完消息后,用 getChat 读群当前置顶(=上一个 release),
    pinChatMessage 置顶新消息(静音,避免二次提醒)、unpinChatMessage 取消旧的——无需持久化存储。
    issue 通知不置顶;置顶失败(机器人非管理员/无置顶权限)仅跳过、不影响通知本身。
    文档补充:需把机器人设为群管理员并开启「置顶消息」权限。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • chore: 默认镜像源切到 Docker Hub,GHCR 作为备用
    Docker Hub 国内/国际通用、免登录拉公开镜像,飞牛OS(fnOS) 等 NAS 还内置拉取加速,
    通常比 GHCR 更快更稳。docker-compose.yml 两处 :- 兜底默认与 .env.example 默认值
    由 ghcr.io/gloridust 改为 docker.io/gloridust;GHCR / 南大反代 / 阿里云等列为备用源。
    README 快速开始措辞同步更新。镜像仍同时发布到两个 registry,未改 CI。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • docs(readme): 增加 Docker Hub 镜像源切换说明(飞牛OS 等 NAS 有加速)
    官方镜像已同步发布到 Docker Hub(公开、多架构)。README 快速开始补充:
    ghcr.io 拉不动时在 .env 设 WOC_IMAGE_PREFIX=docker.io/gloridust 切到 Docker Hub;
    飞牛 OS(fnOS) 等 NAS 内置 Docker Hub 拉取加速,通常更快更稳。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • fix(panel): 修复 VolumeManager 漏闭合的 .vol-sec 标签致构建失败
    a42006e 把第 1259 行的 </div> 误回退成 </>,与 <div className="vol-sec"> 不匹配,
    导致 vite/esbuild 构建报 "Unexpected closing fragment tag" → main 上 panel 镜像构建失败
    (v1.1.10 标签镜像本身是好的,从 1c34777 构建)。改回 </div>。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • feat(panel): 管理员数据卷管理(整卷备份/恢复 + 文件浏览器)
    管理页 → 实例「管理」→ 数据卷(仅 admin)。解决大量用户"把 PC 微信数据迁移上 docker"的诉求。
    
    - 整卷备份:流式打包 /config 为 .tar.gz 下载(大文件不入内存);恢复:上传覆盖回 /config。
      machine-id 存在卷内随包迁移 → 跨 woc 实例恢复可保留聊天记录。
    - 文件浏览器:浏览/上传/上传并解压(.tar/.tar.gz)/下载/改名/移动/删除;PC 数据打包上传解压后重启实例。
    - 全程在运行中的实例上操作(exec + docker cp,运行容器才可 exec);恢复为全量覆盖,强提示并建议重启。
    - 安全:仅 admin;路径严格限制在 /config、禁止 .. 穿越;上传落地为 abc 属主。
    - docker.ts 抽出 extractSingleFileFromTar 复用(PAX 头跳过),新增 list/mkdir/move/delete/upload/
      extract/download/backup(stream)/restore;index.ts 加 9 个 /volume 管理路由;前端 VolumeManager 弹窗
      + 线性 SVG 图标(替代渲染不一致的 emoji);新增 doc/数据卷管理.md。
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • ci(telegram): render release/issue notes as Telegram HTML (not raw markdown)
    GitHub-Flavored Markdown ≠ Telegram MarkdownV2, so the old plain-text send
    showed literal ## ** | etc. New .github/scripts/tg-notify.mjs converts GFM
    → Telegram-safe HTML (<b>/<i>/<code>/<pre>/<a>; headers→bold, tables→· rows,
    lists→•, quotes→▎), escapes <>&, and falls back to plain text if Telegram
    rejects the HTML. Adds workflow_dispatch to telegram-notify so you can send
    the latest release rendered for testing without cutting a new release.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • feat(admin/ci): 管理页折叠菜单 + 空状态/主页优化 + Telegram 命令机器人
    管理页 UI/UX
    - 实例卡片操作改为「管理」分类折叠菜单(默认收起,点开按 运维/设置/危险 分组的
      文字操作),替代之前难辨认的图标排;删除单独成组、红色,降低误点
    - 修复展开一张卡片时同行其它卡片被 grid 拉等高(inst-grid align-items:start)
    - 管理页空状态(无实例/无子账号)改为图标+标题+说明+引导按钮
    - 主页实例卡片加副行(状态·微信版本)、悬停上浮高亮
    
    Telegram 命令机器人(轮询版,纯 GitHub Actions,无服务器)
    - .github/workflows/telegram-bot.yml + scripts/telegram-bot.mjs
    - 私聊/群组命令:/help /releases /release <tag> /issues /issue <编号>
    - cron 每 5 分钟 getUpdates,处理后用 offset 向 Telegram 确认,无需持久化存储
    - 受 vars.TELEGRAM_BOT_ENABLED 开关;命令非实时(cron 限制),文档已说明
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • ci: Telegram notify on release / new issue (serverless via Actions)
    New .github/workflows/telegram-notify.yml: on release published or issue
    opened, send a message to a Telegram group via @WechatOnCloudBot. Runs on
    GitHub Actions (no server). Gated on vars.TELEGRAM_CHAT_ID so unconfigured
    forks skip safely. Arbitrary text passed via env (no script injection),
    sent as plain text with --data-urlencode (no markdown parse breakage).
    Setup documented in doc/发布到GHCR.md.
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • feat: 中文输入条 + 文件下载/另存修复 + 卡连接自愈 + CF/MAC/音频
    中文输入(彻底改造,弃用脆弱的 VNC IME 拦截)
    - 关闭 KasmVNC enable_ime:VNC 直接打字回归纯 keysym,英文/数字正常、不再损坏
    - 新增底部「中文输入条」:面板真实 textarea 原生输入法 → POST /type → 容器内 xclip+xdotool
      粘贴进微信,可靠且与浏览器/输入法无关。flex 列布局(nav/画面/输入条三者并列不遮挡),
      牛奶布艺主题配色,可一键收起。
    
    稳定性 / 自愈
    - watchdog 新增响应性探测:实例 I/O/服务 stall(进程在、显示在线但读不出 VNC 文件、永远"正在
      连接桌面")时,连续 2 次无响应即自动重启自愈
    - 前端 12s 未加载出来 → 「桌面无响应」+ 重新连接/重启,不再无限转圈
    - PWA 新 SW 接管即自动重载一次,更新一刷即生效(修"改了仍看旧界面")
    
    文件
    - 下载:正确解析 tar、跳过 PAX 扩展头(中文名文件曾因此大小错误/损坏)
    - 另存:每次启动确保 /config/Desktop 归 abc,修微信另存"保存失败"
    
    安全 / 伪装
    - Host 白名单支持 *.example.com 通配 + X-Forwarded-Host(修 CF 反代域名仍被拒)
    - 设备伪装新增真实网卡 MAC(厂商 OUI,替代容器本地管理位 MAC)
    
    音频:扬声器自动连接(首个手势激活)、焦点离开自动断、麦克风(HTTPS)
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • docs: add社媒 links (Twitter / Telegram) to README
    Hero badges + a 交流与关注 section: x.com/gloridust1024, t.me/WechatOnCloud.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
  • fix(P0): unique persistent machine-id per instance + manual reset
    All instances shared the image-baked machine-id (a67bf09f...), so Tencent
    saw every WechatOnCloud account worldwide as one "device" — a textbook
    device-farm signal triggering risk control and the forced-logout loop
    reported across old and new versions.
    
    - docker/woc-identity.sh: new /custom-cont-init.d/00-woc-identity hook —
      generates a unique machine-id on first start, persists it in the data
      volume (survives restart/upgrade/recreate), writes /etc/machine-id +
      /var/lib/dbus/machine-id, removes /.dockerenv. Existing instances get a
      fresh unique id on first upgraded start (volume lacks the file).
    - regenInstanceMachineId + POST /api/admin/instances/:id/regen-machine-id:
      roll a brand-new device id and restart, for accounts re-flagged by risk
      control. Gated on the hook being present (old image → instructs upgrade).
    - Admin 实例卡片「安全」弹窗新增「重置设备 ID 并重启」。
    
    Verified: two fresh containers get distinct machine-ids; id persists across
    restart; regen (rm persisted file + restart) yields a new persistent id.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
  • ci: optional Docker Hub mirror in release workflow
    - release.yml: dual-push to GHCR + Docker Hub when vars.DOCKERHUB_USERNAME
      is set; falls back to GHCR-only when unset (no behavior change for forks).
    - .env.example: surface docker.io as a first-class WOC_IMAGE_PREFIX option.
    - doc/发布到GHCR.md: document the one-time Variable + Secret setup and the
      prerequisite of pre-creating the public repos on hub.docker.com.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • docs(security): clarify multi-host allowlist + echo rejected host in 400
    - .env.example: surface multi-domain syntax (PANEL_ALLOWED_HOSTS=a,b,c),
      IPv6 literal example, and reverse-proxy troubleshooting tip.
    - index.ts: 400 response includes the rejected `host` and a hint pointing
      at PANEL_ALLOWED_HOSTS — drops the diagnostic floor when reverse-proxy
      Host-passthrough is misconfigured.
    
    Follow-up to #13 (DNS-rebinding allowlist).
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • Merge pull request #13 from aaronjmars/security/host-allowlist-dns-rebinding
    fix(security): gate panel Host header to block DNS rebinding
  • fix(security): gate panel Host header to block DNS rebinding
    Without Host validation, a malicious page the operator visits can use DNS
    rebinding to point a hostname at the panel's loopback / LAN IP and drive
    every authenticated API from the operator's own browser — including the
    docker.sock-backed admin endpoints. The README's "intranet-only" guidance
    does not cover this: the browser is the trust-boundary crossing.
    
    Add an onRequest hook (plus a Host check on raw WebSocket upgrades) that
    allows loopback + RFC1918 LAN by default and accepts public hostnames via
    PANEL_ALLOWED_HOSTS (documented in .env.example and threaded through
    docker-compose.yml). 35 inject()-driven assertions; tsc --noEmit clean.
    
    Detected by Aeon + manual review (DNS-rebinding-gate axis).
    Severity: high
    CWE-346 (Origin Validation Error)
  • Merge pull request #12 from huglemon/fix/cjk-ime-paste-fallback
    修复中文 IME 输入大量丢字:增加容器内剪贴板粘贴兜底路径
  • feat: 超管密码离线找回 + 改密/重置二次确认 + GHCR 手动构建文档
    - 密码找回:accounts.json 给用户加 "resetPassword": true(兼容 reset_password),
      重启面板即把其密码重置为 PANEL_ADMIN_PASSWORD(默认 wechat)、解禁并清除标记
    - 改密/重置密码弹窗新增「再次输入新密码」二次确认:两次不一致则拦截,
      避免浏览器自动填充/手误把密码静默设成非预期值导致锁死
    - README:补充方式 B(本机 buildx 手动多架构构建推送 GHCR)+ Release 的 latest 注意事项
      + 「重置超管密码(离线找回)」操作步骤
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • feat: 音视频/文件传输 + 产品 UX 改进 + 镜像源可切换
    媒体链路(生产 HTTPS 下可用,含降级)
    - 音频(听):PulseAudio + KasmVNC 工具条,开箱即用
    - 麦克风(说):virtmic 管道源已就绪,运行时需 HTTPS(非 HTTPS 前端提示)
    - 摄像头(视频):docker.ts 条件化 v4l2 设备直通 + 加 video 组;无设备/无 HTTPS 时优雅降级,音频麦克风不受影响
    - WOC_VIDEO_DEVICES 显式指定或经 /host-dev 自动探测
    
    文件传输(原生拖拽)
    - 面板侧拖拽上传 + 下载:dockerode putArchive/getArchive 到实例 ~/Desktop(持久卷)
    - 纯 JS 单文件 tar 编解码(免依赖),文本/二进制均无损;全程走面板鉴权与权限校验
    
    安全 & UX
    - 默认密码告警条 + mustChangePassword 追踪(兼容旧账号文件迁移)
    - 会话过期(401) 自动跳登录;桌面连接 loading 态
    - 停止/未创建实例一键启动(新增 /api/admin/instances/:id/start)
    - 统一牛奶布艺弹窗 + Toast,替换 Admin 原生 alert/confirm/prompt
    - 密码可见切换;实例重命名;退出二次确认;空状态改用品牌终端图标
    
    其它
    - gen-icons 生成终端风格图标(此前仅空白绿块,影响 Docker/CI 产物)
    - 镜像源可切换 WOC_IMAGE_PREFIX(国内反代/ACR);品牌名「云微」
    - 文档:.env.example / docker-compose 增加音视频(v4l2loopback/HTTPS)、镜像源、视频设备说明
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
  • 品牌更名为「云微」并替换为终端风格图标
    - 面板/PWA/iOS/fnOS 显示名统一改为「云微」(英文项目名 WechatOnCloud 保留)
    - favicon 改为绿底 macOS 终端风格(>_ 提示符),重新编译 180/192/512 PNG
    - 登录页 logo 复用同款终端图标
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>