enchant-workflow-and-auth #1

Merged
meb merged 6 commits from enchant-betterworkflow into main 2026-04-21 20:39:11 +00:00
5 changed files with 96 additions and 26 deletions
Showing only changes of commit e43c330594 - Show all commits

View File

@@ -33,23 +33,34 @@ async function register(username, password) {
* Esegue il login di un utente * Esegue il login di un utente
*/ */
async function login(username, password) { async function login(username, password) {
console.log('[DEBUG AUTH] login() START - username:', username);
const result = await query('SELECT id, username, password_hash, created_at FROM users WHERE username = $1', [username]); const result = await query('SELECT id, username, password_hash, created_at FROM users WHERE username = $1', [username]);
console.log('[DEBUG AUTH] login() - query result rows:', result.rows.length);
if (result.rows.length === 0) { if (result.rows.length === 0) {
console.log('[DEBUG AUTH] login() - user not found');
throw new Error('No user matched') throw new Error('No user matched')
} }
const user = result.rows[0]; const user = result.rows[0];
console.log('[DEBUG AUTH] login() - user found:', { id: user.id, username: user.username });
const isValid = await security.verifyPassword(password, user.password_hash); const isValid = await security.verifyPassword(password, user.password_hash);
console.log('[DEBUG AUTH] login() - password valid:', isValid);
if (!isValid) { if (!isValid) {
console.log('[DEBUG AUTH] login() - password mismatch');
throw new Error('Password mismatch') throw new Error('Password mismatch')
} }
return { const result_obj = {
id: user.id, id: user.id,
username: user.username, username: user.username,
created: user.created_at created: user.created_at
} };
console.log('[DEBUG AUTH] login() SUCCESS - returning user:', result_obj);
return result_obj;
} }
/** /**
@@ -69,38 +80,61 @@ async function logout(sessionID) {
* Crea una nuova sessione per un utente che ha appaena eseguito il login * Crea una nuova sessione per un utente che ha appaena eseguito il login
*/ */
async function newSession(userId, userAgent, ip) { async function newSession(userId, userAgent, ip) {
console.log('[DEBUG AUTH] newSession() START - userId:', userId);
const id = uuid(); const id = uuid();
const sessionCode = security.generateSessionCode(); const sessionCode = security.generateSessionCode();
const metadata = track.getBasicMetadata(userAgent); const metadata = track.getBasicMetadata(userAgent);
console.log('[DEBUG AUTH] newSession() - sessionCode generated:', sessionCode, 'metadata:', metadata);
await query( const insertResult = await query(
`INSERT INTO sessions (id, user_id, session_code, encoded_username, ip_address, user_agent, browser, os, device_type) `INSERT INTO sessions (id, user_id, session_code, encoded_username, ip_address, user_agent, browser, os, device_type)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
[id, userId, sessionCode, '', ip, userAgent, metadata.browser, metadata.os, metadata.device_type] [id, userId, sessionCode, '', ip, userAgent, metadata.browser, metadata.os, metadata.device_type]
); );
console.log('[DEBUG AUTH] newSession() - INSERT result:', { rowCount: insertResult.rowCount });
return { id, sessionCode }; const result = { id, sessionCode };
console.log('[DEBUG AUTH] newSession() SUCCESS - returning:', result);
return result;
} }
/** /**
* Valida una sessione tramite il suo UUID * Valida una sessione tramite il suo UUID
*/ */
async function validateSession(sessionId) { async function validateSession(sessionId) {
console.log('[DEBUG AUTH] validateSession() START - sessionId:', sessionId);
if (!sessionId || typeof sessionId !== 'string') { if (!sessionId || typeof sessionId !== 'string') {
console.log('[DEBUG AUTH] validateSession() - invalid sessionId type');
throw new Error('Invalid session ID'); throw new Error('Invalid session ID');
} }
const result = await query( console.log('[DEBUG AUTH] validateSession() - executing query with sessionId:', sessionId);
'SELECT s.id, u.is_active FROM sessions s JOIN users u ON s.user_id = u.id WHERE s.id = $1 AND s.is_revoked = FALSE',
[sessionId] try {
); const result = await query(
'SELECT s.id, u.is_active FROM sessions s JOIN users u ON s.user_id = u.id WHERE s.id = $1 AND s.is_revoked = FALSE',
[sessionId]
);
console.log('[DEBUG AUTH] validateSession() - query SUCCESS, rows:', result.rows.length);
if (result.rows.length === 0) { if (result.rows.length === 0) {
throw new Error('Session not found or revoked'); console.log('[DEBUG AUTH] validateSession() - session not found or revoked');
} throw new Error('Session not found or revoked');
}
if (!result.rows[0].is_active) { console.log('[DEBUG AUTH] validateSession() - row data:', result.rows[0]);
throw new Error('User account is not active');
if (!result.rows[0].is_active) {
console.log('[DEBUG AUTH] validateSession() - user not active');
throw new Error('User account is not active');
}
console.log('[DEBUG AUTH] validateSession() SUCCESS');
} catch (err) {
console.error('[DEBUG AUTH] validateSession() ERROR:', err.message, err.code);
throw err;
} }
} }

View File

@@ -134,7 +134,11 @@ app.use((req, res) => {
// ─── ERROR HANDLER GLOBALE ────────────────────────────────────────── // ─── ERROR HANDLER GLOBALE ──────────────────────────────────────────
app.use((err, req, res, _next) => { app.use((err, req, res, _next) => {
console.error('[AUTH] Errore non gestito:', err); console.error('[ERROR HANDLER] Global error caught:');
console.error('[ERROR HANDLER] Message:', err.message);
console.error('[ERROR HANDLER] Code:', err.code);
console.error('[ERROR HANDLER] Full error:', err);
console.error('[ERROR HANDLER] Stack:', err.stack);
res.status(500).json({ error: 'Errore interno del server' }); res.status(500).json({ error: 'Errore interno del server' });
}); });

View File

@@ -2,9 +2,13 @@ const jwt = require('../tools/jwt');
const { validateSession } = require('../core/auth.core'); const { validateSession } = require('../core/auth.core');
const userAuth = async (req, res, next) => { const userAuth = async (req, res, next) => {
console.log('[DEBUG MIDDLEWARE] userAuth() START - path:', req.path);
const token = (req.cookies && req.cookies.auth_token) || jwt.getToken(req.headers['authorization']); const token = (req.cookies && req.cookies.auth_token) || jwt.getToken(req.headers['authorization']);
console.log('[DEBUG MIDDLEWARE] token found:', !!token);
const redirectToLogin = () => { const redirectToLogin = () => {
console.log('[DEBUG MIDDLEWARE] redirectToLogin()');
if (req.accepts('html')) { if (req.accepts('html')) {
const redirect = encodeURIComponent(req.originalUrl); const redirect = encodeURIComponent(req.originalUrl);
return res.redirect(`/login?redirect=${redirect}`); return res.redirect(`/login?redirect=${redirect}`);
@@ -13,15 +17,20 @@ const userAuth = async (req, res, next) => {
}; };
if (!token || typeof token !== 'string') { if (!token || typeof token !== 'string') {
console.log('[DEBUG MIDDLEWARE] no token or invalid type');
return redirectToLogin(); return redirectToLogin();
} }
if (token.length > 2048) { if (token.length > 2048) {
console.log('[DEBUG MIDDLEWARE] token too long');
return redirectToLogin(); return redirectToLogin();
} }
const verified = jwt.verifyToken(token); const verified = jwt.verifyToken(token);
console.log('[DEBUG MIDDLEWARE] jwt.verifyToken() result - valid:', verified.valid);
if (!verified.valid) { if (!verified.valid) {
console.log('[DEBUG MIDDLEWARE] token not valid - reason:', verified.reason);
if (req.accepts('html')) { if (req.accepts('html')) {
return res.redirect('/login'); return res.redirect('/login');
} }
@@ -32,8 +41,11 @@ const userAuth = async (req, res, next) => {
} }
try { try {
console.log('[DEBUG MIDDLEWARE] calling validateSession() with session_id:', verified.payload.session_id);
await validateSession(verified.payload.session_id); await validateSession(verified.payload.session_id);
} catch { console.log('[DEBUG MIDDLEWARE] validateSession() SUCCESS');
} catch (err) {
console.error('[DEBUG MIDDLEWARE] validateSession() FAILED:', err.message);
if (req.accepts('html')) { if (req.accepts('html')) {
return res.redirect('/login'); return res.redirect('/login');
} }
@@ -41,6 +53,7 @@ const userAuth = async (req, res, next) => {
} }
req.user = verified.payload; req.user = verified.payload;
console.log('[DEBUG MIDDLEWARE] auth SUCCESS - user_id:', req.user.user_id);
next(); next();
}; };

View File

@@ -84,9 +84,12 @@ router.post('/login', async (req, res) => {
} }
try { try {
const user = await auth.login(username, password); console.log('[DEBUG ROUTES] POST /api/auth/login START - username:', username);\n
const session = await auth.newSession(user.id, req.headers['user-agent'], req.ip); const user = await auth.login(username, password);\n console.log('[DEBUG ROUTES] auth.login() success - user:', user);
const token = jwt.generateToken(user, session.id);
const session = await auth.newSession(user.id, req.headers['user-agent'], req.ip);\n console.log('[DEBUG ROUTES] auth.newSession() success - session:', session);
const token = jwt.generateToken(user, session.id);\n console.log('[DEBUG ROUTES] jwt.generateToken() success');
const cookieOptions = { const cookieOptions = {
httpOnly: true, httpOnly: true,
@@ -101,12 +104,12 @@ router.post('/login', async (req, res) => {
res.cookie('auth_token', token, cookieOptions); res.cookie('auth_token', token, cookieOptions);
res.clearCookie('_csrf'); res.clearCookie('_csrf');
console.log('[DEBUG ROUTES] cookies set - redirecting to:', safeRedirect || CONSOLE_URL);
const destination = safeRedirect || CONSOLE_URL; const destination = safeRedirect || CONSOLE_URL;
res.redirect(destination); res.redirect(destination);
} catch (err) { } catch (err) {
console.error('[AUTH] Login failed:', err.message); console.error('[DEBUG ROUTES] Login FAILED:', err.message, err.code, err);\n return loginRedirect('invalid_credentials', safeRedirect);
return loginRedirect('invalid_credentials', safeRedirect);
} }
}); });

View File

@@ -24,14 +24,30 @@ pool.on('error', (err) => {
*/ */
async function query(text, params) { async function query(text, params) {
const start = Date.now(); const start = Date.now();
const result = await pool.query(text, params); console.log('[DEBUG DB] Executing query:', text.substring(0, 120));
const duration = Date.now() - start; if (params && params.length > 0) {
console.log('[DEBUG DB] Parameters:', params);
if (duration > 100) {
console.warn(`[DB] Slow query (${duration}ms):`, text.substring(0, 80));
} }
try {
const result = await pool.query(text, params);
const duration = Date.now() - start;
return result; if (duration > 100) {
console.warn(`[DB] Slow query (${duration}ms):`, text.substring(0, 80));
}
console.log('[DEBUG DB] Query successful - rows:', result.rowCount, 'duration:', duration + 'ms');
return result;
} catch (err) {
const duration = Date.now() - start;
console.error('[DEBUG DB] Query FAILED:', err.message);
console.error('[DEBUG DB] Error code:', err.code);
console.error('[DEBUG DB] Query:', text.substring(0, 120));
console.error('[DEBUG DB] Duration:', duration + 'ms');
console.error('[DEBUG DB] Full error:', err);
throw err;
}
} }
/** /**