From 43f573854554eb3ed6cc2d1b10cdaaad05788a88 Mon Sep 17 00:00:00 2001 From: Imer ouijdane Date: Thu, 6 Aug 2026 09:45:23 +0200 Subject: [PATCH] Fix formateur login/visibility, docker build, and calendar refresh bugs - Correct system diagnostic to check v_Formateurs_CD (the view actually used) instead of the nonexistent v_Formateurs_CD_Declarations, which was forcing the backend into degraded legacy_hash mode and blocking all formateurs except the hardcoded special case. - Add .dockerignore to frontend/backend so the Windows-installed node_modules doesn't overwrite the container's npm install (was causing "vite: not found"). - Fetch declarations with cache: 'no-store' and await the save callback so the calendar reflects a new entry without a page reload. - Add docker-compose.prod.yml using published Docker Hub images. --- GTF/docker-compose.prod.yml | 33 +++++++++++++++++++ GTF/project/.dockerignore | 3 ++ GTF/project/backend/.dockerignore | 2 ++ GTF/project/backend/config/server.js | 4 +-- GTF/project/src/App.tsx | 2 +- GTF/project/src/components/TimeEntryModal.tsx | 4 +-- 6 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 GTF/docker-compose.prod.yml create mode 100644 GTF/project/.dockerignore create mode 100644 GTF/project/backend/.dockerignore diff --git a/GTF/docker-compose.prod.yml b/GTF/docker-compose.prod.yml new file mode 100644 index 00000000..0e4aa274 --- /dev/null +++ b/GTF/docker-compose.prod.yml @@ -0,0 +1,33 @@ +version: "3.9" + +services: + backend: + image: ouijdaneim/gtf-backend:latest + ports: + - "8000:3000" + environment: + - DB_SERVER=192.168.0.3 + - DB_DATABASE=GTF + - DB_USER=gtf_app + - DB_PASSWORD=GTF2025!Secure + - DB_ENCRYPT=true + - DB_TRUST_SERVER_CERTIFICATE=true + - PORT=3000 + extra_hosts: + - "BONEMINE:192.168.0.3" + - "bonemine.ensup.local:192.168.0.3" + restart: unless-stopped + + frontend: + image: ouijdaneim/gtf-frontend:latest + ports: + - "3001:3001" + volumes: + # Chemin du certificat HTTPS sur l'HÔTE DE PROD — à adapter s'il diffère de ce poste + - C:\Users\oimer\.aspnet\https:/https:ro + environment: + - ASPNETCORE_URLS=https://+:3001;http://+:3001 + - ASPNETCORE_Kestrel__Certificates__Default__Password=tGTF2025 + - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx + - VITE_API_BASE_URL=https://mygtf.ensup-adm.net:8000 + restart: unless-stopped diff --git a/GTF/project/.dockerignore b/GTF/project/.dockerignore new file mode 100644 index 00000000..a21f178d --- /dev/null +++ b/GTF/project/.dockerignore @@ -0,0 +1,3 @@ +node_modules +dist +.git diff --git a/GTF/project/backend/.dockerignore b/GTF/project/backend/.dockerignore new file mode 100644 index 00000000..651665bb --- /dev/null +++ b/GTF/project/backend/.dockerignore @@ -0,0 +1,2 @@ +node_modules +.git diff --git a/GTF/project/backend/config/server.js b/GTF/project/backend/config/server.js index 43eb6e64..a14f4288 100644 --- a/GTF/project/backend/config/server.js +++ b/GTF/project/backend/config/server.js @@ -64,13 +64,13 @@ async function checkSystemStatus() { const viewCheck = await pool.request().query(` SELECT COUNT(*) AS count FROM INFORMATION_SCHEMA.VIEWS - WHERE TABLE_NAME = 'v_Formateurs_CD_Declarations' + WHERE TABLE_NAME = 'v_Formateurs_CD' `); systemStatus.hasFormateurView = viewCheck.recordset[0].count > 0; if (systemStatus.hasFormateurView) { try { - await pool.request().query(`SELECT TOP 1 userPrincipalName FROM dbo.v_Formateurs_CD_Declarations`); + await pool.request().query(`SELECT TOP 1 userPrincipalName FROM dbo.v_Formateurs_CD`); systemStatus.canAccessFormateurView = true; } catch { systemStatus.canAccessFormateurView = false; diff --git a/GTF/project/src/App.tsx b/GTF/project/src/App.tsx index 7e78ed85..7b9700b9 100644 --- a/GTF/project/src/App.tsx +++ b/GTF/project/src/App.tsx @@ -25,7 +25,7 @@ function App() { return; } - const response = await fetch(`/api/get_declarations_by_email?email=${encodeURIComponent(user.email)}`); + const response = await fetch(`/api/get_declarations_by_email?email=${encodeURIComponent(user.email)}`, { cache: 'no-store' }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); diff --git a/GTF/project/src/components/TimeEntryModal.tsx b/GTF/project/src/components/TimeEntryModal.tsx index 133fde53..46d8be78 100644 --- a/GTF/project/src/components/TimeEntryModal.tsx +++ b/GTF/project/src/components/TimeEntryModal.tsx @@ -7,7 +7,7 @@ interface TimeEntryModalProps { date: string; entries: TimeEntry[]; onClose: () => void; - onSave: () => void; + onSave: () => void | Promise; } const TimeEntryModal: React.FC = ({ @@ -215,7 +215,7 @@ const TimeEntryModal: React.FC = ({ return; } - onSave(); + await onSave(); resetForm(); if (entries.length === 0) { onClose();