Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.example.projektarendehantering.infrastructure.persistence.EmployeeRepository;
import org.example.projektarendehantering.infrastructure.persistence.PatientEntity;
import org.example.projektarendehantering.infrastructure.persistence.PatientRepository;
import org.example.projektarendehantering.infrastructure.persistence.UserAccountEntity;
import org.example.projektarendehantering.infrastructure.persistence.UserAccountRepository;
import org.example.projektarendehantering.presentation.dto.CaseAssignmentDTO;
import org.example.projektarendehantering.presentation.dto.CaseDTO;
import org.springframework.http.HttpStatus;
Expand All @@ -39,6 +41,7 @@ public class CaseService {
private final PatientRepository patientRepository;
private final CaseNoteRepository caseNoteRepository;
private final EmployeeRepository employeeRepository;
private final UserAccountRepository userAccountRepository;
private final AuditService auditService;

@Transactional
Expand Down Expand Up @@ -75,23 +78,29 @@ public CaseDTO createCase(Actor actor, CaseDTO caseDTO) {
if (requestedPatientId != null && !actor.userId().equals(requestedPatientId)) {
throw new NotAuthorizedException("Patients can only create cases for themselves");
}
requestedPatientId = actor.userId();
requestedPatientId = null;
}
if (requestedPatientId == null) {
throw new BadRequestException("patientId is required");
if (!isPatient(actor)) {
throw new BadRequestException("patientId is required");
}
}
CaseEntity entity = caseMapper.toEntity(caseDTO);
entity.setId(UUID.randomUUID());
PatientEntity patient = patientRepository.findById(requestedPatientId).orElse(null);
if (patient == null) {
if (isPatient(actor) && actor.userId().equals(requestedPatientId)) {
PatientEntity patient;
if (isPatient(actor)) {
patient = patientRepository.findByUserAccount_Id(actor.userId()).orElseGet(() -> {
UserAccountEntity account = userAccountRepository.findById(actor.userId())
.orElseThrow(() -> new NotAuthorizedException("Patient account not found"));
PatientEntity self = new PatientEntity();
self.setId(requestedPatientId);
self.setId(UUID.randomUUID());
self.setUserAccount(account);
self.setCreatedAt(Instant.now());
patient = patientRepository.save(self);
} else {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Patient not found");
}
return patientRepository.save(self);
});
} else {
patient = patientRepository.findById(requestedPatientId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Patient not found"));
}
entity.setPatient(patient);
if (isDoctor(actor) || isManager(actor)) {
Expand Down Expand Up @@ -198,7 +207,7 @@ public List<CaseDTO> getAllCases(Actor actor) {
.collect(Collectors.toList());
}
if (isPatient(actor)) {
return caseRepository.findAllByPatient_IdAndStatusNot(actor.userId(), CaseStatus.CLOSED).stream()
return caseRepository.findAllByPatient_UserAccount_IdAndStatusNot(actor.userId(), CaseStatus.CLOSED).stream()
.map(caseMapper::toDTO)
.collect(Collectors.toList());
}
Expand Down Expand Up @@ -274,7 +283,7 @@ private void requireCanRead(Actor actor, CaseEntity entity) {
if (isManager(actor)) return;
if (isDoctor(actor) && actor.userId().equals(entity.getOwnerId())) return;
if (isNurse(actor) && actor.userId().equals(entity.getHandlerId())) return;
if (isPatient(actor) && entity.getPatient() != null && actor.userId().equals(entity.getPatient().getId())) return;
if (isPatient(actor) && isActorPatientLinked(actor, entity)) return;
throw new NotAuthorizedException("Not allowed to read this case");
}

Expand Down Expand Up @@ -304,10 +313,16 @@ private boolean canRead(Actor actor, CaseEntity entity) {
if (isManager(actor)) return true;
if (isDoctor(actor) && actor.userId().equals(entity.getOwnerId())) return true;
if (isNurse(actor) && actor.userId().equals(entity.getHandlerId())) return true;
if (isPatient(actor) && entity.getPatient() != null && actor.userId().equals(entity.getPatient().getId())) return true;
if (isPatient(actor) && isActorPatientLinked(actor, entity)) return true;
return false;
}

private boolean isActorPatientLinked(Actor actor, CaseEntity entity) {
return entity.getPatient() != null
&& entity.getPatient().getUserAccount() != null
&& actor.userId().equals(entity.getPatient().getUserAccount().getId());
}

private boolean isManager(Actor actor) {
return actor.role() == Role.MANAGER;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,10 @@ 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;
if (actor.isPatient()
&& caseEntity.getPatient() != null
&& caseEntity.getPatient().getUserAccount() != null
&& actor.userId().equals(caseEntity.getPatient().getUserAccount().getId())) return;
throw new NotAuthorizedException("Not authorized to access documents for this case");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.Locale;
import java.util.UUID;

@Service
@RequiredArgsConstructor
Expand Down Expand Up @@ -59,11 +61,12 @@ public void registerPatient(PatientRegistrationDTO registrationDTO) {
}

PatientEntity patientEntity = new PatientEntity();
patientEntity.setId(savedAccount.getId());
patientEntity.setId(UUID.randomUUID());
patientEntity.setFirstName(firstName);
patientEntity.setLastName(lastName);
patientEntity.setPersonalIdentityNumber(personalIdentityNumber);
patientEntity.setCreatedAt(savedAccount.getCreatedAt());
patientEntity.setUserAccount(savedAccount);
patientEntity.setCreatedAt(savedAccount.getCreatedAt() != null ? savedAccount.getCreatedAt() : Instant.now());

try {
patientRepository.save(patientEntity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public interface CaseRepository extends JpaRepository<CaseEntity, UUID> {
List<CaseEntity> findAllByStatusNot(CaseStatus status);
List<CaseEntity> findAllByPatient_Id(UUID patientId);
List<CaseEntity> findAllByPatient_IdAndStatusNot(UUID patientId, CaseStatus status);
List<CaseEntity> findAllByPatient_UserAccount_IdAndStatusNot(UUID userAccountId, CaseStatus status);
List<CaseEntity> findAllByOwnerId(UUID ownerId);
List<CaseEntity> findAllByOwnerIdAndStatusNot(UUID ownerId, CaseStatus status);
List<CaseEntity> findAllByHandlerId(UUID handlerId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public class PatientEntity {
@Column(unique = true)
private String personalIdentityNumber;

@OneToOne
@JoinColumn(name = "user_account_id", unique = true)
private UserAccountEntity userAccount;

private Instant createdAt;

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@

public interface PatientRepository extends JpaRepository<PatientEntity, UUID> {
Optional<PatientEntity> findByPersonalIdentityNumber(String personalIdentityNumber);
Optional<PatientEntity> findByUserAccount_Id(UUID userAccountId);
}

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class CaseServiceTest {
@Mock
private EmployeeRepository employeeRepository;
@Mock
private UserAccountRepository userAccountRepository;
@Mock
private CaseNoteMapper caseNoteMapper;
@Mock
private AuditService auditService;
Expand Down Expand Up @@ -79,6 +81,9 @@ void setUp() {

PatientEntity patient = new PatientEntity();
patient.setId(patientId);
UserAccountEntity patientUserAccount = new UserAccountEntity();
patientUserAccount.setId(patientId);
patient.setUserAccount(patientUserAccount);
caseEntity.setPatient(patient);
}

Expand Down Expand Up @@ -145,17 +150,22 @@ void createCase_shouldAllowDoctor() {
void createCase_shouldAllowPatientAndForceOwnPatientId() {
CaseDTO dto = new CaseDTO();
PatientEntity patient = new PatientEntity();
patient.setId(patientActor.userId());
patient.setId(UUID.randomUUID());
UserAccountEntity patientUserAccount = new UserAccountEntity();
patientUserAccount.setId(patientActor.userId());
patient.setUserAccount(patientUserAccount);

when(caseMapper.toEntity(dto)).thenReturn(new CaseEntity());
when(patientRepository.findById(patientActor.userId())).thenReturn(Optional.of(patient));
when(patientRepository.findByUserAccount_Id(patientActor.userId())).thenReturn(Optional.of(patient));
when(caseRepository.save(any(CaseEntity.class))).thenAnswer(i -> i.getArgument(0));
when(caseMapper.toDTO(any(CaseEntity.class))).thenReturn(new CaseDTO());

caseService.createCase(patientActor, dto);

verify(patientRepository).findById(patientActor.userId());
verify(caseRepository).save(argThat(saved -> saved.getPatient() != null && patientActor.userId().equals(saved.getPatient().getId())));
verify(patientRepository).findByUserAccount_Id(patientActor.userId());
verify(caseRepository).save(argThat(saved -> saved.getPatient() != null
&& saved.getPatient().getUserAccount() != null
&& patientActor.userId().equals(saved.getPatient().getUserAccount().getId())));
}

@Test
Expand Down Expand Up @@ -465,13 +475,13 @@ void getClosedCases_shouldDenyDoctor() {

@Test
void getAllCases_shouldReturnPatientCasesForPatientActor() {
when(caseRepository.findAllByPatient_IdAndStatusNot(patientActor.userId(), CaseStatus.CLOSED)).thenReturn(List.of(caseEntity));
when(caseRepository.findAllByPatient_UserAccount_IdAndStatusNot(patientActor.userId(), CaseStatus.CLOSED)).thenReturn(List.of(caseEntity));
when(caseMapper.toDTO(caseEntity)).thenReturn(new CaseDTO());

List<CaseDTO> result = caseService.getAllCases(patientActor);

assertThat(result).hasSize(1);
verify(caseRepository).findAllByPatient_IdAndStatusNot(patientActor.userId(), CaseStatus.CLOSED);
verify(caseRepository).findAllByPatient_UserAccount_IdAndStatusNot(patientActor.userId(), CaseStatus.CLOSED);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
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.infrastructure.persistence.UserAccountEntity;
import org.example.projektarendehantering.presentation.dto.DocumentDTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -85,6 +86,9 @@ void setUp() {

PatientEntity patient = new PatientEntity();
patient.setId(patientId);
UserAccountEntity patientUserAccount = new UserAccountEntity();
patientUserAccount.setId(patientId);
patient.setUserAccount(patientUserAccount);

caseId = UUID.randomUUID();
caseEntity = new CaseEntity();
Expand Down