From 9c940c463d32786f0af59134150f9f9250cbe54f Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 09:56:07 +0200 Subject: [PATCH 1/2] Modified handler to handle edits --- .../handler/MedicalRecordEventHandler.java | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/main/java/cat/udl/eps/softarch/demo/handler/MedicalRecordEventHandler.java b/src/main/java/cat/udl/eps/softarch/demo/handler/MedicalRecordEventHandler.java index 5e1c76c5..392ff37f 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/handler/MedicalRecordEventHandler.java +++ b/src/main/java/cat/udl/eps/softarch/demo/handler/MedicalRecordEventHandler.java @@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.HandleBeforeCreate; +import org.springframework.data.rest.core.annotation.HandleBeforeSave; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -15,12 +16,11 @@ import java.util.List; @Component -@RepositoryEventHandler +@RepositoryEventHandler() // Ensure this handler is for MedicalRecord entity public class MedicalRecordEventHandler { private static final Logger logger = LoggerFactory.getLogger(MedicalRecordEventHandler.class); - // Authorities private static final String ROLE_SHELTER_VOLUNTEER = "ROLE_SHELTER_VOLUNTEER"; private static final String ROLE_ADMIN = "ROLE_ADMIN"; @@ -31,16 +31,17 @@ public class MedicalRecordEventHandler { */ @HandleBeforeCreate public void handleMedicalRecordBeforeCreate(MedicalRecord medicalRecord) throws UnauthorizedAccessException { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - - if (!isAuthorized(authentication)) { - String userName = authentication != null ? authentication.getName() : "anonymous"; - String errorMessage = String.format("Unauthorized attempt to create a medical record by user: %s", userName); - logger.error(errorMessage); - throw new UnauthorizedAccessException(); - } + checkAuthorization(); + logger.info("Authorized creation of a new medical record by user: {}", getCurrentUsername()); + } - logger.info("Authorized creation of a new medical record by user: {}", authentication.getName()); + /** + * Handles actions before saving (updating) a medical record. + */ + @HandleBeforeSave + public void handleMedicalRecordBeforeSave(MedicalRecord medicalRecord) throws UnauthorizedAccessException { + checkAuthorization(); + logger.info("Authorized save of medical record by user: {}", getCurrentUsername()); } /** @@ -52,19 +53,24 @@ public void handleMedicalRecordPostSave(MedicalRecord medicalRecord) { logger.info("Medical record for pet {} saved successfully", medicalRecord.getPet().getName()); } - /** - * Checks if the authenticated user is authorized to perform the action. - * @param authentication the authentication context - * @return true if the user is authorized, false otherwise - */ + private void checkAuthorization() throws UnauthorizedAccessException { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (!isAuthorized(authentication)) { + throw new UnauthorizedAccessException(); + } + } + private boolean isAuthorized(Authentication authentication) { if (authentication == null || !authentication.isAuthenticated()) { return false; } - List requiredAuthorities = Arrays.asList(ROLE_SHELTER_VOLUNTEER, ROLE_ADMIN); - return authentication.getAuthorities().stream() .anyMatch(grantedAuthority -> requiredAuthorities.contains(grantedAuthority.getAuthority())); } + + private String getCurrentUsername() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication != null ? authentication.getName() : "anonymous"; + } } From 5467fff1405da6f7cdfc3b460e2deaf14bea349d Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 09:57:19 +0200 Subject: [PATCH 2/2] Testing - Edit Medical record feature --- .../demo/steps/EditMedicalRecordStepDefs.java | 88 +++++++++++++++++++ .../features/EditMedicalRecord.feature | 43 +++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/test/java/cat/udl/eps/softarch/demo/steps/EditMedicalRecordStepDefs.java create mode 100644 src/test/resources/features/EditMedicalRecord.feature diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/EditMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/EditMedicalRecordStepDefs.java new file mode 100644 index 00000000..19a470c8 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/EditMedicalRecordStepDefs.java @@ -0,0 +1,88 @@ +package cat.udl.eps.softarch.demo.steps; + +import cat.udl.eps.softarch.demo.domain.MedicalRecord; +import cat.udl.eps.softarch.demo.domain.Pet; +import cat.udl.eps.softarch.demo.repository.MedicalRecordRepository; +import cat.udl.eps.softarch.demo.repository.PetRepository; +import io.cucumber.java.en.And; +import io.cucumber.java.en.When; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; + +import java.nio.charset.StandardCharsets; +import java.time.ZonedDateTime; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +public class EditMedicalRecordStepDefs { + + @Autowired + private StepDefs stepDefs; + + @Autowired + MedicalRecordRepository medicalRecordRepository; + + @Autowired + PetRepository petRepository; + + @And("a medical record exists for the pet") + public void aMedicalRecordExistsForThePet() { + Pet pet = petRepository.findAll().iterator().next(); + + MedicalRecord existingMedicalRecord; + existingMedicalRecord = new MedicalRecord(); + existingMedicalRecord.setPet(pet); + existingMedicalRecord.setIssue("Initial Issue"); + existingMedicalRecord.setDescription("Initial Description"); + existingMedicalRecord.setDate(ZonedDateTime.now()); + medicalRecordRepository.save(existingMedicalRecord); + + } + + @When("I edit the medical record for a pet with new issue {string}, new description {string}, and new date {string}") + public void iEditTheMedicalRecordForAPetWithNewIssueNewDescriptionAndNewDate(String issue, String description, String date) throws Throwable { + MedicalRecord existingMedicalRecord = medicalRecordRepository.findAll().iterator().next(); + existingMedicalRecord.setIssue(issue); + existingMedicalRecord.setDescription(description); + existingMedicalRecord.setDate(ZonedDateTime.parse(date)); + + stepDefs.result = stepDefs.mockMvc.perform( + put("/medicalRecords/" + existingMedicalRecord.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(existingMedicalRecord)) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); + } + + @When("I edit the medical record for a pet with new issue {string}, new description {string}") + public void iEditTheMedicalRecordForAPetWithNewIssueNewDescription(String issue, String description) throws Throwable { + MedicalRecord existingMedicalRecord = medicalRecordRepository.findAll().iterator().next(); + + existingMedicalRecord.setIssue(issue); + existingMedicalRecord.setDescription(description); + // Keeping the original date + + stepDefs.result = stepDefs.mockMvc.perform( + put("/medicalRecords/" + existingMedicalRecord.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(existingMedicalRecord)) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); + } + + @When("I try to edit a medical record for a pet") + public void iTryToEditAMedicalRecordForAPet() throws Exception { + MedicalRecord existingMedicalRecord = medicalRecordRepository.findAll().iterator().next(); + + stepDefs.result = stepDefs.mockMvc.perform( + put("/medicalRecords/" + existingMedicalRecord.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(existingMedicalRecord)) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); + } +} diff --git a/src/test/resources/features/EditMedicalRecord.feature b/src/test/resources/features/EditMedicalRecord.feature new file mode 100644 index 00000000..4480f341 --- /dev/null +++ b/src/test/resources/features/EditMedicalRecord.feature @@ -0,0 +1,43 @@ +Feature: Edit Medical Record + In order to keep pet health history up to date + As a shelter volunteer + I want to edit existing medical records in pets' profiles + + Background: + Given a pet exists in the system + And a medical record exists for the pet + Given There is a registered user with username "user" and password "password" and email "user@sample.app" + Given There is a registered admin with name "admin" and password "password" and email "admin@sample.app" + Given There is a registered volunteer with name "volunteer" and password "password" and email "volunteer@sample.app" + + + Scenario: Edit an existing medical record as Volunteer + Given I login as "volunteer" with password "password" + When I edit the medical record for a pet with new issue "Allergy Update", new description "Updated seasonal allergy treatment", and new date "2024-03-08T14:00:00Z" + Then The response code is 204 + + Scenario: Edit a medical record with empty issue as Volunteer + Given I login as "volunteer" with password "password" + When I edit the medical record for a pet with new issue "", new description "Revaccination", and new date "2024-03-08T14:00:00Z" + Then The response code is 400 + + Scenario: Edit a medical record with empty description as Volunteer + Given I login as "volunteer" with password "password" + When I edit the medical record for a pet with new issue "Vaccination Update", new description "", and new date "2024-03-08T14:00:00Z" + Then The response code is 400 + + Scenario: Edit a medical record without changing the date as Volunteer + Given I login as "volunteer" with password "password" + When I edit the medical record for a pet with new issue "Injury Update", new description "Healed cut on paw" + Then The response code is 204 + + Scenario: Attempt to edit a medical record as a normal user + Given I login as "user" with password "password" + When I try to edit a medical record for a pet + Then The response code is 403 + And The error message is "Unauthorized access" + + Scenario: Attempt to edit a medical record as an admin + Given I login as "admin" with password "password" + When I try to edit a medical record for a pet + Then The response code is 204