feat: PG session store via connect-pg-simple (src/middleware/session.js)

This commit is contained in:
2026-05-30 15:34:50 +03:00
parent 289e7cd751
commit f4c9983612
4 changed files with 79 additions and 14 deletions
+60
View File
@@ -0,0 +1,60 @@
/**
* src/middleware/session.js — конфигурация express-session.
*
* Стор выбирается по наличию пула БД:
* - pool передан → connect-pg-simple (PG): сессии переживают рестарт, работают
* на нескольких подах.
* - pool не передан → MemoryStore: только для юнит-тестов (не требует БД).
*
* Таблица session создаётся автоматически connect-pg-simple при первом старте
* (createTableIfMissing: true). SQL-схема совместима с PostgreSQL 9.6+.
*
* Экспортирует одну функцию: createSessionMiddleware(pool) → express middleware.
*/
'use strict';
const session = require('express-session');
const ConnectPgSimple = require('connect-pg-simple');
const SESSION_MAX_AGE = 8 * 60 * 60 * 1000; // 8 часов, в мс
/**
* Создаёт и возвращает сконфигурированный express-session middleware.
* @param {import('pg').Pool|null} pool — pg Pool; null → MemoryStore (тесты)
* @returns {import('express').RequestHandler}
*/
function createSessionMiddleware(pool) {
const store = pool ? buildPgStore(pool) : undefined; // undefined → MemoryStore
return session({
store,
secret: process.env.SESSION_SECRET || 'dev-session-secret-change-me',
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production', // HTTPS only в проде
sameSite: 'lax',
maxAge: SESSION_MAX_AGE,
},
});
}
/**
* Создаёт connect-pg-simple Store поверх переданного пула.
* Таблица `session` создаётся автоматически если отсутствует.
* @param {import('pg').Pool} pool
* @returns {session.Store}
*/
function buildPgStore(pool) {
const PgSession = ConnectPgSimple(session);
return new PgSession({
pool,
createTableIfMissing: true,
// Автоочистка протухших сессий раз в час (прунинг не блокирует запросы).
pruneSessionInterval: 60 * 60, // секунды
});
}
module.exports = { createSessionMiddleware };