89 lines
3.2 KiB
JavaScript
89 lines
3.2 KiB
JavaScript
// Authentication route registration for the web app.
|
|
|
|
const { normalizeReturnToPath, getRequestOrigin } = require('../../lib/auth/session');
|
|
|
|
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 consumeAuthMessageCookie = deps.consumeAuthMessageCookie;
|
|
const setAuthMessageCookie = deps.setAuthMessageCookie;
|
|
const hashSessionToken = deps.hashSessionToken;
|
|
const verifyPassword = deps.verifyPassword;
|
|
const sessionCookieName = deps.sessionCookieName;
|
|
|
|
function getReturnTo(req) {
|
|
return normalizeReturnToPath(req && (req.query && req.query.returnTo || req.body && req.body.returnTo), getRequestOrigin(req));
|
|
}
|
|
|
|
function buildLoginRedirect(returnTo) {
|
|
return returnTo ? '/login?returnTo=' + encodeURIComponent(returnTo) : '/login';
|
|
}
|
|
|
|
app.get('/', function (req, res) {
|
|
res.redirect(req.currentUser ? '/dashboard' : '/login');
|
|
});
|
|
|
|
app.get('/login', function (req, res) {
|
|
const returnTo = getReturnTo(req);
|
|
if (req.currentUser) {
|
|
return res.redirect(returnTo || '/dashboard');
|
|
}
|
|
|
|
const message = typeof consumeAuthMessageCookie === 'function'
|
|
? consumeAuthMessageCookie(req, res)
|
|
: (req.query.message ? String(req.query.message) : '');
|
|
res.send(pages.renderLoginPage(message, returnTo));
|
|
});
|
|
|
|
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 a_users WHERE username = ? LIMIT 1', [username]);
|
|
const user = rows[0] || null;
|
|
if (!user || !verifyPassword(password, user)) {
|
|
const returnTo = getReturnTo(req);
|
|
if (typeof setAuthMessageCookie === 'function') {
|
|
setAuthMessageCookie(res, 'Invalid username or password.');
|
|
return res.redirect(buildLoginRedirect(returnTo));
|
|
}
|
|
|
|
return res.status(401).send(pages.renderLoginPage('Invalid username or password.', returnTo));
|
|
}
|
|
|
|
const returnTo = getReturnTo(req);
|
|
const token = await createUserSession(pool, user.id);
|
|
setSessionCookie(res, token);
|
|
res.redirect(returnTo || '/dashboard');
|
|
} 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 a_sessions WHERE session_hash = ?', [hashSessionToken(token)]);
|
|
}
|
|
clearSessionCookie(res);
|
|
if (typeof setAuthMessageCookie === 'function') {
|
|
setAuthMessageCookie(res, 'You have been signed out.');
|
|
return res.redirect('/login');
|
|
}
|
|
|
|
res.redirect('/login');
|
|
} catch (error) {
|
|
next(error);
|
|
}
|
|
});
|
|
}; |