Files
ykxmz/_build/halo_reset_email.py
xmz7891 2061f9525f 2.3.0:手表界面精简 + 播放器 + 鼠标重做
手表端
- 功能页从 10 个杂项精简到 7 个(屏幕/鼠标/媒体/文件/电脑/语音/电源)
- 删掉:游戏封锁、待办、掷骰子、抽奖、壁纸、显示器开关、定时关机、
  剪贴板历史、性能/磁盘/电量、文件夹浏览、教室限制等
- 改成显式列按钮,不再把电脑端所有功能组无脑铺到表盘
- 远程鼠标控制重做:滑动区 + 左键/滚轮/右键三按钮
  滚轮点按=中键、上下滑=滚动
- 新增视频/音乐播放器(手表本地播放):进度拖动、左右滑快进退10秒、
  点画面播放暂停、上一/下一、播完自动下一首

电脑端
- 新增 kill_all(结束所有进程),白名单保护系统关键进程和自身
- 新增 media_list / media_pull(播放器数据源)
  安全边界:只允许媒体目录,用 relative_to 判断,防同前缀兄弟目录绕过

中转站
- known_devices 从 ID 集合改成「设备ID -> 配对码」映射
- 修复:管理员改码后关机超过 6 小时,改码会被超时清理冲掉
- 老格式 state 文件平滑升级
2026-10-18 11:39:14 +08:00

117 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
r'''走 Halo 的「邮箱找回密码」流程。
== 流程长什么样 ==
Halo 2.x 的重置密码分两步:
1. POST /password/restore/email {"email": "..."}
-> 服务器往这个邮箱发一个验证码(6 位数字)
2. POST /password/restore/email/verify {"email": "...", "code": "..."}
-> 校验验证码
3. PUT /password/restore {"password": "新密码"}
-> 用上一步换来的临时凭据改密码
**⚠ 但前提是 Halo 配了 SMTP** —— 没配的话邮件根本发不出去,
用户等半天收不到码,白折腾。
所以这个脚本**先查 SMTP 配置**,再决定要不要发。
== 为什么不用令牌 ==
用户先提邮箱这个方案,就按他的来。但两个方案其实可以并行:
* 邮箱重置:能改密码 → 然后我用新密码登录
* 个人令牌:不用改密码,更安全
**改密码有个副作用**:用户自己也得记住新密码。
所以我会把新密码**明确告诉用户**。
== 关于验证码 ==
用户会把验证码发给我。验证码有时效(Halo 默认 10 分钟),
所以拿到之后要**立刻**用。
'''
from __future__ import annotations
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "_build"))
from lssh import run # noqa: E402
EMAIL = "3235109770@qq.com"
def main() -> int:
print("=" * 62)
print(" Halo 邮箱找回密码 —— 先确认能不能发邮件")
print("=" * 62)
print()
print("── 1. 重置接口存在吗 ──")
out = run(r'''
BASE=http://127.0.0.1:3001
for ep in \
"/password/restore/email" \
"/apis/api.halo.run/v1alpha1/password/restore/email" \
"/apis/uc.api.auth.halo.run/v1alpha1/password/restore/email" \
"/apis/api.console.halo.run/v1alpha1/indices/-/users" \
; do
printf " %-64s " "$ep"
curl -s -o /dev/null -w "%{http_code}\n" --max-time 8 "$BASE$ep"
done
echo
echo "── 2. 探测一下 POST 的形状(不发真请求,只看方法是否允许)──"
curl -s -o /dev/null -w " POST /password/restore/email -> %{http_code}\n" \
--max-time 10 -X POST "http://127.0.0.1:3001/password/restore/email" \
-H "Content-Type: application/json" -d '{}'
echo
echo "── 3. Halo 的 SMTP 配了吗(数据库里找)──"
sudo docker exec halo sh -c "
find /root/.halo2 -name '*.mv.db' -o -name '*.db' 2>/dev/null | head -3
" 2>/dev/null | sed 's/^/ /'
echo " 从设置接口看(需要登录,先看看会不会泄露结构):"
curl -s --max-time 8 "http://127.0.0.1:3001/apis/api.halo.run/v1alpha1/configmaps" | head -c 200
echo
echo
echo "── 4. 邮件相关的日志(有没有发信记录/报错)──"
sudo docker logs halo 2>&1 | grep -iE "mail|smtp|email|JavaMail" | tail -10 | sed 's/^/ /' || echo " (日志里没提邮件)"
echo
echo "── 5. 用户的邮箱地址(确认收件人)──"
curl -s --max-time 8 "http://127.0.0.1:3001/apis/api.halo.run/v1alpha1/users" | head -c 300
echo
''', timeout=300, quiet=True)
print(out[1] if isinstance(out, tuple) else out)
print()
print("── 6. 试发一次(如果接口在)──")
out = run(r'''
curl -s -w "\n HTTP %{http_code}\n" --max-time 20 \
-X POST "http://127.0.0.1:3001/password/restore/email" \
-H "Content-Type: application/json" \
-d '{"email":"__EMAIL__"}' 2>&1 | head -20
'''.replace("__EMAIL__", EMAIL), timeout=200, quiet=True)
print(out[1] if isinstance(out, tuple) else out)
print()
print("── 7. 发完之后看日志(有没有真发出去)──")
out = run(r'''
sleep 3
sudo docker logs --tail 40 halo 2>&1 | grep -iE "mail|smtp|email|restore|code|error|exception" | tail -15 | sed 's/^/ /' || echo " (没有相关日志)"
''', timeout=200, quiet=True)
print(out[1] if isinstance(out, tuple) else out)
return 0
if __name__ == "__main__":
sys.exit(main())