diff --git a/src/main/java/org/example/projektarendehantering/application/service/DocumentService.java b/src/main/java/org/example/projektarendehantering/application/service/DocumentService.java
index f08e89f..c787e8b 100644
--- a/src/main/java/org/example/projektarendehantering/application/service/DocumentService.java
+++ b/src/main/java/org/example/projektarendehantering/application/service/DocumentService.java
@@ -164,6 +164,9 @@ public S3Resource downloadDocument(Actor actor, UUID documentId) {
@Transactional
public void deleteDocument(Actor actor, UUID documentId) {
+ if (actor.isPatient()) {
+ throw new NotAuthorizedException("Patients are not allowed to delete documents");
+ }
DocumentEntity entity = documentRepository.findById(documentId)
.orElseThrow(() -> new BadRequestException("Document not found"));
@@ -215,6 +218,8 @@ private void validateAccess(Actor actor, CaseEntity caseEntity) {
if (actor.isManager()) return;
if (actor.isDoctor() && actor.userId().equals(caseEntity.getOwnerId())) return;
if (actor.isNurse() && actor.userId().equals(caseEntity.getHandlerId())) return;
+ if (actor.isPatient() && caseEntity.getPatient() != null
+ && actor.userId().equals(caseEntity.getPatient().getId())) return;
throw new NotAuthorizedException("Not authorized to access documents for this case");
}
}
diff --git a/src/main/resources/templates/cases/detail.html b/src/main/resources/templates/cases/detail.html
index a997963..cb21737 100644
--- a/src/main/resources/templates/cases/detail.html
+++ b/src/main/resources/templates/cases/detail.html
@@ -103,7 +103,8 @@
Documents
Date
-
diff --git a/src/test/java/org/example/projektarendehantering/application/service/DocumentServiceTest.java b/src/test/java/org/example/projektarendehantering/application/service/DocumentServiceTest.java
index b59b564..680806b 100644
--- a/src/test/java/org/example/projektarendehantering/application/service/DocumentServiceTest.java
+++ b/src/test/java/org/example/projektarendehantering/application/service/DocumentServiceTest.java
@@ -9,6 +9,7 @@
import org.example.projektarendehantering.infrastructure.persistence.CaseRepository;
import org.example.projektarendehantering.infrastructure.persistence.DocumentEntity;
import org.example.projektarendehantering.infrastructure.persistence.DocumentRepository;
+import org.example.projektarendehantering.infrastructure.persistence.PatientEntity;
import org.example.projektarendehantering.presentation.dto.DocumentDTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -22,6 +23,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
+import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -50,23 +52,30 @@ class DocumentServiceTest {
private Actor doctorActor;
private Actor managerActor;
+ private Actor patientActor;
private UUID caseId;
private CaseEntity caseEntity;
@BeforeEach
void setUp() {
ReflectionTestUtils.setField(documentService, "bucket", "test-bucket");
-
+
UUID doctorId = UUID.randomUUID();
UUID managerId = UUID.randomUUID();
+ UUID patientId = UUID.randomUUID();
doctorActor = new Actor(doctorId, Role.DOCTOR, "Doctor", "doctor_user");
managerActor = new Actor(managerId, Role.MANAGER, "Manager", "manager_user");
+ patientActor = new Actor(patientId, Role.PATIENT, "Patient", "patient_user");
+
+ PatientEntity patient = new PatientEntity();
+ patient.setId(patientId);
caseId = UUID.randomUUID();
caseEntity = new CaseEntity();
caseEntity.setId(caseId);
caseEntity.setOwnerId(doctorId);
+ caseEntity.setPatient(patient);
}
@Test
@@ -130,4 +139,52 @@ void deleteDocument_shouldAllowOwner() {
verify(s3Template).deleteObject(eq("test-bucket"), eq("some-key"));
verify(documentRepository).delete(docEntity);
}
+
+ @Test
+ void uploadDocument_shouldAllowPatientOnOwnCase() throws IOException {
+ MockMultipartFile file = new MockMultipartFile("file", "test.txt", "text/plain", "hello".getBytes());
+ when(caseRepository.findById(caseId)).thenReturn(Optional.of(caseEntity));
+ when(documentRepository.save(any(DocumentEntity.class))).thenAnswer(i -> {
+ DocumentEntity e = i.getArgument(0);
+ e.setId(UUID.randomUUID());
+ return e;
+ });
+ when(documentMapper.toDTO(any(DocumentEntity.class))).thenReturn(
+ new DocumentDTO(UUID.randomUUID(), "test.txt", "text/plain", 5, Instant.now(), patientActor.userId(), caseId));
+
+ DocumentDTO result = documentService.uploadDocument(patientActor, caseId, file);
+
+ assertThat(result).isNotNull();
+ verify(s3Template).upload(eq("test-bucket"), anyString(), any(InputStream.class), any(ObjectMetadata.class));
+ }
+
+ @Test
+ void uploadDocument_shouldDenyPatientOnOtherCase() {
+ Actor otherPatient = new Actor(UUID.randomUUID(), Role.PATIENT, "Other", "other_patient");
+ MockMultipartFile file = new MockMultipartFile("file", "test.txt", "text/plain", "hello".getBytes());
+ when(caseRepository.findById(caseId)).thenReturn(Optional.of(caseEntity));
+
+ assertThatThrownBy(() -> documentService.uploadDocument(otherPatient, caseId, file))
+ .isInstanceOf(NotAuthorizedException.class);
+ }
+
+ @Test
+ void listDocuments_shouldAllowPatientOnOwnCase() {
+ when(caseRepository.findById(caseId)).thenReturn(Optional.of(caseEntity));
+ when(documentRepository.findAllByCaseEntityId(caseId)).thenReturn(List.of());
+
+ documentService.listDocuments(patientActor, caseId);
+
+ verify(documentRepository).findAllByCaseEntityId(caseId);
+ }
+
+ @Test
+ void deleteDocument_shouldDenyPatient() {
+ UUID docId = UUID.randomUUID();
+
+ assertThatThrownBy(() -> documentService.deleteDocument(patientActor, docId))
+ .isInstanceOf(NotAuthorizedException.class);
+
+ verify(documentRepository, never()).findById(any());
+ }
}