From 687a7e8d3fa4258fc8b63b4ed1a5d6902e6c5850 Mon Sep 17 00:00:00 2001
From: Jessie Ragot <jessie.ragot@hotmail.com>
Date: Thu, 6 Mar 2025 16:45:55 +0100
Subject: [PATCH] Change of MedicalFile to secure routes and ensure that
 authenticated patients can only see their medical records and doctors can see
 all MedicalFiles.

---
 ....java => DoctorMedicalFileController.java} | 44 +++++------
 .../PatientMedicalFileController.java         | 73 +++++++++++++++++++
 .../repositories/MedicalFileRepository.java   |  3 +
 .../services/MedicalFileService.java          |  4 +
 .../resources/templates/appointments.html     |  1 -
 .../resources/templates/doctor-dashboard.html |  3 +-
 ...l-files.html => medical-files-doctor.html} |  7 +-
 .../templates/medical-files-patient.html      | 55 ++++++++++++++
 .../templates/patient-dashboard.html          |  6 +-
 ...ile.html => view-medical-file-doctor.html} | 11 +--
 10 files changed, 167 insertions(+), 40 deletions(-)
 rename src/main/java/com/projet/projetIndu/controllers/{MedicalFileController.java => DoctorMedicalFileController.java} (80%)
 create mode 100644 src/main/java/com/projet/projetIndu/controllers/PatientMedicalFileController.java
 rename src/main/resources/templates/{medical-files.html => medical-files-doctor.html} (82%)
 create mode 100644 src/main/resources/templates/medical-files-patient.html
 rename src/main/resources/templates/{view-medical-file.html => view-medical-file-doctor.html} (84%)

diff --git a/src/main/java/com/projet/projetIndu/controllers/MedicalFileController.java b/src/main/java/com/projet/projetIndu/controllers/DoctorMedicalFileController.java
similarity index 80%
rename from src/main/java/com/projet/projetIndu/controllers/MedicalFileController.java
rename to src/main/java/com/projet/projetIndu/controllers/DoctorMedicalFileController.java
index c8bad47..6adfe0d 100644
--- a/src/main/java/com/projet/projetIndu/controllers/MedicalFileController.java
+++ b/src/main/java/com/projet/projetIndu/controllers/DoctorMedicalFileController.java
@@ -13,17 +13,16 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import java.io.IOException;
 import java.time.LocalDate;
-import java.util.List;
 import java.util.Optional;
 
 @Controller
-@RequestMapping("/medical-files")
-public class MedicalFileController {
+@RequestMapping("/doctors/medical-files-doctor")
+public class DoctorMedicalFileController {
 
     private final MedicalFileService medicalFileService;
     private final MedicalDocumentRepository medicalDocumentRepository;
 
-    public MedicalFileController(MedicalFileService medicalFileService, MedicalDocumentRepository medicalDocumentRepository) {
+    public DoctorMedicalFileController(MedicalFileService medicalFileService, MedicalDocumentRepository medicalDocumentRepository) {
         this.medicalFileService = medicalFileService;
         this.medicalDocumentRepository = medicalDocumentRepository;
     }
@@ -31,29 +30,27 @@ public class MedicalFileController {
     // Afficher tous les dossiers médicaux
     @GetMapping
     public String listMedicalFiles(Model model) {
-        List<MedicalFile> medicalFiles = medicalFileService.getAllMedicalFiles();
-        System.out.println("Dossiers médicaux récupérés : " + medicalFiles.size());
-        model.addAttribute("medicalFiles", medicalFiles);
-        return "medical-files";
+        model.addAttribute("medicalFiles", medicalFileService.getAllMedicalFiles());
+        return "medical-files-doctor";
     }
 
-
     // Afficher un dossier médical spécifique
     @GetMapping("/{id}")
     public String viewMedicalFile(@PathVariable Long id, Model model) {
-        return medicalFileService.getMedicalFileById(id)
-                .map(medicalFile -> {
-                    model.addAttribute("medicalFile", medicalFile);
-                    return "view-medical-file";
-                })
-                .orElse("error");
+        MedicalFile medicalFile = medicalFileService.getMedicalFileById(id).orElse(null);
+        if (medicalFile != null) {
+            model.addAttribute("medicalFile", medicalFile);
+            return "view-medical-file-doctor";
+        }
+        model.addAttribute("errorMessage", "Dossier introuvable.");
+        return "error";
     }
 
     // Créer un dossier médical
     @PostMapping("/create")
     public String createMedicalFile(@ModelAttribute MedicalFile medicalFile) {
         medicalFileService.saveMedicalFiles(medicalFile);
-        return "redirect:/medical-files";
+        return "redirect:/doctors/medical-files-doctor";
     }
 
     // Mettre à jour l'historique médical
@@ -63,10 +60,9 @@ public class MedicalFileController {
                                            @RequestParam String notes,
                                            @RequestParam LocalDate consultationDate) {
         medicalFileService.updateMedicalFileHistory(id, antecedent, notes, consultationDate);
-        return "redirect:/medical-files/" + id;
+        return "redirect:/doctors/medical-files-doctor/" + id;
     }
 
-
     // Ajouter un document à un dossier médical
     @PostMapping("/{id}/documents")
     public String uploadMedicalFileDocument(@PathVariable Long id, @RequestParam("document") MultipartFile document, RedirectAttributes redirectAttributes) {
@@ -75,12 +71,11 @@ public class MedicalFileController {
         } catch (IOException e) {
             e.printStackTrace();
             redirectAttributes.addFlashAttribute("errorMessage", "Erreur lors de l'upload du document.");
-            return "redirect:/medical-files/" + id;
+            return "redirect:/doctors/medical-files-doctor/" + id;
         }
-        return "redirect:/medical-files/" + id;
+        return "redirect:/doctors/medical-files-doctor/" + id;
     }
 
-
     // Télécharger un document médical
     @GetMapping("/{id}/documents/{docId}")
     @ResponseBody
@@ -100,7 +95,6 @@ public class MedicalFileController {
         }
     }
 
-
     // Supprimer un document médical
     @DeleteMapping("/{id}/documents/{docId}")
     public String deleteDocument(@PathVariable Long id, @PathVariable Long docId, RedirectAttributes redirectAttributes) {
@@ -113,10 +107,9 @@ public class MedicalFileController {
             redirectAttributes.addFlashAttribute("errorMessage", "Document introuvable.");
         }
 
-        return "redirect:/medical-files/" + id;
+        return "redirect:/doctors/medical-files-doctor/" + id;
     }
 
-
     // Supprimer un dossier médical
     @DeleteMapping("/{id}")
     public String deleteMedicalFile(@PathVariable Long id, RedirectAttributes redirectAttributes) {
@@ -126,7 +119,6 @@ public class MedicalFileController {
         } catch (Exception e) {
             redirectAttributes.addFlashAttribute("errorMessage", "Erreur lors de la suppression du dossier médical.");
         }
-        return "redirect:/medical-files";
+        return "redirect:/doctors/medical-files-doctor";
     }
-
 }
diff --git a/src/main/java/com/projet/projetIndu/controllers/PatientMedicalFileController.java b/src/main/java/com/projet/projetIndu/controllers/PatientMedicalFileController.java
new file mode 100644
index 0000000..f47af20
--- /dev/null
+++ b/src/main/java/com/projet/projetIndu/controllers/PatientMedicalFileController.java
@@ -0,0 +1,73 @@
+package com.projet.projetIndu.controllers;
+
+import com.projet.projetIndu.entities.MedicalDocument;
+import com.projet.projetIndu.entities.MedicalFile;
+import com.projet.projetIndu.entities.Patient;
+import com.projet.projetIndu.services.MedicalFileService;
+import com.projet.projetIndu.services.PatientService;
+import org.springframework.http.*;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping("/patients/medical-files-patient")
+public class PatientMedicalFileController {
+
+    private final MedicalFileService medicalFileService;
+    private final PatientService patientService;
+
+    public PatientMedicalFileController(MedicalFileService medicalFileService, PatientService patientService) {
+        this.medicalFileService = medicalFileService;
+        this.patientService = patientService;
+    }
+
+    // Afficher le dossier médical du patient connecté
+    @GetMapping
+    public String viewMedicalFile(Model model) {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        String currentUsername = authentication.getName(); // Récupérer l'email du patient authentifié
+
+        // Récupérer le patient correspondant à cet email
+        Patient patient = patientService.getPatientByEmail(currentUsername).orElse(null);
+
+        if (patient != null) {
+            // Récupérer le dossier médical pour ce patient (un seul dossier par patient)
+            MedicalFile medicalFile = medicalFileService.getMedicalFileByPatientId(patient.getId()).orElse(null);
+
+            if (medicalFile != null) {
+                model.addAttribute("medicalFile", medicalFile);
+                return "medical-files-patient"; // Afficher le dossier médical
+            }
+        }
+
+        model.addAttribute("errorMessage", "Dossier médical introuvable.");
+        return "error"; // Vue d'erreur si aucun dossier n'est trouvé
+    }
+
+
+    // Télécharger un document médical
+    @GetMapping("/{id}/documents/{docId}")
+    @ResponseBody
+    public ResponseEntity<byte[]> getMedicalFileDocument(@PathVariable Long id, @PathVariable Long docId) {
+        try {
+            MedicalDocument document = medicalFileService.getMedicalFileDocument(id, docId);
+
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
+            headers.setContentDisposition(ContentDisposition.attachment()
+                    .filename(document.getFileName())
+                    .build());
+
+            return new ResponseEntity<>(document.getFileData(), headers, HttpStatus.OK);
+        } catch (RuntimeException e) {
+            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
+        }
+    }
+}
+
diff --git a/src/main/java/com/projet/projetIndu/repositories/MedicalFileRepository.java b/src/main/java/com/projet/projetIndu/repositories/MedicalFileRepository.java
index 54f79cc..4841839 100644
--- a/src/main/java/com/projet/projetIndu/repositories/MedicalFileRepository.java
+++ b/src/main/java/com/projet/projetIndu/repositories/MedicalFileRepository.java
@@ -3,6 +3,9 @@ package com.projet.projetIndu.repositories;
 import com.projet.projetIndu.entities.MedicalFile;
 import org.springframework.data.jpa.repository.JpaRepository;
 
+import java.util.Optional;
+
 public interface MedicalFileRepository extends JpaRepository<MedicalFile, Long> {
 
+    Optional<MedicalFile> findByPatientId(Long patientId);
 }
diff --git a/src/main/java/com/projet/projetIndu/services/MedicalFileService.java b/src/main/java/com/projet/projetIndu/services/MedicalFileService.java
index a789dea..89d02c2 100644
--- a/src/main/java/com/projet/projetIndu/services/MedicalFileService.java
+++ b/src/main/java/com/projet/projetIndu/services/MedicalFileService.java
@@ -110,6 +110,10 @@ public class MedicalFileService {
                 .orElseThrow(() -> new RuntimeException("Document introuvable."));
     }
 
+    public Optional<MedicalFile> getMedicalFileByPatientId(Long patientId) {
+        return medicalFileRepository.findByPatientId(patientId);
+    }
+
 
 }
 
diff --git a/src/main/resources/templates/appointments.html b/src/main/resources/templates/appointments.html
index f529e14..cafccf1 100644
--- a/src/main/resources/templates/appointments.html
+++ b/src/main/resources/templates/appointments.html
@@ -39,7 +39,6 @@
     </table>
 
     <a href="/doctors/appointments/create" class="btn btn-primary mt-3">Créer un nouveau rendez-vous</a>
-    <a href="/doctors/dashboard" class="btn btn-secondary mt-3">Retour au tableau de bord</a>
 </div>
 
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
diff --git a/src/main/resources/templates/doctor-dashboard.html b/src/main/resources/templates/doctor-dashboard.html
index 6927532..b31bed1 100644
--- a/src/main/resources/templates/doctor-dashboard.html
+++ b/src/main/resources/templates/doctor-dashboard.html
@@ -31,7 +31,8 @@
                 <p class="mt-2 text-gray-600">Consulter et gérer la liste de vos patients.</p>
             </a>
 
-            <a href="/medical-files" class="p-6 bg-white shadow-md rounded-lg hover:shadow-lg transition">
+            <a href="/doctors/medical-files-doctor"
+               class="p-6 bg-white shadow-md rounded-lg hover:shadow-lg transition">
                 <h3 class="text-xl font-semibold text-gray-800">Dossiers Médicaux</h3>
                 <p class="mt-2 text-gray-600">Accéder aux dossiers médicaux de vos patients.</p>
             </a>
diff --git a/src/main/resources/templates/medical-files.html b/src/main/resources/templates/medical-files-doctor.html
similarity index 82%
rename from src/main/resources/templates/medical-files.html
rename to src/main/resources/templates/medical-files-doctor.html
index 368bb30..e660738 100644
--- a/src/main/resources/templates/medical-files.html
+++ b/src/main/resources/templates/medical-files-doctor.html
@@ -4,8 +4,7 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Liste des dossiers médicaux</title>
-    <link rel="stylesheet"
-          href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
 </head>
 <body class="bg-light">
 
@@ -39,13 +38,13 @@
             </td>
 
             <td>
-                <a th:href="@{/medical-files/{id}(id=${file.id})}" class="btn btn-info">Consulter</a>
+                <a th:href="@{/doctors/medical-files-doctor/{id}(id=${file.id})}" class="btn btn-info">Consulter</a>
             </td>
         </tr>
         </tbody>
     </table>
 
-    <a href="/" class="btn btn-primary mt-3">Retour à l'accueil</a>
+    <a href="/doctors/dashboard" class="btn btn-primary mt-3">Retour à l'accueil</a>
 </div>
 
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
diff --git a/src/main/resources/templates/medical-files-patient.html b/src/main/resources/templates/medical-files-patient.html
new file mode 100644
index 0000000..77e6507
--- /dev/null
+++ b/src/main/resources/templates/medical-files-patient.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Mon Dossier Médical</title>
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
+</head>
+<body class="bg-light">
+
+<div class="container mt-5">
+    <h1 class="text-center mb-4">Mon Dossier Médical</h1>
+
+    <div th:if="${medicalFile}">
+        <h5 class="card-title">Dossier médical de :
+            <span th:text="${medicalFile.patient != null ? medicalFile.patient.firstName : 'Inconnu'}"></span>
+            <span th:text="${medicalFile.patient != null ? medicalFile.patient.lastName : ''}"></span>
+        </h5>
+
+        <!-- Historique médical -->
+        <div class="mt-3">
+            <h5>Historique médical :</h5>
+            <ul class="list-group">
+                <li th:each="history : ${medicalFile.healthHistoricalList}" class="list-group-item">
+                    <strong>Antécédent:</strong> <span th:text="${history.antecedent}"></span><br>
+                    <strong>Notes:</strong> <span th:text="${history.notes}"></span><br>
+                    <strong>Date de consultation:</strong> <span th:text="${history.consultationDate}"></span>
+                </li>
+            </ul>
+        </div>
+
+        <!-- Liste des documents avec lien de téléchargement -->
+        <div class="mt-3">
+            <h5>Documents disponibles :</h5>
+            <ul class="list-group">
+                <li th:each="doc : ${medicalFile.documentList}"
+                    class="list-group-item d-flex justify-content-between align-items-center">
+                    <span th:text="${doc.fileName}"></span>
+                    <div>
+                        <a th:href="@{/patients/medical-files-patient/{id}/documents/{docId}(id=${medicalFile.id}, docId=${doc.id})}"
+                           class="btn btn-sm btn-warning">
+                            Télécharger
+                        </a>
+                    </div>
+                </li>
+            </ul>
+        </div>
+    </div>
+
+    <a href="/patients/dashboard" class="btn btn-primary mt-3">Retour à l'accueil</a>
+</div>
+
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
+</body>
+</html>
diff --git a/src/main/resources/templates/patient-dashboard.html b/src/main/resources/templates/patient-dashboard.html
index ebb9bf3..78819ac 100644
--- a/src/main/resources/templates/patient-dashboard.html
+++ b/src/main/resources/templates/patient-dashboard.html
@@ -24,9 +24,9 @@
             <p class="mt-2 text-gray-600">Voir les informations de votre médecin.</p>
         </a>
 
-        <a href="/medical-files" class="p-6 bg-white shadow-md rounded-lg hover:shadow-lg transition">
-            <h3 class="text-xl font-semibold text-gray-800">Mes Dossiers Médicaux</h3>
-            <p class="mt-2 text-gray-600">Consulter vos dossiers médicaux.</p>
+        <a href="/patients/medical-files-patient" class="p-6 bg-white shadow-md rounded-lg hover:shadow-lg transition">
+            <h3 class="text-xl font-semibold text-gray-800">Mon Dossier Médical</h3>
+            <p class="mt-2 text-gray-600">Consulter votre dossier médical.</p>
         </a>
 
         <a href="/patients/appointments" class="p-6 bg-white shadow-md rounded-lg hover:shadow-lg transition">
diff --git a/src/main/resources/templates/view-medical-file.html b/src/main/resources/templates/view-medical-file-doctor.html
similarity index 84%
rename from src/main/resources/templates/view-medical-file.html
rename to src/main/resources/templates/view-medical-file-doctor.html
index b336c37..b53f4c0 100644
--- a/src/main/resources/templates/view-medical-file.html
+++ b/src/main/resources/templates/view-medical-file-doctor.html
@@ -31,7 +31,8 @@
     </div>
 
     <!-- Formulaire de téléchargement du document -->
-    <form method="post" th:action="@{/medical-files/{id}/documents(id=${medicalFile.id})}" enctype="multipart/form-data"
+    <form method="post" th:action="@{/doctors/medical-files-doctor/{id}/documents(id=${medicalFile.id})}"
+          enctype="multipart/form-data"
           class="mt-3">
         <label for="file" class="form-label">Importer un document :</label>
         <input type="file" name="document" id="file" class="form-control mb-2"/>
@@ -46,11 +47,11 @@
                 class="list-group-item d-flex justify-content-between align-items-center">
                 <span th:text="${doc.fileName}"></span>
                 <div>
-                    <a th:href="@{/medical-files/{id}/documents/{docId}(id=${medicalFile.id}, docId=${doc.id})}"
+                    <a th:href="@{/doctors/medical-files-doctor/{id}/documents/{docId}(id=${medicalFile.id}, docId=${doc.id})}"
                        class="btn btn-sm btn-warning">
                         Télécharger
                     </a>
-                    <form th:action="@{/medical-files/{id}/documents/{docId}(id=${medicalFile.id}, docId=${doc.id})}"
+                    <form th:action="@{/doctors/medical-files-doctor/{id}/documents/{docId}(id=${medicalFile.id}, docId=${doc.id})}"
                           method="post" class="d-inline">
                         <input type="hidden" name="_method" value="delete"/>
                         <button type="submit" class="btn btn-sm btn-danger"
@@ -63,9 +64,9 @@
         </ul>
     </div>
 
-    <a href="/medical-files" class="btn btn-primary mt-3">Retour à la liste</a>
+    <a href="/doctors/medical-files-doctor" class="btn btn-primary mt-3">Retour à la liste</a>
 </div>
 
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
 </body>
-</html>
\ No newline at end of file
+</html>
-- 
GitLab