costco-grocery-list/backend/models/session.model.js

57 lines
1.4 KiB
JavaScript

const crypto = require("crypto");
const pool = require("../db/pool");
const { SESSION_TTL_DAYS } = require("../utils/session-cookie");
function generateSessionId() {
if (typeof crypto.randomUUID === "function") {
return crypto.randomUUID().replace(/-/g, "") + crypto.randomBytes(8).toString("hex");
}
return crypto.randomBytes(32).toString("hex");
}
exports.createSession = async (userId, userAgent = null) => {
const id = generateSessionId();
const result = await pool.query(
`INSERT INTO sessions (id, user_id, expires_at, user_agent)
VALUES ($1, $2, NOW() + ($3 || ' days')::interval, $4)
RETURNING id, user_id, created_at, expires_at`,
[id, userId, String(SESSION_TTL_DAYS), userAgent]
);
return result.rows[0];
};
exports.getActiveSessionWithUser = async (sessionId) => {
const result = await pool.query(
`SELECT
s.id,
s.user_id,
s.expires_at,
u.username,
u.role
FROM sessions s
JOIN users u ON u.id = s.user_id
WHERE s.id = $1
AND s.expires_at > NOW()`,
[sessionId]
);
const session = result.rows[0] || null;
if (!session) return null;
await pool.query(
`UPDATE sessions
SET last_seen_at = NOW()
WHERE id = $1`,
[sessionId]
);
return session;
};
exports.deleteSession = async (sessionId) => {
await pool.query(
`DELETE FROM sessions WHERE id = $1`,
[sessionId]
);
};