Forum teuk.org

mbweb β€” Refactoring and improvements round 3 (April 2026)

in Mediabot Β· started by TeuK Β· 18h ago

TeuK Β· 18h ago

mbweb β€” Refactoring and improvements round 3 (April 2026)

Context

Third audit pass on the mbweb web console. This article covers the remaining items from the backlog: bug fixes, full i18n cleanup, and the major structural refactor of app.js.


Bug fixes

B1 β€” /channels missing try/catch

The HTML /channels route had no error handler around the DB calls, unlike every other route. A DB failure would propagate unhandled. A try/catch block was added, consistent with the rest of the codebase.

B2 β€” fmtUptime returning French suffixes

viewHelpers.js was outputting 2j 3h 14mn instead of 2d 3h 14m. Suffixes corrected: j β†’ d, mn β†’ m.

B3 β€” lang="fr" in the HTML root element

lib/render.js was declaring <html lang="fr"> on every page. Corrected to lang="en".


Full English UI

All remaining French strings were translated across app.js, routes/auth.js, lib/render.js, and lib/sessionUser.js. This covers page titles, section headers, table headers, error messages, hero paragraphs, stat card labels, filter bars, empty states, nav labels, and the login form.


R9 β€” app.js split into dedicated route files

app.js went from 1867 lines to 134. All route handlers were extracted into separate files under routes/:

File Routes
routes/home.js GET /
routes/profile.js GET /profile, GET /api/me
routes/channels.js GET /channels, GET /channels/:id, GET /api/channels, GET /api/channels/:id
routes/radio.js GET /radio, GET /api/radio/status
routes/network.js GET /network, GET /api/network
routes/quotes.js GET /quotes, GET /api/quotes
routes/commands.js GET /commands, GET /api/commands
routes/users.js GET /users, GET /api/users
routes/metricsProxy.js GET /api/metrics

The Prometheus helpers (parseMetrics, fetchMetrics, metricVal, metricSum) were extracted into lib/metrics.js.

app.js now contains only: Express setup, Helmet CSP, session middleware, static file serving, router mounts, 404 handler, global error handler, and app.listen.


A β€” Pagination on /users and /channels

Both routes now load 50 records per page. getAllUsersWithRoles() and getAllChannels() accept { page, perPage } and return { rows, total }. The /api/ variants expose total, page, perPage, and pages in their JSON response.

For /channels, pagination only applies to Master and above (non-Master users see all their own channels, volumes are low).


B β€” Search/filter on /users

A filter bar with a free-text input (?q=) is now displayed above the users table. The search filters on nickname and username via a LIKE query. Pagination preserves the active search term across pages. The count badge updates to reflect the filtered total.


C β€” Cache getKnownChannelRelatedTables()

This function was running a full information_schema.tables query on every channel detail page load. It now caches its result in memory with a 5-minute TTL. The schema does not change at runtime, so the cache is effectively always valid in normal operation.


D β€” Session user refresh on permission change

Previously, a level change in the DB (e.g. promoting a user from User to Master via IRC) required the affected user to log out and back in to see their new permissions in the web console.

requireLogin now triggers a silent refreshSessionUser() call at most once every 2 minutes per session. If the DB profile has changed, the session is rebuilt and saved transparently. The request is never blocked β€” the refresh is fire-and-forget.


F β€” CSRF token on the login form

GET /login now generates a 32-byte hex token using Node.js native crypto, stores it in req.session._csrf, and injects it as a hidden field in the form. POST /login validates the token via a csrfMiddleware before any authentication logic runs. A missing or mismatched token redirects back to the login page with an error. The token is deleted from the session on successful login (one-time use). No external dependency β€” crypto is built into Node.js.


Status after round 3

# Item Status
B1 /channels missing try/catch βœ… fixed
B2 fmtUptime French suffixes βœ… fixed
B3 lang="fr" in HTML βœ… fixed
i18n Remaining French strings βœ… done
R9 app.js β†’ 9 route files + lib/metrics.js βœ… done
A Pagination on /users and /channels βœ… done
B Search/filter on /users βœ… done
C Cache getKnownChannelRelatedTables() βœ… done
D Session user refresh on permission change βœ… done
F CSRF token on login form βœ… done

Remaining long-term items: EJS migration (R12), CSRF on other forms if any are added, Matrix/Discord integration stubs.

You must be logged in to reply.