From 285d0895800b9f0844219d1fe4a5fe6533156ef6 Mon Sep 17 00:00:00 2001 From: Codinab Date: Thu, 7 Mar 2024 16:35:01 +0100 Subject: [PATCH 01/11] Feature AddMedicalRecord --- .../udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java | 2 ++ src/test/resources/features/AddMedicalRecord.feature | 0 2 files changed, 2 insertions(+) create mode 100644 src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java create mode 100644 src/test/resources/features/AddMedicalRecord.feature diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java new file mode 100644 index 00000000..98186a22 --- /dev/null +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java @@ -0,0 +1,2 @@ +package cat.udl.eps.softarch.demo.steps;public class AddMedicalRecordStepDefs { +} diff --git a/src/test/resources/features/AddMedicalRecord.feature b/src/test/resources/features/AddMedicalRecord.feature new file mode 100644 index 00000000..e69de29b From e890f9676d258222286a0ed5ccc25fd93919683e Mon Sep 17 00:00:00 2001 From: Codinab Date: Thu, 7 Mar 2024 16:35:53 +0100 Subject: [PATCH 02/11] Steps defined --- .../demo/steps/AddMedicalRecordStepDefs.java | 40 +++++++++++++++++- .../features/AddMedicalRecord.feature | 41 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java index 98186a22..139b44a9 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java @@ -1,2 +1,40 @@ -package cat.udl.eps.softarch.demo.steps;public class AddMedicalRecordStepDefs { +package cat.udl.eps.softarch.demo.steps; + +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.When; + +public class AddMedicalRecordStepDefs { + @Given("a pet {string} exists in the system") + public void aPetExistsInTheSystem(String arg0) { + + } + + @And("I am logged in as a shelter volunteer") + public void iAmLoggedInAsAShelterVolunteer() { + } + + @When("I add a new medical record with issue {string}, description {string}, and date {string} for {string}") + public void iAddANewMedicalRecordWithIssueDescriptionAndDateFor(String arg0, String arg1, String arg2, String arg3) { + } + + @And("It has been created a medical record with issue {string} and description {string} for {string}") + public void itHasBeenCreatedAMedicalRecordWithIssueAndDescriptionFor(String arg0, String arg1, String arg2) { + } + + @When("I add a new medical record with issue {string}, description {string} and no date for {string}") + public void iAddANewMedicalRecordWithIssueDescriptionAndNoDateFor(String arg0, String arg1, String arg2) { + } + + @Given("I am logged in as a normal user") + public void iAmLoggedInAsANormalUser() { + } + + @When("I try to add a medical record for {string}") + public void iTryToAddAMedicalRecordFor(String arg0) { + } + + @Given("I am logged in as an admin") + public void iAmLoggedInAsAnAdmin() { + } } diff --git a/src/test/resources/features/AddMedicalRecord.feature b/src/test/resources/features/AddMedicalRecord.feature index e69de29b..29861a36 100644 --- a/src/test/resources/features/AddMedicalRecord.feature +++ b/src/test/resources/features/AddMedicalRecord.feature @@ -0,0 +1,41 @@ +Feature: Add Medical Record + In order to maintain an accurate health history for pets + As a shelter volunteer + I want to add medical records to pets' profiles + + Background: + Given a pet "Buddy" exists in the system + And I am logged in as a shelter volunteer + + Scenario: Add a valid medical record to an existing pet + When I add a new medical record with issue "Allergy", description "Seasonal allergy", and date "2024-03-07T14:00:00Z" for "Buddy" + Then The response code is 201 + And It has been created a medical record with issue "Allergy" and description "Seasonal allergy" for "Buddy" + + Scenario: Add medical record with empty issue + When I add a new medical record with issue "", description "Missing vaccine", and date "2024-03-07T14:00:00Z" for "Buddy" + Then The response code is 400 + And The error message is "issue must not be blank" + + Scenario: Add medical record with empty description + When I add a new medical record with issue "Vaccination", description "", and date "2024-03-07T14:00:00Z" for "Buddy" + Then The response code is 400 + And The error message is "description must not be blank" + + Scenario: Add medical record without date + When I add a new medical record with issue "Injury", description "Minor cut on paw" and no date for "Buddy" + Then The response code is 400 + And The error message is "date must not be null" + + Scenario: Attempt to add a medical record as a normal user + Given I am logged in as a normal user + When I try to add a medical record for "Buddy" + Then The response code is 403 + And The error message is "Unauthorized access" + + Scenario: Attempt to add a medical record as an admin + Given I am logged in as an admin + When I try to add a medical record for "Buddy" + Then The response code is 403 + And The error message is "Unauthorized access" + From 3b3b534af1939d2d5856291986ea5073d11ee865 Mon Sep 17 00:00:00 2001 From: Codinab Date: Wed, 13 Mar 2024 17:37:52 +0100 Subject: [PATCH 03/11] Created MedicalRecordRepository Defined method findByPet --- .../demo/repository/MedicalRecordRepository.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java diff --git a/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java b/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java new file mode 100644 index 00000000..2fced999 --- /dev/null +++ b/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java @@ -0,0 +1,15 @@ +package cat.udl.eps.softarch.demo.repository; + +import cat.udl.eps.softarch.demo.domain.MedicalRecord; +import cat.udl.eps.softarch.demo.domain.Pet; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import java.util.List; + +@RepositoryRestResource +public interface MedicalRecordRepository extends CrudRepository, PagingAndSortingRepository { + + List findByPet(Pet pet); +} From 3cda4b55f302ebdb767d16775c914d364a2f39e1 Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 00:06:45 +0200 Subject: [PATCH 04/11] Fixed features --- .../features/AddMedicalRecord.feature | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/test/resources/features/AddMedicalRecord.feature b/src/test/resources/features/AddMedicalRecord.feature index 29861a36..518f82e2 100644 --- a/src/test/resources/features/AddMedicalRecord.feature +++ b/src/test/resources/features/AddMedicalRecord.feature @@ -8,34 +8,32 @@ Feature: Add Medical Record And I am logged in as a shelter volunteer Scenario: Add a valid medical record to an existing pet - When I add a new medical record with issue "Allergy", description "Seasonal allergy", and date "2024-03-07T14:00:00Z" for "Buddy" + When I add a new medical record with issue "Allergy", description "Seasonal allergy", and date "2024-03-07T14:00:00Z" Then The response code is 201 - And It has been created a medical record with issue "Allergy" and description "Seasonal allergy" for "Buddy" + And It has been created a medical record with issue "Allergy" and description "Seasonal allergy" Scenario: Add medical record with empty issue - When I add a new medical record with issue "", description "Missing vaccine", and date "2024-03-07T14:00:00Z" for "Buddy" + When I add a new medical record with issue "", description "Missing vaccine", and date "2024-03-07T14:00:00Z" Then The response code is 400 And The error message is "issue must not be blank" Scenario: Add medical record with empty description - When I add a new medical record with issue "Vaccination", description "", and date "2024-03-07T14:00:00Z" for "Buddy" + When I add a new medical record with issue "Vaccination", description "", and date "2024-03-07T14:00:00Z" Then The response code is 400 And The error message is "description must not be blank" Scenario: Add medical record without date - When I add a new medical record with issue "Injury", description "Minor cut on paw" and no date for "Buddy" + When I add a new medical record with issue "Injury", description "Minor cut on paw" and no date Then The response code is 400 And The error message is "date must not be null" Scenario: Attempt to add a medical record as a normal user Given I am logged in as a normal user - When I try to add a medical record for "Buddy" + When I try to add a medical record Then The response code is 403 And The error message is "Unauthorized access" Scenario: Attempt to add a medical record as an admin Given I am logged in as an admin - When I try to add a medical record for "Buddy" - Then The response code is 403 - And The error message is "Unauthorized access" - + When I try to add a medical record + Then The response code is 201 \ No newline at end of file From 045ca3270f7521b443c9d5eba9f508a615e55ab1 Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 00:07:23 +0200 Subject: [PATCH 05/11] Fixed features --- .../demo/steps/AddMedicalRecordStepDefs.java | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java index 139b44a9..f65f2d93 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java @@ -1,40 +1,69 @@ 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.domain.ShelterVolunteer; +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.Given; import io.cucumber.java.en.When; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.ZonedDateTime; + public class AddMedicalRecordStepDefs { - @Given("a pet {string} exists in the system") - public void aPetExistsInTheSystem(String arg0) { - - } + + Pet pet; + ShelterVolunteer volunteer; + + @Autowired + MedicalRecordRepository medicalRecordRepository; + @And("I am logged in as a shelter volunteer") public void iAmLoggedInAsAShelterVolunteer() { + volunteer = new ShelterVolunteer(); + } + @Given("a pet {string} exists in the system") + public void aPetExistsInTheSystem(String arg0) { + pet = new Pet(); + pet.setName(arg0); } - @When("I add a new medical record with issue {string}, description {string}, and date {string} for {string}") - public void iAddANewMedicalRecordWithIssueDescriptionAndDateFor(String arg0, String arg1, String arg2, String arg3) { + @When("I add a new medical record with issue {string}, description {string}, and date {string}") + public void iAddANewMedicalRecordWithIssueDescriptionAndDateFor(String issue, String description, String date) { + ZonedDateTime dateTime = ZonedDateTime.parse(date); + + // Create and set up new MedicalRecord + MedicalRecord medicalRecord = new MedicalRecord(); + medicalRecord.setIssue(issue); + medicalRecord.setDescription(description); + medicalRecord.setDate(dateTime); + medicalRecord.setPet(pet); + medicalRecordRepository.save(medicalRecord); } - @And("It has been created a medical record with issue {string} and description {string} for {string}") + + @And("It has been created a medical record with issue {string} and description {string}") public void itHasBeenCreatedAMedicalRecordWithIssueAndDescriptionFor(String arg0, String arg1, String arg2) { + } - @When("I add a new medical record with issue {string}, description {string} and no date for {string}") + @When("I add a new medical record with issue {string}, description {string} and no date") public void iAddANewMedicalRecordWithIssueDescriptionAndNoDateFor(String arg0, String arg1, String arg2) { } @Given("I am logged in as a normal user") - public void iAmLoggedInAsANormalUser() { + public void iAmLoggedInAsANormalUser() { } - @When("I try to add a medical record for {string}") + @When("I try to add a medical record") public void iTryToAddAMedicalRecordFor(String arg0) { } @Given("I am logged in as an admin") public void iAmLoggedInAsAnAdmin() { } -} +} \ No newline at end of file From 4e5e3d379b6eb76714c6c1d5fa7471026d978302 Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 01:50:04 +0200 Subject: [PATCH 06/11] Implemented handler --- .../softarch/demo/domain/MedicalRecord.java | 1 + .../UnauthorizedAccessException.java | 7 ++ .../handler/MedicalRecordEventHandler.java | 63 +++++++++++ .../repository/MedicalRecordRepository.java | 9 +- .../demo/steps/AddMedicalRecordStepDefs.java | 100 +++++++++++------- .../features/AddMedicalRecord.feature | 40 +++---- 6 files changed, 160 insertions(+), 60 deletions(-) create mode 100644 src/main/java/cat/udl/eps/softarch/demo/exceptions/UnauthorizedAccessException.java create mode 100644 src/main/java/cat/udl/eps/softarch/demo/handler/MedicalRecordEventHandler.java diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java b/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java index 1d83c87f..e87850e9 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java @@ -9,6 +9,7 @@ import java.time.ZonedDateTime; @EqualsAndHashCode(callSuper = true) +@Table(name = "MedicalRecord") @Data @Entity public class MedicalRecord extends UriEntity { diff --git a/src/main/java/cat/udl/eps/softarch/demo/exceptions/UnauthorizedAccessException.java b/src/main/java/cat/udl/eps/softarch/demo/exceptions/UnauthorizedAccessException.java new file mode 100644 index 00000000..f92e9c12 --- /dev/null +++ b/src/main/java/cat/udl/eps/softarch/demo/exceptions/UnauthorizedAccessException.java @@ -0,0 +1,7 @@ +package cat.udl.eps.softarch.demo.exceptions; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.FORBIDDEN, reason = "Unauthorized access") +public class UnauthorizedAccessException extends RuntimeException {} 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 new file mode 100644 index 00000000..97132231 --- /dev/null +++ b/src/main/java/cat/udl/eps/softarch/demo/handler/MedicalRecordEventHandler.java @@ -0,0 +1,63 @@ +package cat.udl.eps.softarch.demo.handler; + +import cat.udl.eps.softarch.demo.domain.MedicalRecord; +import cat.udl.eps.softarch.demo.exceptions.UnauthorizedAccessException; +import cat.udl.eps.softarch.demo.repository.MedicalRecordRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.core.annotation.HandleAfterSave; +import org.springframework.data.rest.core.annotation.HandleBeforeCreate; +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +@Component +@RepositoryEventHandler() +public class MedicalRecordEventHandler { + + private final MedicalRecordRepository medicalRecordRepository; + private static final Logger logger = LoggerFactory.getLogger(MedicalRecordEventHandler.class); + + public MedicalRecordEventHandler(MedicalRecordRepository medicalRecordRepository) { + this.medicalRecordRepository = medicalRecordRepository; + } + + @HandleBeforeCreate + public void handleMedicalRecordBeforeCreate(MedicalRecord medicalRecord) throws UnauthorizedAccessException { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (!isAuthorized(authentication)) { + logger.error("Unauthorized attempt to create a medical record by user: {}", authentication != null ? authentication.getName() : "anonymous"); + throw new UnauthorizedAccessException(); + } + + logger.info("Authorized creation of a new medical record by user: {}", authentication.getName()); + } + + @HandleAfterSave + public void handleMedicalRecordPostSave(MedicalRecord medicalRecord) { + // Example of repository usage after saving a MedicalRecord + // For instance, post-save validation or updating related entities + logger.info("Medical record for pet {} saved successfully", medicalRecord.getPet().getName()); + } + + private boolean isAuthorized(Authentication authentication) { + if (authentication == null || !authentication.isAuthenticated()) { + return false; + } + + // Define the required authorities for creating a MedicalRecord + List requiredAuthorities = Arrays.asList("ROLE_SHELTER_VOLUNTEER", "ROLE_ADMIN"); + + // Check if the authenticated user has any of the required authorities + return authentication.getAuthorities().stream() + .anyMatch(grantedAuthority -> requiredAuthorities.contains(grantedAuthority.getAuthority())); + } + +} diff --git a/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java b/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java index 2fced999..3d829869 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java +++ b/src/main/java/cat/udl/eps/softarch/demo/repository/MedicalRecordRepository.java @@ -4,12 +4,13 @@ import cat.udl.eps.softarch.demo.domain.Pet; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import java.util.List; @RepositoryRestResource -public interface MedicalRecordRepository extends CrudRepository, PagingAndSortingRepository { - - List findByPet(Pet pet); -} +public interface MedicalRecordRepository extends CrudRepository < MedicalRecord, Long > , PagingAndSortingRepository < MedicalRecord, Long > { + + List < MedicalRecord > findByPet(@Param("pet") Pet pet); +} \ No newline at end of file diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java index f65f2d93..7be5a505 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java @@ -2,68 +2,94 @@ import cat.udl.eps.softarch.demo.domain.MedicalRecord; import cat.udl.eps.softarch.demo.domain.Pet; -import cat.udl.eps.softarch.demo.domain.ShelterVolunteer; 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.Given; import io.cucumber.java.en.When; +import org.junit.Assert; 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.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + public class AddMedicalRecordStepDefs { - Pet pet; - ShelterVolunteer volunteer; + @Autowired MedicalRecordRepository medicalRecordRepository; + @Autowired + private StepDefs stepDefs; - @And("I am logged in as a shelter volunteer") - public void iAmLoggedInAsAShelterVolunteer() { - volunteer = new ShelterVolunteer(); - } - @Given("a pet {string} exists in the system") - public void aPetExistsInTheSystem(String arg0) { - pet = new Pet(); - pet.setName(arg0); - } - - @When("I add a new medical record with issue {string}, description {string}, and date {string}") - public void iAddANewMedicalRecordWithIssueDescriptionAndDateFor(String issue, String description, String date) { - ZonedDateTime dateTime = ZonedDateTime.parse(date); + Pet pet; - // Create and set up new MedicalRecord - MedicalRecord medicalRecord = new MedicalRecord(); - medicalRecord.setIssue(issue); - medicalRecord.setDescription(description); - medicalRecord.setDate(dateTime); - medicalRecord.setPet(pet); - medicalRecordRepository.save(medicalRecord); + @Given("a pet exists in the system") + public void aPetExistsInTheSystem() { + pet = new Pet(); } - - @And("It has been created a medical record with issue {string} and description {string}") - public void itHasBeenCreatedAMedicalRecordWithIssueAndDescriptionFor(String arg0, String arg1, String arg2) { - + @When("I add a new medical record for a pet with issue {string}, description {string}, and date {string}") + public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndDate(String issue, String description, String date) throws Throwable { + MedicalRecord newRecord = new MedicalRecord(); + newRecord.setDescription(description); + newRecord.setIssue(issue); + newRecord.setDate(ZonedDateTime.parse(date)); + newRecord.setPet(pet); + + // Mock a POST request to /medicalRecords + stepDefs.result = stepDefs.mockMvc.perform( + post("/medicalRecords") + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(newRecord)) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } - @When("I add a new medical record with issue {string}, description {string} and no date") - public void iAddANewMedicalRecordWithIssueDescriptionAndNoDateFor(String arg0, String arg1, String arg2) { - } - @Given("I am logged in as a normal user") - public void iAmLoggedInAsANormalUser() { - } - @When("I try to add a medical record") - public void iTryToAddAMedicalRecordFor(String arg0) { + @When("I add a new medical record for a pet with issue {string}, description {string} and no date") + public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndNoDate(String issue, String description) throws Exception { + // Assuming that MedicalRecord has a constructor that does not require a date or it's nullable + MedicalRecord recordWithoutDate = new MedicalRecord(); + //recordWithoutDate.setDescription(description); + recordWithoutDate.setIssue(issue); + + recordWithoutDate.setPet(pet); + + // Simulate the action of adding a record without a date through a REST call + stepDefs.result = stepDefs.mockMvc.perform( + post("/medicalRecords") + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(recordWithoutDate)) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate())) + .andDo(print()); } - @Given("I am logged in as an admin") - public void iAmLoggedInAsAnAdmin() { + @When("I try to add a medical record for a pet") + public void iTryToAddAMedicalRecordForAPet() throws Exception { + // Attempt to add a medical record without specifying role or permissions + MedicalRecord medicalRecord = new MedicalRecord(); + medicalRecord.setDescription("Description"); + medicalRecord.setIssue("Issue"); + medicalRecord.setDate(ZonedDateTime.now()); + medicalRecord.setPet(pet); // Simplification for example purposes + + stepDefs.result = stepDefs.mockMvc.perform( + post("/medicalRecords") + .contentType(MediaType.APPLICATION_JSON) + .content(stepDefs.mapper.writeValueAsString(medicalRecord)) + .characterEncoding(StandardCharsets.UTF_8) + .with(AuthenticationStepDefs.authenticate()) + ) + .andDo(print()); } } \ No newline at end of file diff --git a/src/test/resources/features/AddMedicalRecord.feature b/src/test/resources/features/AddMedicalRecord.feature index 518f82e2..5f4a0db5 100644 --- a/src/test/resources/features/AddMedicalRecord.feature +++ b/src/test/resources/features/AddMedicalRecord.feature @@ -4,36 +4,38 @@ Feature: Add Medical Record I want to add medical records to pets' profiles Background: - Given a pet "Buddy" exists in the system - And I am logged in as a shelter volunteer + Given a pet exists in the system + 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: Add a valid medical record to an existing pet - When I add a new medical record with issue "Allergy", description "Seasonal allergy", and date "2024-03-07T14:00:00Z" + Scenario: Add a valid medical record to an existing pet as Volunteer + Given I login as "volunteer" with password "password" + When I add a new medical record for a pet with issue "Allergy", description "Seasonal allergy", and date "2024-03-07T14:00:00Z" Then The response code is 201 - And It has been created a medical record with issue "Allergy" and description "Seasonal allergy" - Scenario: Add medical record with empty issue - When I add a new medical record with issue "", description "Missing vaccine", and date "2024-03-07T14:00:00Z" + Scenario: Add medical record with empty issue as Volunteer + Given I login as "volunteer" with password "password" + When I add a new medical record for a pet with issue "", description "Missing vaccine", and date "2024-03-07T14:00:00Z" Then The response code is 400 - And The error message is "issue must not be blank" - Scenario: Add medical record with empty description - When I add a new medical record with issue "Vaccination", description "", and date "2024-03-07T14:00:00Z" + Scenario: Add medical record with empty description as Volunteer + Given I login as "volunteer" with password "password" + When I add a new medical record for a pet with issue "Vaccination", description "", and date "2024-03-07T14:00:00Z" Then The response code is 400 - And The error message is "description must not be blank" - Scenario: Add medical record without date - When I add a new medical record with issue "Injury", description "Minor cut on paw" and no date + Scenario: Add medical record without date as Volunteer + Given I login as "volunteer" with password "password" + When I add a new medical record for a pet with issue "Injury", description "Minor cut on paw" and no date Then The response code is 400 - And The error message is "date must not be null" Scenario: Attempt to add a medical record as a normal user - Given I am logged in as a normal user - When I try to add a medical record + Given I login as "user" with password "password" + When I try to add a medical record for a pet Then The response code is 403 And The error message is "Unauthorized access" Scenario: Attempt to add a medical record as an admin - Given I am logged in as an admin - When I try to add a medical record - Then The response code is 201 \ No newline at end of file + Given I login as "admin" with password "password" + When I try to add a medical record for a pet + Then The response code is 201 From e918041fcdcf08c2e49add8a5110d1543700548b Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 03:00:46 +0200 Subject: [PATCH 07/11] Implemented tests --- .../softarch/demo/domain/MedicalRecord.java | 7 +++- .../cat/udl/eps/softarch/demo/domain/Pet.java | 1 + .../handler/MedicalRecordEventHandler.java | 2 +- .../demo/steps/AddMedicalRecordStepDefs.java | 41 +++++++++++-------- .../features/AddMedicalRecord.feature | 1 + 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java b/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java index e87850e9..e3890d01 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/MedicalRecord.java @@ -1,5 +1,7 @@ package cat.udl.eps.softarch.demo.domain; +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import com.fasterxml.jackson.annotation.JsonInclude; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -9,13 +11,12 @@ import java.time.ZonedDateTime; @EqualsAndHashCode(callSuper = true) -@Table(name = "MedicalRecord") @Data @Entity public class MedicalRecord extends UriEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue() private Long id; @NotBlank @@ -28,5 +29,7 @@ public class MedicalRecord extends UriEntity { private ZonedDateTime date; @ManyToOne + @JsonIdentityReference(alwaysAsId = true) // Only serialize the pet ID + @JsonInclude(JsonInclude.Include.NON_NULL) // Include pet only if it's not null private Pet pet; } \ No newline at end of file diff --git a/src/main/java/cat/udl/eps/softarch/demo/domain/Pet.java b/src/main/java/cat/udl/eps/softarch/demo/domain/Pet.java index cd82c311..23aeaf09 100644 --- a/src/main/java/cat/udl/eps/softarch/demo/domain/Pet.java +++ b/src/main/java/cat/udl/eps/softarch/demo/domain/Pet.java @@ -12,6 +12,7 @@ public class Pet extends UriEntity { @GeneratedValue Long id; + String name; boolean isAdopted; String color; 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 97132231..786885fc 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 @@ -21,7 +21,7 @@ @RepositoryEventHandler() public class MedicalRecordEventHandler { - private final MedicalRecordRepository medicalRecordRepository; + final MedicalRecordRepository medicalRecordRepository; private static final Logger logger = LoggerFactory.getLogger(MedicalRecordEventHandler.class); public MedicalRecordEventHandler(MedicalRecordRepository medicalRecordRepository) { diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java index 7be5a505..09989936 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java @@ -19,20 +19,29 @@ public class AddMedicalRecordStepDefs { - - - - @Autowired - MedicalRecordRepository medicalRecordRepository; - + @Autowired private StepDefs stepDefs; + + @Autowired + PetRepository petRepository; - Pet pet; @Given("a pet exists in the system") public void aPetExistsInTheSystem() { - pet = new Pet(); + var pet = new Pet(); + + pet.setName("Buddy"); + pet.setAdopted(false); // Assuming false for a new entry, adjust as needed + pet.setColor("Brown"); + pet.setSize("Medium"); + pet.setWeight(20.5); // Example weight in kilograms + pet.setAge("5 years"); + pet.setDescription("Friendly and loves to play fetch"); + pet.setBreed("Labrador Retriever"); + + petRepository.save(pet); // Save the pet to the database + } @When("I add a new medical record for a pet with issue {string}, description {string}, and date {string}") @@ -41,7 +50,7 @@ public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndDate(String issue newRecord.setDescription(description); newRecord.setIssue(issue); newRecord.setDate(ZonedDateTime.parse(date)); - newRecord.setPet(pet); + //newRecord.setPet(petRepository.findAll().iterator().next()); // Mock a POST request to /medicalRecords stepDefs.result = stepDefs.mockMvc.perform( @@ -51,18 +60,19 @@ public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndDate(String issue .characterEncoding(StandardCharsets.UTF_8) .with(AuthenticationStepDefs.authenticate())) .andDo(print()); + } @When("I add a new medical record for a pet with issue {string}, description {string} and no date") - public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndNoDate(String issue, String description) throws Exception { - // Assuming that MedicalRecord has a constructor that does not require a date or it's nullable + public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndNoDate(String issue, String description) throws Throwable { + // Assuming that MedicalRecord has a constructor that does not require a date, or it's nullable MedicalRecord recordWithoutDate = new MedicalRecord(); - //recordWithoutDate.setDescription(description); + recordWithoutDate.setDescription(description); recordWithoutDate.setIssue(issue); - recordWithoutDate.setPet(pet); + //recordWithoutDate.setPet(petRepository.findAll().iterator().next()); // Simulate the action of adding a record without a date through a REST call stepDefs.result = stepDefs.mockMvc.perform( @@ -76,13 +86,12 @@ public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndNoDate(String iss @When("I try to add a medical record for a pet") public void iTryToAddAMedicalRecordForAPet() throws Exception { - // Attempt to add a medical record without specifying role or permissions MedicalRecord medicalRecord = new MedicalRecord(); medicalRecord.setDescription("Description"); medicalRecord.setIssue("Issue"); medicalRecord.setDate(ZonedDateTime.now()); - medicalRecord.setPet(pet); // Simplification for example purposes - + //medicalRecord.setPet(petRepository.findAll().iterator().next()); + stepDefs.result = stepDefs.mockMvc.perform( post("/medicalRecords") .contentType(MediaType.APPLICATION_JSON) diff --git a/src/test/resources/features/AddMedicalRecord.feature b/src/test/resources/features/AddMedicalRecord.feature index 5f4a0db5..5454d2e2 100644 --- a/src/test/resources/features/AddMedicalRecord.feature +++ b/src/test/resources/features/AddMedicalRecord.feature @@ -8,6 +8,7 @@ Feature: Add Medical Record 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: Add a valid medical record to an existing pet as Volunteer Given I login as "volunteer" with password "password" From b335b280ebb7d7c950f92a5833925bda5ad1592e Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 09:15:44 +0200 Subject: [PATCH 08/11] Added comments --- .../handler/MedicalRecordEventHandler.java | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 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 786885fc..c8b4ebe6 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 @@ -5,59 +5,72 @@ import cat.udl.eps.softarch.demo.repository.MedicalRecordRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.HandleBeforeCreate; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; @Component -@RepositoryEventHandler() +@RepositoryEventHandler public class MedicalRecordEventHandler { - final MedicalRecordRepository medicalRecordRepository; + private final MedicalRecordRepository medicalRecordRepository; 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"; + public MedicalRecordEventHandler(MedicalRecordRepository medicalRecordRepository) { this.medicalRecordRepository = medicalRecordRepository; } + /** + * Handles actions before creating a medical record. + * @param medicalRecord the medical record to be created + * @throws UnauthorizedAccessException if the user is not authorized to create a medical record + */ @HandleBeforeCreate public void handleMedicalRecordBeforeCreate(MedicalRecord medicalRecord) throws UnauthorizedAccessException { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!isAuthorized(authentication)) { - logger.error("Unauthorized attempt to create a medical record by user: {}", authentication != null ? authentication.getName() : "anonymous"); + 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(); } logger.info("Authorized creation of a new medical record by user: {}", authentication.getName()); } + /** + * Handles actions after saving a medical record. + * @param medicalRecord the saved medical record + */ @HandleAfterSave public void handleMedicalRecordPostSave(MedicalRecord medicalRecord) { - // Example of repository usage after saving a MedicalRecord - // For instance, post-save validation or updating related entities 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 boolean isAuthorized(Authentication authentication) { if (authentication == null || !authentication.isAuthenticated()) { return false; } - // Define the required authorities for creating a MedicalRecord - List requiredAuthorities = Arrays.asList("ROLE_SHELTER_VOLUNTEER", "ROLE_ADMIN"); + List requiredAuthorities = Arrays.asList(ROLE_SHELTER_VOLUNTEER, ROLE_ADMIN); - // Check if the authenticated user has any of the required authorities return authentication.getAuthorities().stream() .anyMatch(grantedAuthority -> requiredAuthorities.contains(grantedAuthority.getAuthority())); } - } From 572211f38f70b60b63b846d7e04c86a75d041bf3 Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 09:21:17 +0200 Subject: [PATCH 09/11] Added comments and code cleanup --- .../handler/MedicalRecordEventHandler.java | 6 ----- .../demo/steps/AddMedicalRecordStepDefs.java | 23 ++++--------------- 2 files changed, 4 insertions(+), 25 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 c8b4ebe6..5e1c76c5 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 @@ -2,7 +2,6 @@ import cat.udl.eps.softarch.demo.domain.MedicalRecord; import cat.udl.eps.softarch.demo.exceptions.UnauthorizedAccessException; -import cat.udl.eps.softarch.demo.repository.MedicalRecordRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.rest.core.annotation.HandleAfterSave; @@ -19,17 +18,12 @@ @RepositoryEventHandler public class MedicalRecordEventHandler { - private final MedicalRecordRepository medicalRecordRepository; 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"; - public MedicalRecordEventHandler(MedicalRecordRepository medicalRecordRepository) { - this.medicalRecordRepository = medicalRecordRepository; - } - /** * Handles actions before creating a medical record. * @param medicalRecord the medical record to be created diff --git a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java index 09989936..9d3fe53b 100644 --- a/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java +++ b/src/test/java/cat/udl/eps/softarch/demo/steps/AddMedicalRecordStepDefs.java @@ -2,12 +2,9 @@ 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.Given; import io.cucumber.java.en.When; -import org.junit.Assert; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -31,17 +28,7 @@ public class AddMedicalRecordStepDefs { public void aPetExistsInTheSystem() { var pet = new Pet(); - pet.setName("Buddy"); - pet.setAdopted(false); // Assuming false for a new entry, adjust as needed - pet.setColor("Brown"); - pet.setSize("Medium"); - pet.setWeight(20.5); // Example weight in kilograms - pet.setAge("5 years"); - pet.setDescription("Friendly and loves to play fetch"); - pet.setBreed("Labrador Retriever"); - petRepository.save(pet); // Save the pet to the database - } @When("I add a new medical record for a pet with issue {string}, description {string}, and date {string}") @@ -50,7 +37,7 @@ public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndDate(String issue newRecord.setDescription(description); newRecord.setIssue(issue); newRecord.setDate(ZonedDateTime.parse(date)); - //newRecord.setPet(petRepository.findAll().iterator().next()); + newRecord.setPet(petRepository.findAll().iterator().next()); // Mock a POST request to /medicalRecords stepDefs.result = stepDefs.mockMvc.perform( @@ -67,14 +54,12 @@ public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndDate(String issue @When("I add a new medical record for a pet with issue {string}, description {string} and no date") public void iAddANewMedicalRecordForAPetWithIssueDescriptionAndNoDate(String issue, String description) throws Throwable { - // Assuming that MedicalRecord has a constructor that does not require a date, or it's nullable MedicalRecord recordWithoutDate = new MedicalRecord(); recordWithoutDate.setDescription(description); recordWithoutDate.setIssue(issue); - - //recordWithoutDate.setPet(petRepository.findAll().iterator().next()); + //No data added + recordWithoutDate.setPet(petRepository.findAll().iterator().next()); - // Simulate the action of adding a record without a date through a REST call stepDefs.result = stepDefs.mockMvc.perform( post("/medicalRecords") .contentType(MediaType.APPLICATION_JSON) @@ -90,7 +75,7 @@ public void iTryToAddAMedicalRecordForAPet() throws Exception { medicalRecord.setDescription("Description"); medicalRecord.setIssue("Issue"); medicalRecord.setDate(ZonedDateTime.now()); - //medicalRecord.setPet(petRepository.findAll().iterator().next()); + medicalRecord.setPet(petRepository.findAll().iterator().next()); stepDefs.result = stepDefs.mockMvc.perform( post("/medicalRecords") From 9c940c463d32786f0af59134150f9f9250cbe54f Mon Sep 17 00:00:00 2001 From: Codinab Date: Fri, 5 Apr 2024 09:56:07 +0200 Subject: [PATCH 10/11] 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 11/11] 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