feat: StarLight 第三方登录 + 安全加固 + 循环池 + 热配置

功能:
- StarLight Yggdrasil 第三方登录(后端中转,accessToken 不落地)
- 管理员可视化权限管理(用户列表 + 一键授予/移出)
- 设置页热配置(11 项可编辑,立即生效)
- 循环池(每流独立手动歌单,队列空时随机不重复抽取)
- 登录页统一主站浅色风格
- 全站改名「Starlight专属电台」
- 删除关于页

安全:
- 全局 CSRF 防护(双提交 Cookie)
- 登录限流防 XFF 伪造、错误信息脱敏
- 权限中间件 requireAdminForWrites(读放行/写 admin)
- 密码哈希存储(scrypt/sha256)
- SSRF 防护(封面下载域名白名单)
- 空 catch 加日志、SSE 连接上限

修复:
- 多角色账号 selectedProfile 缺失
- 普通用户越权删歌(V4)
- streams 写操作越权(V9)
- 设置页布局溢出

测试:38 项全绿(api16 / e2e17 / write5)
This commit is contained in:
Xiao-no-love committed 2026-10-06 16:37:03 +08:00
1 parent 5066f32fa4
commit f0fe50e484
29 files changed
+1703 -315

No files matched your search

+197 -8
View File
@@ -328,12 +328,14 @@
.page {
display: none;
}
.page.active {
.page.active {
display: flex;
flex-direction: column;
gap: var(--sp-4);
flex: 1;
min-height: 0;
overflow-y: auto;
overscroll-behavior: contain;
animation: pageEnter 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes pageEnter {
@@ -361,6 +363,7 @@
display: flex;
flex-direction: column;
min-height: 0;
flex-shrink: 0;
}
@keyframes cardRise {
from {
@@ -807,15 +810,9 @@
justify-content: center;
padding: 0 5px;
}
.section-body {
.section-body {
padding: 0 0.5rem 0.5rem 0.5rem;
margin-bottom: 0.5rem;
flex: 1;
min-height: 0;
overflow-y: auto;
overscroll-behavior: contain;
scrollbar-width: thin;
scrollbar-color: var(--border) transparent;
}
.section-body::-webkit-scrollbar {
width: 5px;
@@ -2144,3 +2141,195 @@
outline: none;
}
.resource-sort:hover { border-color: var(--accent); }
/* StarLight 用户名显示 */
.user-name {
font-size: 13px;
color: var(--muted, #8b949e);
margin-right: 8px;
white-space: nowrap;
}
/* ==================== 设置页:热配置表单 ==================== */
.settings-form {
display: flex;
flex-direction: column;
gap: 2px;
}
.setting-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 9px 0;
border-bottom: 1px solid var(--border, #30363d);
}
.setting-row:last-child { border-bottom: none; }
.setting-row label {
font-size: var(--fs-sm, 0.85rem);
color: var(--text, #e6edf3);
flex: 0 0 auto;
}
.setting-row input,
.setting-row select {
width: 130px;
padding: 6px 10px;
background: var(--bg, #0d1117);
border: 1px solid var(--border, #30363d);
border-radius: var(--radius-sm, 6px);
color: var(--text, #e6edf3);
font-size: var(--fs-sm, 0.85rem);
outline: none;
text-align: right;
}
.setting-row select { text-align: left; }
.setting-row input:focus,
.setting-row select:focus { border-color: var(--accent, #1f6feb); }
/* ==================== 设置页:热配置表单 ==================== */
.settings-form {
display: flex;
flex-direction: column;
gap: 2px;
}
.setting-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 0;
border-bottom: 1px solid var(--border-light);
}
.setting-row:last-child { border-bottom: none; }
.setting-row label {
font-size: var(--fs-base);
color: var(--text-primary);
flex: 0 0 auto;
font-weight: 500;
}
.setting-row input,
.setting-row select {
width: 140px;
padding: 7px 10px;
background: #ffffff;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
color: var(--text-primary);
font-size: var(--fs-base);
outline: none;
text-align: right;
font-family: inherit;
}
.setting-row select { text-align: left; }
.setting-row input:focus,
.setting-row select:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-glow);
}
.setting-row input::placeholder { color: var(--text-muted); }
/* ==================== 权限管理:用户列表 ==================== */
.user-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.user-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 11px 14px;
background: var(--bg);
border: 1px solid var(--border-light);
border-radius: var(--radius-sm);
}
.user-item .user-meta {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.user-item .user-name {
font-size: var(--fs-base);
font-weight: 600;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 6px;
}
.user-item .user-sub {
font-size: var(--fs-xs);
color: var(--text-muted);
font-family: monospace;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.admin-badge {
font-size: var(--fs-2xs);
font-weight: 700;
color: #fff;
background: var(--accent);
border-radius: var(--radius-pill);
padding: 1px 8px;
}
.btn-mini {
font-size: var(--fs-sm);
font-weight: 600;
font-family: inherit;
padding: 6px 12px;
border-radius: var(--radius-pill);
border: 1px solid var(--border);
background: var(--surface);
color: var(--text-secondary);
cursor: pointer;
transition: all .18s;
white-space: nowrap;
}
.btn-mini:hover { border-color: var(--accent); color: var(--accent); }
.btn-mini.danger:hover { border-color: var(--danger); color: var(--danger); }
.user-empty {
text-align: center;
color: var(--text-muted);
font-size: var(--fs-sm);
padding: 20px;
}
/* ==================== 设置页布局优化 v2 ==================== */
/* 让整页统一滚动,卡片更透气 */
#pageSettings {
gap: var(--sp-5, 20px);
padding-bottom: 2rem;
}
#pageSettings .section-card {
margin-bottom: 0;
}
/* 热配置表单更宽松 */
#pageSettings .settings-form {
gap: 0;
}
#pageSettings .setting-row {
padding: 12px 0;
}
#pageSettings .setting-row label {
font-size: var(--fs-md, 0.92rem);
}
#pageSettings .setting-row input,
#pageSettings .setting-row select {
width: 150px;
padding: 8px 12px;
}
/* 日志区限高,自身滚动(唯一允许内滚的区域) */
#pageSettings .log-view {
max-height: 360px;
overflow-y: auto;
}
/* 用户列表项间距 */
#pageSettings .user-list {
gap: 10px;
}
/* 循环池按钮激活态 */
.btn-icon.js-pool.active {
color: var(--accent);
background: var(--accent-light);
}