feat: BizGaze Connect home, BizGaze login, modular backend, /api/v1
User-facing - New post-login home (/home): chat rail + Share/Connect (embedded) + Meeting; login lives here when logged out - Landing: "Log in with BizGaze" + no-login screen share - Console replaced by a role-scoped Dashboard (/dashboard): admins see all team sessions, others see only their own; stats + CSV/PDF export - Recordings saved as MP4 (H.264/AAC) with WebM fallback; old .webm still downloadable - Fix: duplicate "Sign in" on the login card Auth / integration - BizGaze as identity provider: /api/login validates against BIZGAZE_LOGIN_URL (env-gated) and provisions a local user - Phase 2 start: /api/v1 alias for all /api routes; Authorization: Bearer accepted across HTTP + WS; login returns a token (for native desktop/mobile clients) Backend refactor (Phase 1, behavior-preserving) - Split server.js into config/lib/session/presence/routes/static/signaling + repos (data-access) + bizgaze (service) - All SQL behind repos.js, tenant-scoped (tenantId == team_id for now) - e2e updated to current flow (21/21 pass before and after) Docs: ARCHITECTURE.md (target architecture + phased plan), CLAUDE.md repo layout, .env.example BIZGAZE_LOGIN_URL Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
// 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 <token>` → 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 };
|
||||
Reference in New Issue
Block a user