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:
1 parent
5066f32fa4
commit
f0fe50e484
29 files changed
+1703
-315
No files matched your search
+197
-8
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user