feat(users): refactor users system

This commit is contained in:
2026-04-19 16:42:33 -04:00
parent af8da2aa86
commit f08376d979
24 changed files with 1531 additions and 669 deletions
+1 -138
View File
@@ -1,138 +1 @@
/**
* Session Management
* Handles user session creation, validation, and deletion
*/
import { create, findOne, deleteWhere, updateById } from '@zen/core/database';
import { generateToken, generateId } from './password.js';
/**
* Create a new session for a user
* @param {string} userId - User ID
* @param {Object} options - Session options (ipAddress, userAgent)
* @returns {Promise<Object>} Session object with token
*/
async function createSession(userId, options = {}) {
const { ipAddress, userAgent } = options;
// Generate session token
const token = generateToken(32);
const sessionId = generateId();
// Session expires in 30 days
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + 30);
const session = await create('zen_auth_sessions', {
id: sessionId,
user_id: userId,
token,
expires_at: expiresAt,
ip_address: ipAddress || null,
user_agent: userAgent || null,
updated_at: new Date()
});
return session;
}
/**
* Validate a session token
* @param {string} token - Session token
* @returns {Promise<Object|null>} Session object with user data or null if invalid
*/
async function validateSession(token) {
if (!token) return null;
const session = await findOne('zen_auth_sessions', { token });
if (!session) return null;
// Check if session is expired
if (new Date(session.expires_at) < new Date()) {
await deleteSession(token);
return null;
}
// Get user data
const user = await findOne('zen_auth_users', { id: session.user_id });
if (!user) {
await deleteSession(token);
return null;
}
// Auto-refresh session if it expires in less than 20 days
const now = new Date();
const expiresAt = new Date(session.expires_at);
const daysUntilExpiry = Math.ceil((expiresAt - now) / (1000 * 60 * 60 * 24));
let sessionRefreshed = false;
if (daysUntilExpiry < 20) {
// Extend session to 30 days from now
const newExpiresAt = new Date();
newExpiresAt.setDate(newExpiresAt.getDate() + 30);
await updateById('zen_auth_sessions', session.id, {
expires_at: newExpiresAt,
updated_at: new Date()
});
// Update the session object with new expiration
session.expires_at = newExpiresAt;
sessionRefreshed = true;
}
return {
session,
user,
sessionRefreshed
};
}
/**
* Delete a session
* @param {string} token - Session token
* @returns {Promise<number>} Number of deleted sessions
*/
async function deleteSession(token) {
return await deleteWhere('zen_auth_sessions', { token });
}
/**
* Delete all sessions for a user
* @param {string} userId - User ID
* @returns {Promise<number>} Number of deleted sessions
*/
async function deleteUserSessions(userId) {
return await deleteWhere('zen_auth_sessions', { user_id: userId });
}
/**
* Refresh a session (extend expiration)
* @param {string} token - Session token
* @returns {Promise<Object|null>} Updated session or null
*/
async function refreshSession(token) {
const session = await findOne('zen_auth_sessions', { token });
if (!session) return null;
// Extend session by 30 days
const expiresAt = new Date();
expiresAt.setDate(expiresAt.getDate() + 30);
return await updateById('zen_auth_sessions', session.id, {
expires_at: expiresAt,
updated_at: new Date()
});
}
export {
createSession,
validateSession,
deleteSession,
deleteUserSessions,
refreshSession
};
export { createSession, validateSession, deleteSession, deleteUserSessions, refreshSession } from '../../../core/users/session.js';