// Session/auth helpers: resolve the current user from the cookie, write audit rows. const R = require('./repos'); const { parseCookies, now } = require('./lib'); function audit(entry) { R.audit.add(entry); } // Resolve the session token from a request, supporting every client transport: // - `Authorization: Bearer ` → native desktop/mobile apps (HTTP + WS upgrade) // - `sid` cookie → the web app (HTTP + same-origin WS) // - `?access_token=`/`?token=` query → browser WS fallback when a cookie isn't usable // All three resolve to the same opaque token in `sessions_auth`. function tokenFromReq(req) { const h = req.headers && (req.headers.authorization || req.headers.Authorization); if (h && /^Bearer\s+/i.test(h)) return h.replace(/^Bearer\s+/i, '').trim(); const cookieTok = parseCookies(req).sid; if (cookieTok) return cookieTok; try { const qs = (req.url || '').split('?')[1]; if (qs) { const t = new URLSearchParams(qs).get('access_token') || new URLSearchParams(qs).get('token'); if (t) return t; } } catch (_) {} return null; } // Resolve the logged-in user from the request. Returns user row (with mfa state) or null. function currentUser(req, { requireMfa = true } = {}) { const tok = tokenFromReq(req); if (!tok) return null; const s = R.authSessions.byToken(tok); if (!s || s.expires_at < now()) return null; if (requireMfa && !s.mfa_passed) return null; const u = R.users.byId(s.user_id); if (!u || u.active === 0) return null; return { ...u, _session: s }; } module.exports = { audit, currentUser, tokenFromReq };