功能: - StarLight Yggdrasil 第三方登录(后端中转,accessToken 不落地) - 管理员可视化权限管理(用户列表 + 一键授予/移出) - 设置页热配置(11 项可编辑,立即生效) - 循环池(每流独立手动歌单,队列空时随机不重复抽取) - 登录页统一主站浅色风格 - 全站改名「Starlight专属电台」 - 删除关于页 安全: - 全局 CSRF 防护(双提交 Cookie) - 登录限流防 XFF 伪造、错误信息脱敏 - 权限中间件 requireAdminForWrites(读放行/写 admin) - 密码哈希存储(scrypt/sha256) - SSRF 防护(封面下载域名白名单) - 空 catch 加日志、SSE 连接上限 修复: - 多角色账号 selectedProfile 缺失 - 普通用户越权删歌(V4) - streams 写操作越权(V9) - 设置页布局溢出 测试:38 项全绿(api16 / e2e17 / write5)
46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
import urllib.request, urllib.error, http.cookiejar, json, sys
|
|
|
|
BASE = "http://127.0.0.1:3000"
|
|
import os
|
|
TEST_PASSWORD = os.environ.get("TEST_PASSWORD", "123test")
|
|
cj = http.cookiejar.CookieJar()
|
|
op = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
|
|
|
|
def call(path, method="GET", data=None):
|
|
body = json.dumps(data).encode() if data is not None else None
|
|
req = urllib.request.Request(BASE + path, data=body, method=method)
|
|
if body: req.add_header("Content-Type", "application/json")
|
|
try:
|
|
r = op.open(req, timeout=60)
|
|
return r.status, r.read()
|
|
except urllib.error.HTTPError as e:
|
|
return e.code, e.read()
|
|
|
|
call("/api/auth/login", "POST", {"password": TEST_PASSWORD})
|
|
st, body = call("/api/resources")
|
|
songs = json.loads(body)["list"]
|
|
print(f"共 {len(songs)} 首,开始补全元数据...\n")
|
|
|
|
ok, fail = 0, 0
|
|
for s in songs:
|
|
st, body = call("/api/music/enrich", "POST", {"file": s["file"]})
|
|
if st == 200:
|
|
d = json.loads(body)
|
|
song = d.get("song", {})
|
|
cover = song.get("cover", "")
|
|
artist = song.get("artist", "")
|
|
status = "✓ 有封面" if cover else "○ 无封面"
|
|
print(f" {status} | {song.get('name','')} - {artist} | {cover}")
|
|
ok += 1
|
|
else:
|
|
print(f" ✗ 失败: {s['file']} -> {body[:80]}")
|
|
fail += 1
|
|
|
|
print(f"\n完成: {ok} 成功, {fail} 失败")
|
|
|
|
# 最终确认
|
|
st, body = call("/api/resources")
|
|
songs = json.loads(body)["list"]
|
|
with_cover = sum(1 for s in songs if s["albumImage"])
|
|
print(f"资源库: {len(songs)} 首,其中 {with_cover} 首有本地封面")
|
|
sys.exit(0) |