Commit Graph
277 Commits
Author SHA1 Message Date
saopig1andClaude Opus 4.7 c0504d65a5 fix(web): localize user.role_changed audit label
Adds the missing case so role-change entries display in Chinese
instead of falling through to the generic key→target format.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 15:43:09 +08:00
saopig1 780726a4e3 feat(web): role-aware UI (badge, selector, toggle button, hide admin-only sections for members) 2026-05-27 15:38:42 +08:00
saopig1andClaude Opus 4.7 a73f797bcb feat(auth): two-role permission system (admin/member)
Adds an admin/member role to WebUI auth. /api/users and /api/audit
are now gated by a requireAdmin middleware; all other authenticated
endpoints accept both roles. Schema migration defaults all existing
users to admin to preserve access. POST /api/users defaults new users
to member; first-run setup always creates an admin. Adds PATCH
/api/users/:id/role with last-admin demotion and deletion guards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 15:35:15 +08:00
saopig1 b0b61f8fce fix(auth): defensive audit-record + self-reset preserves current session 2026-05-27 15:16:55 +08:00
saopig1 7be4f13774 feat(web): operation audit log section in Settings 2026-05-27 15:06:54 +08:00
saopig1andClaude Sonnet 4.6 6af0e97f51 feat(auth): user-management audit log (table + record sites + /api/audit endpoint)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 15:04:19 +08:00
saopig1andClaude Sonnet 4.6 ceb24595e6 fix(auth): race-safe first-run setup + rolling cookie max-age refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 14:54:19 +08:00
saopig1andClaude Sonnet 4.6 fb7feec5cf feat(web): user management section in Settings (list/create/delete/reset-password)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 14:44:42 +08:00
saopig1andClaude Sonnet 4.6 175b8e6065 feat(auth): add /api/users CRUD (list, create, delete, reset-password)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 14:41:58 +08:00
saopig1andClaude Opus 4.7 f46b37192f fix(web): break infinite recursion in apiFetch by capturing nativeFetch
apiFetch called window.fetch which installApiClient had reassigned to
call apiFetch — every request blew the stack. Capture the native fetch
at module load (before any wrap) and use it inside apiFetch.

Symptom: first-run / login redirect never fires because the router
guard hangs on session.refresh().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 14:34:56 +08:00
saopig1 a8b056d2aa fix(auth): WS Origin host check + Login next-param open-redirect guard 2026-05-27 14:02:33 +08:00
saopig1andClaude Sonnet 4.6 e148c1556e feat(web): show current user + logout button in nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:57:31 +08:00
saopig1 e2e888710a fix(web): exclude /api/session/* from 401 auto-refresh to prevent re-entrancy 2026-05-27 13:56:14 +08:00
saopig1andClaude Sonnet 4.6 7509814abc feat(web): install global fetch wrapper with credentials + 401 handling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:54:24 +08:00
saopig1andClaude Sonnet 4.6 0dc8746914 feat(web): add /first-run + /login routes with auth guard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:52:49 +08:00
saopig1 2560fc87c2 feat(web): add Login view 2026-05-27 13:51:20 +08:00
saopig1 6db35f704d feat(web): add useSession composable 2026-05-27 13:50:14 +08:00
saopig1andClaude Sonnet 4.6 490b2d57dc test(auth): verify ws upgrade gating end-to-end
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:49:05 +08:00
saopig1andClaude Sonnet 4.6 486979841e feat(auth): gate /api/* behind requireAuth + csrf; gate /ws via upgrade handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:46:59 +08:00
saopig1andClaude Sonnet 4.6 ee5673a22f feat(auth): add /api/session router (setup, login, logout, me, change-password)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:42:00 +08:00
saopig1andClaude Sonnet 4.6 d1c9e14bf0 feat(auth): add csrfOriginCheck middleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:38:35 +08:00
saopig1andClaude Sonnet 4.6 17c11f0512 feat(auth): add requireAuth middleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:36:26 +08:00
saopig1 df5d125279 feat(auth): add shared validateSessionFromHeaders helper 2026-05-27 13:34:47 +08:00
saopig1andClaude Sonnet 4.6 5914f41ea1 feat(auth): add SessionStore with rolling renewal and at-rest token hashing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:33:22 +08:00
saopig1 68a2fb2943 refactor(users): use SQLITE_CONSTRAINT_UNIQUE error code instead of message text 2026-05-27 13:31:31 +08:00
saopig1andClaude Sonnet 4.6 34523cb00f feat(auth): add UserStore with bcryptjs password hashing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:29:39 +08:00
saopig1andClaude Sonnet 4.6 8ea1a64c59 feat(db): add users and sessions tables for WebUI auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:27:12 +08:00
saopig1 df79976933 deps: add bcryptjs + cookie-parser + supertest for WebUI auth 2026-05-27 13:25:32 +08:00
saopig1andClaude Opus 4.7 d3af918f53 docs(plan): WebUI authentication implementation plan
16 bite-sized tasks with TDD discipline:
- 10 backend (schema, users, sessions, middleware, /api/session router,
  server.ts wiring, WS upgrade gating + integration test)
- 5 frontend (useSession composable, Login + FirstRunSetup views,
  router guard, fetch wrapper, Navbar logout)
- 1 manual smoke test gate before PR

Notes /first-run as the admin-setup route since /setup is already taken
by the bot-creation wizard.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 13:18:10 +08:00
saopig1andClaude Opus 4.7 f7c16888e7 docs(spec): WebUI authentication design
Spec for adding username+password auth to the WebUI to close the
unauthenticated-API exposure (all /api/* and /ws currently open).

Design: SQLite users + sessions tables, bcryptjs, 7-day rolling
HTTP-only cookie sessions, first-run setup wizard, Origin/Referer
CSRF check, WebSocket upgrade gated on the same session cookie.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 13:07:51 +08:00
TIANYAO ZHANG 7fc5186c24 Merge pull request #65 from ZHANGTIANYAO1/fix/bilibili-wbi-search
fix(bilibili): wbi-sign search params — legacy /search/type now anti-bot blocked
v1.4.7
2026-05-16 22:31:55 +08:00
saopig1andClaude Opus 4.7 de92c8bcd4 fix(bilibili): wbi-sign search params — legacy /search/type now anti-bot blocked
Closes #64. Bilibili moved the unsigned /x/web-interface/search/type endpoint
behind their anti-bot wall; it now returns an HTML error page (出错啦!) even
with buvid3+buvid4 cookies, causing `play -b` to report "No results found".

Switch search() to /x/web-interface/wbi/search/type with proper wbi signing:
fetch img_key/sub_key from /nav, derive the mixin key via the standard
permutation, and sign each request with wts + w_rid (md5). Keys are cached
for 6h since they rotate ~daily. Other endpoints (view, playurl, popular,
top/rcmd) still work unsigned and are left unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:29:12 +08:00
TIANYAO ZHANG 6b143e1a56 Merge pull request #63 from XuVIIJay/pr/setup-scripts
安装脚本优化(对国内网络环境安装友好)
v1.4.6
2026-05-16 02:02:10 +08:00
XuVIIJay 5728209573 fix(setup.sh): add Node.js and npm version check before install 2026-05-15 21:03:28 +08:00
XuVIIJay 02d8b39d75 fix(setup.bat): remove hardcoded personal Node.js paths 2026-05-15 20:56:59 +08:00
XuVIIJay f87aaaf8c3 feat(scripts): optimize setup/start scripts for China network 2026-05-15 20:42:51 +08:00
TIANYAO ZHANG 8861f39ecc Merge pull request #62 from NoSetViolin/main
fix(qq): switch search to c.y.qq.com client_search_cp with u.y.qq.com fallback
v1.4.5
2026-05-14 22:44:41 +08:00
NoSetViolinandClaude Opus 4.7 6d5755ced7 feat(search): source filter bar, album search, and UX polish
- Add platform source filter bar (网易云/QQ/B站) above category tabs with
  localStorage persistence to remember user preference
- Remove "全部" option, single-source view only
- Increase album/playlist card column-gap to 28px for better spacing
- Sync search query to URL via router.replace so back-navigation from
  album/playlist detail pages restores search results
- Fix !album command: add name-based album search (matching !playlist
  behavior) so "!album APT." searches by name instead of treating it as ID

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 18:56:14 +08:00
NoSetViolinandClaude Opus 4.7 997bb17ceb feat(search): add tabbed category navigation + align NetEase result counts
- Replace single-page layout with pill-slider tabs (单曲/专辑/歌单) under
  the search box, showing only one category at a time with result counts
- NetEase album/playlist search limit raised from 5 to 10 to match QQ

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 16:56:18 +08:00
NoSetViolinandClaude Opus 4.7 ea6501ea81 feat(web): add platform badges to album and playlist cards in search
Album and playlist results now show source tags (网易云, QQ, B站, YouTube)
matching the existing SongCard platform badge style.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 16:34:26 +08:00
NoSetViolinandClaude Opus 4.7 1d2da33d3c fix(qq): apply musicu.fcg upstream fixes + add playlist search
Per https://github.com/ZHANGTIANYAO1/teamspeak-music-bot/issues/61:
- Remove searchid param (its presence now causes empty results)
- Enforce num_per_page >= 10 (lower values return empty)
- Fix search_type: 2 for albums, 3 for playlists (8 was "user")

Now uses the fixed musicu.fcg as primary (supports songs + albums +
playlists), with client_search_cp as fallback.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 16:28:12 +08:00
阿梓喵_あずにゃんandClaude Opus 4.7 0e68e287b7 fix(qq): switch search to c.y.qq.com client_search_cp with u.y.qq.com fallback
u.y.qq.com/cgi-bin/musicu.fcg started returning is_filter=-9 (empty results)
for unauthenticated requests. Primary search now uses the classic
c.y.qq.com/soso/fcgi-bin/client_search_cp endpoint, with the old musicu.fcg
path kept as a fallback in case the primary endpoint changes format or goes
down.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 15:55:21 +08:00
TIANYAO ZHANG ecdb2d253e Merge pull request #60 from XuVIIJay/feat/forward-stack
随机播放模式双向可回溯
v1.4.4
2026-05-12 22:23:35 +08:00
XuVIIJay 8860347bfe Update README.md 2026-05-12 00:04:20 +08:00
XuVIIJay beb99f1d8e Update README.md 2026-05-11 23:49:34 +08:00
XuVIIJay 63f1ced2bc feat(queue): add forwardStack for reversible prev/next navigation
In Random/RandomLoop modes, prev now records the current position
to a forwardStack, and next pops from it first. This ensures prev→next
navigation is fully reversible for any number of steps (up to 50).

Also rebuild playedIndices in prev() so songs reached via backward
navigation become available for random selection again.
2026-05-11 23:45:04 +08:00
saopig1andClaude Opus 4.7 fa6013d22e docs(commands): surface existing !remove <position> in help and README
Closes #59. The command was already implemented but not advertised in
!help output or the README command table, so users assumed it was missing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 20:56:49 +08:00
saopig1andClaude Opus 4.7 6b60792277 feat(web): custom avatar field in edit-bot modal
User reported that the edit-bot dialog had no avatar option (only
create-bot did). Reuses the same CustomAvatarRow component, which
auto-loads on mount and PUT/DELETEs on change. Each bot's avatar
is bound by botId — independent across bots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.4.3
2026-05-07 21:23:21 +08:00
saopig1andClaude Opus 4.7 c562fe05b0 fix(player): start frame loop only after ffmpeg spawns in jdymusic path
PR #54's playViaPowerShellDownload called startFrameLoop() right after
spawning the PowerShell downloader, before ffmpeg existed. The loop's
"no ffmpeg + empty buffer → emit trackEnd" branch fired on the very
first tick (~25ms), skipping every jdymusic song. Visible as: each
PowerShell download sessionId logged "Track ended, advancing queue"
before the download completed, so the queue burned through every
track in a few seconds.

Move startFrameLoop() into spawnFfmpegFromFile() where ffmpeg is
known to be alive and producing PCM. state = "playing" still flips
in playViaPowerShellDownload so external observers see the right
status during download.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 21:04:27 +08:00
TIANYAO ZHANG 9efa818bbb Merge pull request #57 from ZHANGTIANYAO1/feat/album-search
feat(search): album section + album playback
2026-05-07 20:50:02 +08:00