"use strict"; const { UnauthorizedError } = require("../../errors"); const SESSION_COOKIE = "kadr_session"; function sessionCookieOptions(ttlMs = 7 * 24 * 60 * 60 * 1000) { return { httpOnly: true, sameSite: "lax", path: "/", maxAge: ttlMs, }; } function parseCookies(cookieHeader) { const cookies = {}; if (!cookieHeader) return cookies; const pairs = cookieHeader.split(";"); for (const pair of pairs) { const idx = pair.indexOf("="); if (idx < 0) continue; const key = pair.slice(0, idx).trim(); const val = pair.slice(idx + 1).trim(); try { cookies[key] = decodeURIComponent(val); } catch { cookies[key] = val; } } return cookies; } function readSessionToken(req) { const cookieHeader = req.headers.cookie; if (!cookieHeader) return null; const cookies = parseCookies(cookieHeader); return cookies[SESSION_COOKIE] || null; } function createAuthMiddleware(sessionStore) { return { requireAuth(req, res, next) { const token = readSessionToken(req); if (!token) { return next(new UnauthorizedError("Требуется авторизация.")); } const session = sessionStore.get(token); if (!session) { return next(new UnauthorizedError("Сессия истекла или не найдена.")); } req.user = session.user; req.sessionToken = token; // Sliding TTL: refresh cookie res.cookie(SESSION_COOKIE, token, sessionCookieOptions(sessionStore.ttlMs)); next(); }, optionalAuth(req, res, next) { const token = readSessionToken(req); if (token) { const session = sessionStore.get(token); if (session) { req.user = session.user; req.sessionToken = token; res.cookie(SESSION_COOKIE, token, sessionCookieOptions(sessionStore.ttlMs)); } } next(); }, }; } module.exports = { SESSION_COOKIE, sessionCookieOptions, readSessionToken, createAuthMiddleware, };