Commit Graph

51 Commits

Author SHA1 Message Date
effc262382 fix: site name in top logo + server-list public + external API docs page
- app.js: set #logo-text (top bar) from window.__SITE_NAME__ - the
  top-right site name stayed default because only #site-title and
  #sidebar-title were set
- security.js: apiKeyGuard whitelist /api/polls/server-list so the
  ticket create page can load sub-servers (was 401 without api key)
- external-api.js: management page now only creates/manages clients,
  removed inline endpoint table
- new external-api-docs.js: full API doc page (auth flow, all 11
  endpoints, request/response examples, Node sample) at
  #/external-api-docs, linked from the management page
- index.html: load external-api-docs.js
2026-08-22 02:18:29 +08:00
188e083719 refactor: auth expiry - sync JWT exp check, remove async validation
Previous async validateAuth() approach caused: recursion loop,
wrong /me path (404 -> session cleared), init() fetching auth-required
settings without token (cleared session every load).

New synchronous approach:
- Auth.expired(): decodes JWT payload locally, checks exp timestamp
- Auth.logged(): token+user exist AND not expired; auto-clears stale
  session on expiry (no network, no async, no loops)
- route(): simple sync guard - if !Auth.logged() reset + redirect to
  #/login; home page stays public (clears stale cookie only)
- API.req: 401 response -> Auth.reset() + redirect to login unless on
  public page (fallback for server-side revocation/invalid signature)
- Removed validateAuth/_validating/_doRoute entirely
2026-08-21 21:01:30 +08:00
edf561729f fix: backend pages redirect loop - wrong /me path + init() clearing auth
Root causes (both in app.js):
1. validateAuth() called API.get('/me') = /api/me, but the route is
   mounted at /auth/me (businessRouter.use('/auth', authRoutes)).
   /api/me returned 404 -> non-auth error was re-thrown -> outer
   .catch() unconditionally Auth.reset() + redirect to #/login.
   Fixed: call /auth/me; non-auth errors (network/404/500) now return
   true (allow routing) instead of throwing.
2. init() fetched /api/settings/settings WITHOUT token, but that route
   requires authenticate+requireRole. Always 401 -> __SITE_NAME__ never
   set -> 'Auth.logged() && !window.__SITE_NAME__' always true ->
   Auth.reset() on EVERY page load, wiping valid login.
   Fixed: removed the fetch and the reset line - site_name is already
   injected server-side as window.__SITE_NAME__ (getHtmlWithKey).
2026-08-21 20:57:25 +08:00
7b50b599cf fix: infinite login loop from async auth validation
- Add _validating flag to prevent recursive hashchange calls during async
  token validation
- route() checks _validating before calling validateAuth(), sets flag
  before async call, clears in .then/.catch handlers
- route() returns early if still validating (waits for completion)
- Fixes: expired token causing infinite login redirect loop
2026-08-21 20:52:41 +08:00
e232f3b02e fix: auth expiry - validate token before showing protected pages
- Add validateAuth() method: calls /api/me to verify token validity,
  clears Auth state on 401/login error
- route() now calls validateAuth() async for ALL protected pages
  BEFORE showing layout/sidebar/rendering content
- Extract _doRoute() for actual page rendering (runs after validation)
- init() uses API.get for install check (proper auth handling)
- Added reset() to Auth: clears localStorage without redirecting

This fixes: expired token showing login-required pages, and no feedback
when session expires mid-session.
2026-08-21 20:46:09 +08:00
6ac8a5cd11 fix: site_name not loaded + expired token not cleared
- app.js init(): use native fetch (no Bearer) to call /api/install/status
  and /api/settings/settings, so site_name loads even before login
  state is confirmed; call Auth.reset() if logged but no site_name set
- auth.js: add reset() method that clears TK/US without redirecting
- app.js route(): remove early return for uninstalled; let install check
  run first so init() can fall through to normal routing when installed
- app.js renderMain(): catch 401/login errors from page render, clear
  Auth state, show login prompt with button that redirects back after
  login (target hash preserved)
2026-08-21 20:31:45 +08:00
8c5ce78fd0 chore: add AGPLv3 copyright header to all source files
- 52 JS files (backend + public/js): header with
  Copyright (C) 2026 Sea Network Technology Studio
  Author: CangLan <admin@sea-studio.top>
  + AGPLv3 notice
- idempotent (skips if header present), all syntax-checked
2026-08-19 20:27:05 +08:00
65edbaf157 refactor: session-based external auth, dynamic sources, drop netease UID
Auth (external API):
- ID: 16-digit random (non-sequential); Secret: SeaReport- + 32 hex
- POST /auth/session: ID+Secret -> Bearer SESSION (24h, single-session,
  old session invalidated on re-issue, disabled client invalidates)
- clientAuth now validates Bearer SESSION via api_sessions JOIN api_clients

Sources (dynamic, no default, open-source friendly):
- sources table + CRUD route (/api/sources, owner; delete guarded by usage)
- users/user_identities.source ENUM -> VARCHAR, seeded netease/skin
- register/admin create/identity bind: validate against enabled sources
- UI: 来源管理 page; source dropdowns loaded dynamically everywhere
  (register, dashboard identity, users admin, bans), labels dynamic

UID removal:
- game_uid/reporter_game_uid no longer required (db default '', validations
  dropped, frontend fields optional)

Docs: EXTERNAL-API.md session flow + new credential format; API.md updated
Verified: 37 checks (syntax, session logic, source CRUD, UID removal, docs)
2026-08-19 20:08:06 +08:00
257cd14051 feat: external API for QQ bot - client id+secret auth, ticket tracking, bans, per-server data
- db: api_clients table + server_groups.alias + tickets/bans server_name (auto-migrate)
- external.js: client_id+secret auth (multi-client, bcrypt, show-once secret),
  legacy x-external-key compat, JWT pass-through
  - POST /tickets (optional server), GET /tickets/track?token= (full lifecycle)
  - GET/POST /bans, reported-players/stats/all-tickets with server filter
  - GET /servers (alias list), client CRUD (owner/admin, audit logged)
  - resolveServer: alias | 分组/子服 | server_name
- polls.js: server_groups CRUD with alias (add/edit, dup check)
- servers page: alias display + edit; new 外部API page: client mgmt + quick docs
- API.md: full external API section (auth matrix, server param syntax)
- verified: 37 checks incl. resolveServer sandbox (alias/group/fallback)
2026-08-19 19:12:34 +08:00
a11df22600 feat: system logs - email log + system log with admin UI
- db: email_logs (sent/failed) + system_logs (info/warn/error) tables,
  auto-migrated for existing installs
- backend/logger.js: logEmail/logSystem with try/catch (never breaks flow)
- mailer: log send result (SMTP unconfigured/sent/failed + error msg)
- webhook: log blocked-internal, non-2xx response, send failure
- server: error middleware records 500 errors to system_logs
- routes/logs.js: GET /logs/emails + /logs/system (admin/owner, filters)
- UI: 系统日志 page (owner/admin) with system/email tabs + filters
- API docs updated
2026-08-17 05:14:41 +08:00
1740a52cda fix: install page blank - init() early return skipped route registration 2026-08-16 21:27:46 +08:00
6e9101a506 fix: deploy crash + multiple bug fixes + cleanup
- server.js: fix getSiteName() returning string when not installed causing
  'getSiteName(...).then is not a function' crash on homepage (deploy blocker)
- server.js: auto-load business routes after install completes (no restart needed),
  HTML cache keyed by api_key
- install: validate db name/email/password, trigger route loading after complete
- app.js: fix forgot/reset/verify pages rendering HomePage (missing page mapping)
- verify.js: support URL token auto-verification for external registration links
- auth: new email_code template for 6-digit code, reset_password template
  (forgot-password was using verify_email template)
- upload.js: fix MP4 magic-bytes check using undefined buf variable
- tickets.js: status enum validation, anonymous submission rate limit
- security.js: XSS whitelist preserves email template HTML, strips scripts,
  blocks javascript:/data: hrefs; CORS reject returns 403
- bans.js: allow clearing reason/duration, status enum validation
- users.js: fix req.user.role ReferenceError in create user modal
- home.js: tracking results now have detail view button
- .gitignore: ignore data/ (db credentials), logs, session files, temp scripts
2026-08-16 21:21:25 +08:00
d242786a3a feat: bans sidebar page, public view with masked names 2026-07-18 01:17:40 +08:00
0bd32a1549 fix: keep top bar on home page, tabs stay in page content 2026-07-17 13:39:15 +08:00
0892dd5f8e fix: hide top bar on home page, tabs back in page content 2026-07-17 13:32:28 +08:00
9eb8aba371 fix: home page tabs in top bar, single nav layer 2026-07-17 13:21:30 +08:00
8f7c34dd86 fix: captcha full-width row, hide top-auth on anonymous submit page 2026-07-17 13:14:15 +08:00
ead50beccd feat: 6-digit email verification code, fix missing script+route includes 2026-07-17 00:34:47 +08:00
2961ca67d1 fix: sidebar highlights tickets-create when on create form 2026-07-17 00:10:34 +08:00
1762b016cd fix: tickets-create route matches create?type param, proper redirect 2026-07-17 00:09:02 +08:00
ab08b1a2a9 feat: feature discussion as separate detail page, not inline 2026-07-16 23:50:16 +08:00
09f0d8f2aa fix: 12 issues - admin permission scope, player sidebar nav, SMTP label, user create servers 2026-07-16 23:04:15 +08:00
f423e1f791 fix: dynamic site name from DB, displayed in header/title/sidebar 2026-07-16 04:02:19 +08:00
abf747e3af feat: dedicated server groups management page in sidebar 2026-07-16 03:56:09 +08:00
021351d898 fix: restore from regex corruption, JS-bind modal close, data-action delegation 2026-07-15 03:53:16 +08:00
80f8342c0b debug: add window.onerror to display JS errors in sidebar 2026-07-15 03:49:50 +08:00
0f64af42a1 feat: password reset + data-action delegation for all onclick 2026-07-15 02:45:33 +08:00
f0e891b17c fix: data-action delegation + convert onclick to event listeners, sidebar+logout+modals 2026-07-15 02:44:18 +08:00
9e15a319f5 fix: replace all inline onclick with JS event listeners (sidebar nav + logout) 2026-07-14 05:37:37 +08:00
b4df827f0d fix: restore missing window.App=App causing sidebar+logout broken 2026-07-14 04:30:38 +08:00
8c36314253 fix: hide top bar in admin, add polls+features links, logout text 2026-07-14 04:06:45 +08:00
4913984391 feat: poll groups/servers, timed polls, features sort+filter by group 2026-07-14 03:17:13 +08:00
d61ad2109f refactor: remove polls+features, move to standalone mc-vote repo 2026-07-14 03:11:26 +08:00
ee2f33c61f feat: feature voting (PCL-style), poll owner edit/delete, blind polls for all 2026-07-14 01:17:56 +08:00
116fe89ac8 feat: poll/voting system with live results and bar charts 2026-07-13 21:37:16 +08:00
728a4c46f1 fix: keep top bar visible in admin mode too 2026-07-12 21:57:45 +08:00
6f66b854b3 fix: add logout text label in top bar 2026-07-12 21:57:22 +08:00
650a65e347 fix: hide top bar in admin mode, sidebar is the primary nav 2026-07-12 21:28:20 +08:00
83398d1fab feat: quick nav buttons in top bar when logged in 2026-07-12 21:24:49 +08:00
a9d85b2d07 fix: top bar shows username+logout when logged in, not blank 2026-07-12 21:23:16 +08:00
531d2a6e26 fix: expose all page objects to window for inline onclick handlers 2026-07-12 21:16:05 +08:00
82c2671149 fix: loadFooter only for admin, only once per session 2026-07-12 04:21:26 +08:00
f2fec8e609 fix: loadFooter after login, escape user-info, error handling on render 2026-07-12 03:16:02 +08:00
50f3cace51 fix: move install check to init once, route() sync for instant nav, hide top-bar in admin 2026-07-12 02:40:08 +08:00
7699bd0598 fix: keep top bar visible, raise sidebar z-index to 210 to prevent overlap 2026-07-12 02:20:54 +08:00
9241dd6a6f fix: add appeal button, hide top bar when logged in so sidebar is clickable 2026-07-12 02:14:25 +08:00
f09a554ea3 fix: make LoginPage.render async to unify async render contract 2026-07-12 02:04:10 +08:00
989a3ae4cf feat: home page hash-based tab routing for shareable links 2026-07-12 01:53:59 +08:00
5bb2df7b52 fix: login broken by sync/async mismatch, register missing home link, top bar contrast 2026-07-12 01:50:17 +08:00
a6058bf207 feat: top bar, footer, login/register buttons, ICP/copyright settings 2026-07-12 01:32:18 +08:00