mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-19 13:08:23 +02:00
perf(serveur): réponses API allégées, compression, cache des assets et index
- Fichiers statiques servis avant la session (plus de requêtes SQL par asset), /assets en cache immuable 1 an, index.html en no-cache, et compression gzip/brotli des réponses (dépendance compression, externe dans le bundle esbuild du Dockerfile). - req.user (déjà chargé par deserializeUser) réutilisé dans les handlers au lieu de relire l'utilisateur et ses magasins à chaque appel ; GET /api/user ne refait plus de requête. - Listes : le magasin joint est réduit aux champs lus par l'interface (plus de logo base64 ni de configuration SMTP/NocoDB dans chaque ligne), plus aucune empreinte de mot de passe dans les créateurs/auteurs ni dans /api/users. - N+1 supprimés (/api/users, annonces, historique SAV, caches de vérification des factures), requêtes indépendantes en parallèle (stats, analytics, météo, getDelivery, getUserWithGroups), jointure multiplicative des statistiques par magasin corrigée. - Échéancier limité au magasin demandé ; filtre status sur GET /api/deliveries. - Index de performance créés en arrière-plan au démarrage (CREATE INDEX CONCURRENTLY, reliquats invalides purgés sans verrou exclusif). - La connexion n'attend plus la sauvegarde quotidienne ; purge du cache des factures active en production ; logs volumineux retirés des chemins chauds ; NODE_ENV fixé dans l'image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MsDJjQrAggcJwbbBtKhgyb
This commit is contained in:
13 files changed
+1113
-1116
No files matched your search
+35
-37
@@ -5,7 +5,7 @@ import session from "express-session";
|
||||
import { scrypt, randomBytes, timingSafeEqual } from "crypto";
|
||||
import { promisify } from "util";
|
||||
import { storage } from "./storage";
|
||||
import { User as SelectUser } from "@shared/schema";
|
||||
import { User as SelectUser, type UserWithGroups } from "@shared/schema";
|
||||
import connectPg from "connect-pg-simple";
|
||||
import { backupService } from "./backupService";
|
||||
|
||||
@@ -141,7 +141,9 @@ export function setupLocalAuth(app: Express) {
|
||||
passport.deserializeUser(async (id: string, done) => {
|
||||
try {
|
||||
const user = await storage.getUserWithGroups(id);
|
||||
done(null, user);
|
||||
// Utilisateur supprimé depuis la connexion : false vide la session (401)
|
||||
// au lieu de l'erreur « Failed to deserialize user out of session » (500)
|
||||
done(null, user || false);
|
||||
} catch (error) {
|
||||
done(error);
|
||||
}
|
||||
@@ -157,20 +159,9 @@ export function setupLocalAuth(app: Express) {
|
||||
return res.status(400).json({ message: info?.message || "Invalid credentials" });
|
||||
}
|
||||
|
||||
req.login(user, async (err) => {
|
||||
req.login(user, (err) => {
|
||||
if (err) return next(err);
|
||||
|
||||
// Vérifier et effectuer une sauvegarde quotidienne si nécessaire
|
||||
try {
|
||||
const backupResult = await backupService.checkAndPerformDailyBackup(user.id);
|
||||
if (backupResult.backupPerformed) {
|
||||
console.log('💾 Sauvegarde quotidienne effectuée lors de la connexion de', user.username);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('⚠️ Erreur lors de la vérification de sauvegarde:', error);
|
||||
// Ne pas faire échouer la connexion si la sauvegarde échoue
|
||||
}
|
||||
|
||||
res.json({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
@@ -180,6 +171,21 @@ export function setupLocalAuth(app: Express) {
|
||||
role: user.role,
|
||||
passwordChanged: user.passwordChanged
|
||||
});
|
||||
|
||||
// Vérifier et effectuer une sauvegarde quotidienne si nécessaire, après
|
||||
// la réponse : la connexion n'attend plus le pg_dump
|
||||
setImmediate(() => {
|
||||
backupService.checkAndPerformDailyBackup(user.id)
|
||||
.then((backupResult) => {
|
||||
if (backupResult.backupPerformed) {
|
||||
console.log('💾 Sauvegarde quotidienne effectuée lors de la connexion de', user.username);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
// Ne pas faire échouer la connexion si la sauvegarde échoue
|
||||
console.error('⚠️ Erreur lors de la vérification de sauvegarde:', error);
|
||||
});
|
||||
});
|
||||
});
|
||||
})(req, res, next);
|
||||
});
|
||||
@@ -201,33 +207,25 @@ export function setupLocalAuth(app: Express) {
|
||||
app.get("/api/logout", logoutHandler);
|
||||
|
||||
// Get current user
|
||||
app.get("/api/user", async (req, res) => {
|
||||
app.get("/api/user", (req, res) => {
|
||||
if (!req.isAuthenticated()) {
|
||||
return res.status(401).json({ message: "Non authentifié" });
|
||||
}
|
||||
|
||||
try {
|
||||
const userId = (req.user as SelectUser).id;
|
||||
const userWithGroups = await storage.getUserWithGroups(userId);
|
||||
|
||||
if (!userWithGroups) {
|
||||
return res.status(404).json({ message: "Utilisateur non trouvé" });
|
||||
}
|
||||
|
||||
res.json({
|
||||
id: userWithGroups.id,
|
||||
username: userWithGroups.username,
|
||||
email: userWithGroups.email,
|
||||
firstName: userWithGroups.firstName,
|
||||
lastName: userWithGroups.lastName,
|
||||
role: userWithGroups.role,
|
||||
passwordChanged: userWithGroups.passwordChanged,
|
||||
userGroups: userWithGroups.userGroups || []
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error fetching user with groups:", error);
|
||||
res.status(500).json({ message: "Erreur lors de la récupération des données utilisateur" });
|
||||
}
|
||||
// req.user est déjà rechargé avec ses magasins par deserializeUser à chaque
|
||||
// requête : inutile de relire l'utilisateur en base
|
||||
const userWithGroups = req.user as UserWithGroups;
|
||||
|
||||
res.json({
|
||||
id: userWithGroups.id,
|
||||
username: userWithGroups.username,
|
||||
email: userWithGroups.email,
|
||||
firstName: userWithGroups.firstName,
|
||||
lastName: userWithGroups.lastName,
|
||||
role: userWithGroups.role,
|
||||
passwordChanged: userWithGroups.passwordChanged,
|
||||
userGroups: userWithGroups.userGroups || []
|
||||
});
|
||||
});
|
||||
|
||||
// Check if default credentials should be shown
|
||||
|
||||
Reference in new issue
Block a user