- app.js: remove window.Dashboard=... block that crashed the whole
file before page scripts load (ReferenceError: Dashboard is not
defined). Page objects are top-level const in global lexical
scope; PAGE_OBJS map + indirect eval in loadScript onload now
expose them to window for inline onclick / data-action lookups
- index.html: Font Awesome 6.5.1 localized (css/fontawesome.min.css
+ 8 webfont files) - no more cdnjs CDN (Edge Tracking Prevention
blocked it, CN access unstable)
- CSS: drop @import fonts.googleapis (blocked by CSP style-src,
unreachable in CN) - use system font stack with YaHei fallback
- index.html: remove all 26 js/pages/*.js tags - core 4 scripts only
- app.js: route-based lazy loading - PAGE_SCRIPTS map, loadScript
with cache, async route() loads page scripts before render
- cross-deps: home->ticket-create, reset defined in forgot.js
- settings.js: new public GET /settings/public returns only
copyright + icp (no auth, no sensitive settings leaked)
- app.js loadFooter(): dropped Auth.isAdmin() gate, uses public
endpoint; showPublic() (home/root) now loads footer too
- security.js: apiKeyGuard whitelist /api/settings/public and
/api/settings/skin-site
- logout() on home/root page: Auth.reset() only (clear state, refresh
top bar), no redirect to login; other pages still go to login
- home page container: width:min(50vw+300px, 1440px, 96vw) replaces
fixed max-width:800px - PC wide screens use at least half viewport,
mobile near full width
- 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
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).
- 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
- 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.
- 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)