Commit Graph
5 Commits
Author SHA1 Message Date
Claude 3df521ac30 Revue complète : sécurité, optimisations et UI/UX mobile
Sécurité
- JWT : un JWT_SECRET d'exemple ou trop court est ignoré au profit d'un
  secret aléatoire conservé en base (avant, la valeur publique de
  docker-compose.yml permettait de forger un jeton admin).
- Le compte est relu en base à chaque requête : désactivation, changement
  de rôle et réinitialisation du mot de passe prennent effet immédiatement.
- Connexion : 10 échecs max par e-mail / 15 min, temps constant que l'e-mail
  existe ou non, mot de passe admin retiré des logs.
- Validation des entrées (ids, dates, mois, longueurs, e-mail) : 400 au
  lieu de 500. Un admin ne peut plus se désactiver ni se rétrograder.
- Mots de passe : 8 caractères minimum ; changement en libre-service.
- Export : nom de fichier conforme RFC 5987 (un nom de société avec « — »
  faisait planter l'export).
- esc() échappe aussi les guillemets (injection d'attributs HTML).
- En-têtes CSP / X-Frame-Options / nosniff (Nginx + API), API et Postgres
  publiés sur 127.0.0.1 seulement, image backend non-root via npm ci.

Optimisations
- Export : une requête pour tout le mois au lieu d'une par cadre.
- Saisie groupée : un seul INSERT (unnest), doublons dédupliqués.
- Dates renvoyées en chaînes (plus de décalage d'un jour selon le TZ).
- Planning : chaque clic met à jour l'affichage localement au lieu de
  recharger le mois ; les réponses de mois périmées sont ignorées.
- Recherche Utilisateurs / Plannings filtrée localement (plus une requête
  par touche) ; statuts des sociétés chargés en parallèle.

UI/UX
- Mobile : toutes les destinations dans la barre basse (Sociétés et Ma
  saisie étaient inaccessibles à l'admin) ; tableaux affichés en cartes
  (les boutons d'action étaient hors écran).
- Boutons désactivés pendant l'envoi, focus et Échap dans les dialogues,
  retour à l'écran de connexion quand la session est révoquée, erreurs
  d'export affichées au lieu d'un fichier JSON téléchargé, actions
  destructives signalées, confirmation avant désactivation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5Bdayziw6tybgqETZoNSt
2026-10-09 07:17:54 +00:00
Claude ac5f5133da Empêcher le navigateur de mélanger un index.html neuf et un app.js en cache
Symptôme observé en production : après mise à jour, l'application restait
vide et aucune requête /api/ n'était émise. Le navigateur avait rechargé
index.html et les feuilles de style (nouveaux noms de fichiers) mais
servait app.js depuis son cache — la version précédente, qui référence
des identifiants disparus du nouveau balisage. Le script levait
« Cannot read properties of null » à l'évaluation et s'arrêtait avant
d'enregistrer ses gestionnaires et d'appeler boot().

index.html, app.js et les CSS gardant le même nom d'une version à
l'autre, ils sont désormais servis avec Cache-Control: no-cache : le
navigateur peut toujours les mettre en cache mais doit les revalider, ce
qui coûte un 304 quand rien n'a changé. Les polices, stables et
volumineuses, gardent un cache long.

Vérifié en simulant un redéploiement dans un navigateur au cache chaud :
app.js est revalidé et la nouvelle version prise en compte. Suite E2E
toujours à 62/62.
2026-08-03 18:13:47 +00:00
Claude 441a1758a5 Fix: la résolution DNS dynamique du nginx frontend écrasait le chemin de l'API
Avec un proxy_pass entièrement basé sur une variable, nginx ne remplace
plus le préfixe de location par le reste de l'URI comme il le fait pour
une valeur statique : toutes les requêtes /api/* étaient réécrites en
exactement /api/ (sans /auth/login, /users, etc.), d'où les 404 sur
toutes les routes. Fix : $request_uri est maintenant explicitement
ajouté au proxy_pass pour transmettre le chemin et la query string
d'origine.

Reproduit et vérifié avec un vrai nginx local + un faux backend qui
échoue le chemin reçu : le bug était bien présent avec l'ancienne
config, et absent avec la nouvelle.
2026-07-06 14:49:23 +00:00
Claude 0c438275b5 Éviter les collisions DNS sur le réseau partagé + ne plus crasher sur erreur DB
- Renomme les services (db/backend/frontend -> presencia-db/
  presencia-backend/presencia-frontend) : sur le réseau externe partagé
  nginx_default, un nom générique comme "db" peut entrer en collision
  avec un service du même nom dans une autre stack, et Docker résout
  alors le nom en round-robin vers le mauvais container. Confirmé en
  prod : le bootstrap réussissait puis une requête suivante échouait
  avec une erreur d'authentification alors que le mot de passe était
  correct.
- nginx résout maintenant le backend dynamiquement (resolver + variable)
  au lieu de résoudre une seule fois au démarrage, pour survivre à une
  recréation du container backend.
- Ajoute express-async-errors : une erreur dans une route async (ex. la
  requête pg qui échoue) était une rejection non gérée et faisait
  planter tout le process Node au lieu de renvoyer une 500 propre.
  Testé en local : avant le fix, une erreur d'auth pg tuait le process ;
  après le fix, il répond 500 et reste opérationnel.
2026-07-06 09:26:28 +00:00
Claude a73ab28fae Ajout de l'application Presencia (gestion des présences multi-sociétés)
Application complète : API Node/Express + PostgreSQL, frontend HTML/JS
mono-page, et déploiement Docker sur ports non standards (8781/4790/6543).

- Cadres : calendrier mensuel, saisie de présence par demi-journée
  (présent/absent/congé/RTT), validation de fin de mois qui verrouille
  leurs propres saisies.
- Admin : gestion des sociétés et utilisateurs (rattachement société <->
  cadre), consultation de tous les plannings, validation d'une société
  entière une fois tous ses cadres validés, réouverture en cas de
  correction, export PDF et Excel par société/mois.
2026-07-04 20:41:27 +00:00