Skip to content

Commit

Permalink
Merge pull request #93 from UdL-EPS-SoftArch/Feature-Validate-Adoption
Browse files Browse the repository at this point in the history
Feature validate adoption
  • Loading branch information
jorgechp authored Apr 6, 2024
2 parents bc78bb9 + a47bc30 commit bfb17fb
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/main/java/cat/udl/eps/softarch/demo/domain/Adoption.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -30,8 +32,15 @@ public class Adoption extends UriEntity<Long> {
private ZonedDateTime endDate;

@ManyToOne
@JsonIdentityReference(alwaysAsId = true) // Only serialize the pet ID
@JsonInclude(JsonInclude.Include.NON_NULL)
private User user; //Adopter



@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;


}
Original file line number Diff line number Diff line change
@@ -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.CONFLICT, reason = "Bad post request")
public class InvalidPostRequest extends RuntimeException {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package cat.udl.eps.softarch.demo.handler;

import cat.udl.eps.softarch.demo.domain.Adoption;
import cat.udl.eps.softarch.demo.exceptions.InvalidPostRequest;
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;
import cat.udl.eps.softarch.demo.exceptions.UnauthorizedAccessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
* This class defines event handlers for Adoption entity.
*/
@Component
@RepositoryEventHandler() // Ensure this handler is for MedicalRecord entity
public class AdoptionEventHandler {

private static final Logger logger = LoggerFactory.getLogger(AdoptionEventHandler.class);

/**
* These are the roles that are allowed to create an adoption.
*/
private static final String ROLE_USER = "ROLE_USER";
private static final String ROLE_SHELTER_VOLUNTEER = "ROLE_SHELTER_VOLUNTEER";
private static final String ROLE_ADMIN = "ROLE_ADMIN";

/**
* Handles actions before creating an adoption.
* @param adoption The adoption object to be created.
* @throws UnauthorizedAccessException If the user is not authorized.
* @throws InvalidPostRequest If the request is invalid.
*/
@HandleBeforeCreate
public void handleAdoptionBeforeCreate(Adoption adoption) throws UnauthorizedAccessException, InvalidPostRequest {

checkAuthorization("POST");
// If the pet is already adopted or the pet is null, an exception is thrown
if (adoption.getPet() == null || adoption.getPet().isAdopted() || adoption.getConfirmed()) {
logger.error("Pet is already adopted or bad request");
throw new InvalidPostRequest();
}
// If the adoption is successful, the adoption is in process

logger.info("Adoption for pet {} created successfully ", adoption.getPet().getName());
}

/**
* Handles actions before saving an adoption.
* @param adoption The adoption object to be saved.
* @throws UnauthorizedAccessException If the user is not authorized.
*/
@HandleBeforeSave
public void handleAdoptionBeforeSave(Adoption adoption) throws UnauthorizedAccessException {
checkAuthorization("PUT");
logger.info("Authorized save of adoption for pet {} ", adoption.getPet().getName());
}
// This function is called after editing an adoption
@HandleAfterSave
public void handleAdoptionAfterSave(Adoption adoption) throws UnauthorizedAccessException {
adoption.getPet().setAdopted(true);
logger.info("Pet {} adopted successfully", adoption.getPet().getName());
}


/**
* Checks if the user is authorized to create or edit an adoption.
* @param httpMethod The HTTP method used for the request.
* @throws UnauthorizedAccessException If the user is not authorized.
*/
private void checkAuthorization(String httpMethod) throws UnauthorizedAccessException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!isAuthorized(authentication, httpMethod)) {
throw new UnauthorizedAccessException();
}
}

/**
* Checks if the user is authorized and checks the role of the user.
* @param authentication The authentication object of the user.
* @param HTTPMethod The HTTP method used for the request.
* @return True if the user is authorized, false otherwise.
*/
private boolean isAuthorized(Authentication authentication, String HTTPMethod) {
if (authentication == null || !authentication.isAuthenticated()) {
return false;
}
List<String> requiredAuthorities;

if (HTTPMethod.equals("PUT")) {
requiredAuthorities = Arrays.asList(ROLE_SHELTER_VOLUNTEER, ROLE_ADMIN);
}
else if (HTTPMethod.equals("POST")) {
requiredAuthorities = Arrays.asList(ROLE_SHELTER_VOLUNTEER, ROLE_ADMIN, ROLE_USER);
}
else {
requiredAuthorities = Arrays.asList(ROLE_ADMIN, ROLE_SHELTER_VOLUNTEER);
}
return authentication.getAuthorities().stream()
.anyMatch(grantedAuthority -> requiredAuthorities.contains(grantedAuthority.getAuthority()));
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package cat.udl.eps.softarch.demo.repository;

import cat.udl.eps.softarch.demo.domain.Adoption;
import cat.udl.eps.softarch.demo.domain.Location;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;

public interface AdoptionRepository extends CrudRepository<Adoption, Long>, PagingAndSortingRepository<Adoption, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package cat.udl.eps.softarch.demo.steps;


import cat.udl.eps.softarch.demo.domain.Adoption;
import cat.udl.eps.softarch.demo.domain.Pet;
import cat.udl.eps.softarch.demo.repository.AdoptionRepository;
import cat.udl.eps.softarch.demo.repository.PetRepository;
import cat.udl.eps.softarch.demo.repository.UserRepository;
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 org.springframework.http.MediaType;
import org.springframework.test.web.servlet.ResultActions;

import java.nio.charset.StandardCharsets;
import java.time.ZonedDateTime;

import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SuppressWarnings("ALL")
public class ProcessAdoptionStepDefs {


@Autowired
StepDefs stepDefs;

@Autowired
UserRepository userRepository;

@Autowired
PetRepository petRepository;

@Autowired
AdoptionRepository adoptionRepository;

protected ResultActions result;


@And("I receive a confirmation message for adopting the pet")
public void iReceiveAConfirmationMessageForAdoptingThePet() throws Throwable {
result.andExpect(status().isOk())
.andExpect(jsonPath("$.message", is("Adoption successful")));

}

@Given("There is an available pet with name {string} i want to adopt")
public void thereIsAnAvailablePetWithName(String arg0) {

Pet pet = new Pet();
pet.setName(arg0);
pet.setAdopted(false);
pet.setColor("color");
pet.setSize("size");
pet.setWeight(1.0);
pet.setAge("age");
pet.setDescription("description");
pet.setBreed("breed");
petRepository.save(pet);

}

@When("I request to adopt the pet with name {string}")
public void iRequestToAdoptThePetWithName(String arg0) throws Throwable {

Adoption adoption = new Adoption();
adoption.setPet(petRepository.findByName(arg0).get(0));
adoption.setUser(userRepository.findAll().iterator().next());
adoption.setStartDate(ZonedDateTime.now());
adoption.setConfirmed(false);
adoption.setType("Adoption");
adoption.setEndDate(null);

stepDefs.result = stepDefs.mockMvc.perform(
post("/adoptions")
.contentType(MediaType.APPLICATION_JSON)
.content(stepDefs.mapper.writeValueAsString(adoption))
.characterEncoding(StandardCharsets.UTF_8)
.with(AuthenticationStepDefs.authenticate()))
.andDo(print());

}



@When("I request to adopt without a pet")
public void iRequestToAdoptWithoutAPet() throws Throwable{
// Proceed with adoption logic
Adoption adoption = new Adoption();
adoption.setUser(userRepository.findAll().iterator().next());
adoption.setStartDate(ZonedDateTime.now());
adoption.setConfirmed(false);
adoption.setType("Adoption");
adoption.setEndDate(null);


stepDefs.result = stepDefs.mockMvc.perform(
post("/adoptions")
.contentType(MediaType.APPLICATION_JSON)
.content(stepDefs.mapper.writeValueAsString(adoption))
.characterEncoding(StandardCharsets.UTF_8)
.with(AuthenticationStepDefs.authenticate()))
.andDo(print());

}

@And("The pet with name {string} is already adopted")
public void thePetWithNameIsAlreadyAdopted(String arg0) {

Pet pet = new Pet();
pet.setName(arg0);
pet.setAdopted(true);
pet.setColor("color");
pet.setSize("size");
pet.setWeight(1.0);
pet.setAge("age");
pet.setDescription("description");
pet.setBreed("breed");
petRepository.save(pet);


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cat.udl.eps.softarch.demo.steps;



import cat.udl.eps.softarch.demo.domain.Pet;
import cat.udl.eps.softarch.demo.domain.Adoption;
import cat.udl.eps.softarch.demo.repository.AdoptionRepository;
import cat.udl.eps.softarch.demo.repository.PetRepository;
import cat.udl.eps.softarch.demo.repository.UserRepository;
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 org.springframework.test.web.servlet.ResultActions;

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;

@SuppressWarnings("ALL")
public class ValidateAdoptionStepDefs {

@Autowired
StepDefs stepDefs;

@Autowired
UserRepository userRepository;

@Autowired
PetRepository petRepository;

@Autowired
AdoptionRepository adoptionRepository;

protected ResultActions result;


@And("There is a dog with a pending adoption request from an user")
public void thereIsAPendingAdoptionRequestForPetFromUser() {
Pet pet = new Pet();
pet.setName("Pet");
pet.setAdopted(false);
pet.setColor("color");
pet.setSize("size");
pet.setWeight(1.0);
pet.setAge("age");
pet.setDescription("description");
pet.setBreed("breed");
petRepository.save(pet);


Adoption adoption = new Adoption();
adoption.setConfirmed(false);
adoption.setStartDate(ZonedDateTime.now());
adoption.setUser(userRepository.findAll().iterator().next());
adoption.setPet(petRepository.findAll().iterator().next());
adoption.setType("Adoption");
adoption.setEndDate(null);
adoptionRepository.save(adoption);

}

@When("I validate the adoption request")
public void iValidateTheAdoptionRequestForPetFromUser() throws Throwable {
Adoption existingAdoption = adoptionRepository.findAll().iterator().next();
existingAdoption.setConfirmed(true);

stepDefs.result = stepDefs.mockMvc.perform(
put("/adoptions/" + existingAdoption.getId())
.contentType(MediaType.APPLICATION_JSON)
.content(stepDefs.mapper.writeValueAsString(existingAdoption))
.characterEncoding(StandardCharsets.UTF_8)
.with(AuthenticationStepDefs.authenticate()))
.andDo(print());

}


}
Loading

0 comments on commit bfb17fb

Please sign in to comment.