Release 2.8.0
This commit is contained in:
@@ -34,6 +34,8 @@ function normalizeReturnToPath(value, baseUrl) {
|
||||
function createSessionService(options) {
|
||||
const sessionCookieName = String(options && options.sessionCookieName || '').trim();
|
||||
const sessionMaxAgeMs = Number(options && options.sessionMaxAgeMs);
|
||||
const getConfiguredSessionMaxAgeMs = options && options.getConfiguredSessionMaxAgeMs;
|
||||
const getConfiguredMaxActiveSessions = options && options.getConfiguredMaxActiveSessions;
|
||||
const hashSessionToken = options && options.hashSessionToken;
|
||||
const createSessionToken = options && options.createSessionToken;
|
||||
const authMessageCookieName = 'pulse_auth_message';
|
||||
@@ -88,7 +90,20 @@ function createSessionService(options) {
|
||||
}
|
||||
|
||||
function setSessionCookie(res, token) {
|
||||
appendCookieHeader(res, serializeCookie(sessionCookieName, token, { maxAge: sessionMaxAgeMs }));
|
||||
const hasRequestedMaxAge = arguments.length > 2;
|
||||
const requestedMaxAgeMs = hasRequestedMaxAge ? Number(arguments[2]) : sessionMaxAgeMs;
|
||||
const cookieOptions = hasRequestedMaxAge && arguments[2] === null
|
||||
? {}
|
||||
: { maxAge: Number.isFinite(requestedMaxAgeMs) && requestedMaxAgeMs > 0 ? requestedMaxAgeMs : sessionMaxAgeMs };
|
||||
appendCookieHeader(res, serializeCookie(sessionCookieName, token, cookieOptions));
|
||||
}
|
||||
|
||||
async function getSessionMaxAgeMs() {
|
||||
const configuredValue = typeof getConfiguredSessionMaxAgeMs === 'function'
|
||||
? await getConfiguredSessionMaxAgeMs()
|
||||
: sessionMaxAgeMs;
|
||||
const normalizedValue = Number(configuredValue);
|
||||
return Number.isFinite(normalizedValue) && normalizedValue > 0 ? normalizedValue : sessionMaxAgeMs;
|
||||
}
|
||||
|
||||
function setAuthMessageCookie(res, message) {
|
||||
@@ -113,7 +128,7 @@ function createSessionService(options) {
|
||||
|
||||
const tokenHash = hashSessionToken(token);
|
||||
const [rows] = await pool.query(
|
||||
`SELECT s.user_id, u.id, u.name, u.username
|
||||
`SELECT s.user_id, u.id, u.name, u.username, u.must_change_password
|
||||
FROM a_sessions s
|
||||
JOIN a_users u ON u.id = s.user_id
|
||||
WHERE s.session_hash = ?
|
||||
@@ -146,6 +161,7 @@ function createSessionService(options) {
|
||||
|
||||
await pool.query('UPDATE a_sessions SET last_used_at = CURRENT_TIMESTAMP, modified_by = ? WHERE session_hash = ?', [rows[0].user_id, tokenHash]);
|
||||
return Object.assign({}, rows[0], {
|
||||
mustChangePassword: Boolean(rows[0].must_change_password),
|
||||
roleKeys: roleRows.map(function (row) {
|
||||
return String(row.role_key || '').trim();
|
||||
}).filter(Boolean),
|
||||
@@ -155,14 +171,34 @@ function createSessionService(options) {
|
||||
});
|
||||
}
|
||||
|
||||
async function createUserSession(pool, userId) {
|
||||
async function createUserSession(pool, userId, configuredMaxAgeMs, metadata) {
|
||||
const token = createSessionToken();
|
||||
const tokenHash = hashSessionToken(token);
|
||||
const expiresAt = new Date(Date.now() + sessionMaxAgeMs);
|
||||
const maxAgeMs = Number.isFinite(Number(configuredMaxAgeMs)) && Number(configuredMaxAgeMs) > 0
|
||||
? Number(configuredMaxAgeMs)
|
||||
: await getSessionMaxAgeMs();
|
||||
const expiresAt = new Date(Date.now() + maxAgeMs);
|
||||
const sessionMetadata = metadata && typeof metadata === 'object' ? metadata : {};
|
||||
await pool.query(
|
||||
'INSERT INTO a_sessions (session_hash, user_id, expires_at, created_by, modified_by) VALUES (?, ?, ?, ?, ?)',
|
||||
[tokenHash, userId, expiresAt, userId, userId]
|
||||
'INSERT INTO a_sessions (session_hash, user_id, ip_address, user_agent, expires_at, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
[tokenHash, userId, String(sessionMetadata.ipAddress || '').slice(0, 255) || null, String(sessionMetadata.userAgent || '').slice(0, 512) || null, expiresAt, userId, userId]
|
||||
);
|
||||
|
||||
if (typeof getConfiguredMaxActiveSessions === 'function') {
|
||||
const maxActiveSessions = Number(await getConfiguredMaxActiveSessions());
|
||||
if (Number.isInteger(maxActiveSessions) && maxActiveSessions > 0) {
|
||||
const [sessionRows] = await pool.query(
|
||||
'SELECT id, session_hash FROM a_sessions WHERE user_id = ? AND expires_at > NOW() ORDER BY last_used_at ASC, created_at ASC, id ASC',
|
||||
[userId]
|
||||
);
|
||||
const sessionsToRemove = (sessionRows || []).filter(function (session) {
|
||||
return session.session_hash !== tokenHash;
|
||||
}).slice(0, Math.max(0, sessionRows.length - maxActiveSessions));
|
||||
for (const session of sessionsToRemove) {
|
||||
await pool.query('DELETE FROM a_sessions WHERE id = ? AND user_id = ?', [session.id, userId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -184,6 +220,7 @@ function createSessionService(options) {
|
||||
consumeAuthMessageCookie: consumeAuthMessageCookie,
|
||||
loadCurrentUser: loadCurrentUser,
|
||||
createUserSession: createUserSession,
|
||||
getSessionMaxAgeMs: getSessionMaxAgeMs,
|
||||
requireAuth: requireAuth,
|
||||
getRequestOrigin: getRequestOrigin
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user