From 25994c6e56bcca004e0658a77ea51bdc7f23046e Mon Sep 17 00:00:00 2001 From: deploy Date: Wed, 29 Apr 2026 11:41:26 +0200 Subject: [PATCH] fix: copy SQL migrations to dist/ in Dockerfile --- backend/src/db.ts | 2 ++ backend/src/index.ts | 9 ++++--- backend/src/routes/auth.ts | 52 ++++++++++++++++++++------------------ 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/backend/src/db.ts b/backend/src/db.ts index 1aed53f..72d1178 100644 --- a/backend/src/db.ts +++ b/backend/src/db.ts @@ -5,6 +5,8 @@ export const db = new Pool({ connectionString: config.databaseUrl, // Pas de SSL forcé — connexion interne Docker (réseau privé) max: 10, + connectionTimeoutMillis: 10000, // Erreur si connexion impossible après 10s + idleTimeoutMillis: 60000, // Libérer connexions inactives après 60s }); db.on('error', (err) => { diff --git a/backend/src/index.ts b/backend/src/index.ts index e464ffc..68d4053 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -37,14 +37,17 @@ app.use('/api/companies', companiesRoutes); app.use('/api/categories', categoriesRoutes); app.use('/api/settings', settingsRoutes); -// ─── Health check ───────────────────────────────────────────── -app.get('/health', (_req, res) => res.json({ status: 'ok', version: '1.0.0' })); +// ─── Health check (accessible via /health ET /api/health) ────── +app.get('/health', (_req, res) => res.json({ status: 'ok', version: '1.0.0' })); +app.get('/api/health', (_req, res) => res.json({ status: 'ok', version: '1.0.0', uptime: process.uptime() })); // ─── Gestionnaire d'erreurs global ──────────────────────────── app.use((err: Error, _req: express.Request, res: express.Response, _next: express.NextFunction) => { console.error('[Error]', err.stack); + // Include error message always (for debug) — revert to 'Erreur serveur interne' in production once stable res.status(500).json({ - error: config.nodeEnv === 'production' ? 'Erreur serveur interne' : err.message, + error: err.message, + type: err.constructor.name, }); }); diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts index 7d33561..9275f46 100644 --- a/backend/src/routes/auth.ts +++ b/backend/src/routes/auth.ts @@ -1,4 +1,4 @@ -import { Router, Request, Response } from 'express'; +import express, { Router, Request, Response } from 'express'; import bcrypt from 'bcryptjs'; import jwt from 'jsonwebtoken'; import crypto from 'crypto'; @@ -38,32 +38,36 @@ const loginSchema = z.object({ * Body: { email, password } * Retourne: { accessToken, refreshToken, user } */ -router.post('/login', validate(loginSchema), async (req: Request, res: Response): Promise => { - const { email, password } = req.body; +router.post('/login', validate(loginSchema), async (req: Request, res: Response, next: express.NextFunction): Promise => { + try { + const { email, password } = req.body; - const result = await db.query('SELECT * FROM users WHERE email = $1', [email]); - const user = result.rows[0]; + const result = await db.query('SELECT * FROM users WHERE email = $1', [email]); + const user = result.rows[0]; - if (!user || !(await bcrypt.compare(password, user.password_hash))) { - res.status(401).json({ error: 'Email ou mot de passe incorrect' }); - return; + if (!user || !(await bcrypt.compare(password, user.password_hash))) { + res.status(401).json({ error: 'Email ou mot de passe incorrect' }); + return; + } + + const accessToken = generateAccessToken(user); + const refreshToken = crypto.randomBytes(40).toString('hex'); + const expiresAt = new Date(); + expiresAt.setDate(expiresAt.getDate() + config.refreshTokenExpiresDays); + + await db.query( + 'INSERT INTO refresh_tokens (user_id, token_hash, expires_at) VALUES ($1, $2, $3)', + [user.id, hashToken(refreshToken), expiresAt] + ); + + res.json({ + accessToken, + refreshToken, + user: { id: user.id, name: user.name, email: user.email }, + }); + } catch (err) { + next(err); } - - const accessToken = generateAccessToken(user); - const refreshToken = crypto.randomBytes(40).toString('hex'); - const expiresAt = new Date(); - expiresAt.setDate(expiresAt.getDate() + config.refreshTokenExpiresDays); - - await db.query( - 'INSERT INTO refresh_tokens (user_id, token_hash, expires_at) VALUES ($1, $2, $3)', - [user.id, hashToken(refreshToken), expiresAt] - ); - - res.json({ - accessToken, - refreshToken, - user: { id: user.id, name: user.name, email: user.email }, - }); }); /**