This PR breaks the large web and player bootstrap files into smaller modules with clearer ownership.
Web changes: Split shared helpers, bootstrap logic, route groups, and upload-sync behavior out of web.js. Kept web.js focused on wiring and server startup. Fixed screen playlist reassignment so changing a screen’s playlist now triggers a refresh. Fixed single-slide playlist refresh behavior so updates do not get stuck behind the current slide. Player changes: Split websocket/runtime handling into runtime.js. Split playlist assembly and revision hashing into playlist.js. Split onboarding and player HTTP routes into dedicated modules. Split render utilities and template loading into render-helpers.js. Kept player.js mostly as startup/orchestration. Validation: Rebuilt both services with Docker Compose. Smoke-checked web and player routes after the refactor. Verified get_errors was clean on the touched modules.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
module.exports = function registerAuthRoutes(app, deps) {
|
||||
const pool = deps.pool;
|
||||
const pages = deps.pages;
|
||||
const createUserSession = deps.createUserSession;
|
||||
const setSessionCookie = deps.setSessionCookie;
|
||||
const clearSessionCookie = deps.clearSessionCookie;
|
||||
const parseCookies = deps.parseCookies;
|
||||
const hashSessionToken = deps.hashSessionToken;
|
||||
const verifyPassword = deps.verifyPassword;
|
||||
const sessionCookieName = deps.sessionCookieName;
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.redirect(req.currentUser ? '/admin' : '/login');
|
||||
});
|
||||
|
||||
app.get('/login', function (req, res) {
|
||||
if (req.currentUser) {
|
||||
return res.redirect('/admin');
|
||||
}
|
||||
res.send(pages.renderLoginPage(req.query.message ? String(req.query.message) : ''));
|
||||
});
|
||||
|
||||
app.post('/login', async function (req, res, next) {
|
||||
try {
|
||||
const username = String(req.body.username || '').trim();
|
||||
const password = String(req.body.password || '');
|
||||
if (!username || !password) {
|
||||
return res.status(400).send('Username and password are required.');
|
||||
}
|
||||
|
||||
const [rows] = await pool.query('SELECT id, name, username, password_hash, password_salt, password_iterations FROM users WHERE username = ? LIMIT 1', [username]);
|
||||
const user = rows[0] || null;
|
||||
if (!user || !verifyPassword(password, user)) {
|
||||
return res.redirect('/login?message=' + encodeURIComponent('Invalid username or password.'));
|
||||
}
|
||||
|
||||
const token = await createUserSession(pool, user.id);
|
||||
setSessionCookie(res, token);
|
||||
res.redirect('/admin');
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/logout', async function (req, res, next) {
|
||||
try {
|
||||
const cookies = parseCookies(req.headers.cookie || '');
|
||||
const token = cookies[sessionCookieName];
|
||||
if (token) {
|
||||
await pool.query('DELETE FROM auth_sessions WHERE session_hash = ?', [hashSessionToken(token)]);
|
||||
}
|
||||
clearSessionCookie(res);
|
||||
res.redirect('/login?message=' + encodeURIComponent('You have been signed out.'));
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user