Enforce pet ownership rules
This commit is contained in:
@@ -80,15 +80,8 @@ public class DropdownController {
|
|||||||
@GetMapping("/appointment-customers")
|
@GetMapping("/appointment-customers")
|
||||||
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<List<DropdownOption>> getAppointmentCustomers() {
|
public ResponseEntity<List<DropdownOption>> getAppointmentCustomers() {
|
||||||
User user = com.petshop.backend.util.AuthenticationHelper.getAuthenticatedUser(userRepository);
|
|
||||||
List<com.petshop.backend.entity.Customer> customers;
|
|
||||||
if (user.getRole() == User.Role.ADMIN) {
|
|
||||||
customers = customerRepository.findAll();
|
|
||||||
} else {
|
|
||||||
customers = customerRepository.findAllWithPets();
|
|
||||||
}
|
|
||||||
return ResponseEntity.ok(
|
return ResponseEntity.ok(
|
||||||
customers.stream()
|
customerRepository.findAllWithPets().stream()
|
||||||
.map(c -> new DropdownOption(c.getCustomerId(), c.getFirstName() + " " + c.getLastName()))
|
.map(c -> new DropdownOption(c.getCustomerId(), c.getFirstName() + " " + c.getLastName()))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class AppointmentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Set<Pet> pets = hasPetIds ? fetchPets(request.getPetIds()) : new HashSet<>();
|
Set<Pet> pets = hasPetIds ? fetchPets(request.getPetIds()) : new HashSet<>();
|
||||||
Set<CustomerPet> customerPets = hasCustomerPetIds ? fetchCustomerPets(request.getCustomerPetIds(), customer.getCustomerId(), authenticatedUser.getRole()) : new HashSet<>();
|
Set<CustomerPet> customerPets = hasCustomerPetIds ? fetchCustomerPets(request.getCustomerPetIds(), customer.getCustomerId()) : new HashSet<>();
|
||||||
Employee employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
Employee employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
||||||
|
|
||||||
Appointment appointment = new Appointment();
|
Appointment appointment = new Appointment();
|
||||||
@@ -170,7 +170,7 @@ public class AppointmentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Set<Pet> pets = hasPetIds ? fetchPets(request.getPetIds()) : new HashSet<>();
|
Set<Pet> pets = hasPetIds ? fetchPets(request.getPetIds()) : new HashSet<>();
|
||||||
Set<CustomerPet> customerPets = hasCustomerPetIds ? fetchCustomerPets(request.getCustomerPetIds(), customer.getCustomerId(), authenticatedUser.getRole()) : new HashSet<>();
|
Set<CustomerPet> customerPets = hasCustomerPetIds ? fetchCustomerPets(request.getCustomerPetIds(), customer.getCustomerId()) : new HashSet<>();
|
||||||
Employee employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
Employee employee = resolveAppointmentEmployee(request.getEmployeeId(), store.getStoreId());
|
||||||
|
|
||||||
appointment.setCustomer(customer);
|
appointment.setCustomer(customer);
|
||||||
@@ -255,12 +255,12 @@ public class AppointmentService {
|
|||||||
return pets;
|
return pets;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<CustomerPet> fetchCustomerPets(List<Long> customerPetIds, Long customerId, User.Role authenticatedRole) {
|
private Set<CustomerPet> fetchCustomerPets(List<Long> customerPetIds, Long customerId) {
|
||||||
Set<CustomerPet> customerPets = new HashSet<>();
|
Set<CustomerPet> customerPets = new HashSet<>();
|
||||||
for (Long customerPetId : customerPetIds) {
|
for (Long customerPetId : customerPetIds) {
|
||||||
CustomerPet customerPet = customerPetRepository.findById(customerPetId)
|
CustomerPet customerPet = customerPetRepository.findById(customerPetId)
|
||||||
.orElseThrow(() -> new ResourceNotFoundException("Customer pet not found with id: " + customerPetId));
|
.orElseThrow(() -> new ResourceNotFoundException("Customer pet not found with id: " + customerPetId));
|
||||||
if (authenticatedRole != User.Role.ADMIN && !customerPet.getCustomer().getCustomerId().equals(customerId)) {
|
if (!customerPet.getCustomer().getCustomerId().equals(customerId)) {
|
||||||
throw new IllegalArgumentException("Selected pet does not belong to the selected customer");
|
throw new IllegalArgumentException("Selected pet does not belong to the selected customer");
|
||||||
}
|
}
|
||||||
customerPets.add(customerPet);
|
customerPets.add(customerPet);
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ class DropdownControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getAppointmentCustomersReturnsAllCustomersForAdmin() {
|
void getAppointmentCustomersReturnsOnlyCustomersWithPetsForAdmin() {
|
||||||
User adminUser = new User();
|
User adminUser = new User();
|
||||||
adminUser.setId(88L);
|
adminUser.setId(88L);
|
||||||
adminUser.setRole(User.Role.ADMIN);
|
adminUser.setRole(User.Role.ADMIN);
|
||||||
@@ -185,17 +185,11 @@ class DropdownControllerTest {
|
|||||||
one.setFirstName("Alex");
|
one.setFirstName("Alex");
|
||||||
one.setLastName("Brown");
|
one.setLastName("Brown");
|
||||||
|
|
||||||
Customer two = new Customer();
|
when(customerRepository.findAllWithPets()).thenReturn(List.of(one));
|
||||||
two.setCustomerId(2L);
|
|
||||||
two.setFirstName("Emily");
|
|
||||||
two.setLastName("Clark");
|
|
||||||
|
|
||||||
when(customerRepository.findAll()).thenReturn(List.of(one, two));
|
|
||||||
|
|
||||||
var response = controller.getAppointmentCustomers();
|
var response = controller.getAppointmentCustomers();
|
||||||
|
|
||||||
assertEquals(2, response.getBody().size());
|
assertEquals(1, response.getBody().size());
|
||||||
assertEquals(Long.valueOf(1L), response.getBody().get(0).getId());
|
assertEquals(Long.valueOf(1L), response.getBody().get(0).getId());
|
||||||
assertEquals(Long.valueOf(2L), response.getBody().get(1).getId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ class AppointmentServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createAppointmentAllowsCustomerPetOwnedByDifferentCustomerForAdmin() {
|
void createAppointmentRejectsCustomerPetOwnedByDifferentCustomer() {
|
||||||
setAuthentication(99L, User.Role.ADMIN);
|
setAuthentication(99L, User.Role.ADMIN);
|
||||||
|
|
||||||
Customer otherCustomer = new Customer();
|
Customer otherCustomer = new Customer();
|
||||||
@@ -206,11 +206,6 @@ class AppointmentServiceTest {
|
|||||||
.thenReturn(List.of(new EmployeeStore(employee, store)));
|
.thenReturn(List.of(new EmployeeStore(employee, store)));
|
||||||
when(appointmentRepository.findByStoreAndDate(1L, date)).thenReturn(List.of());
|
when(appointmentRepository.findByStoreAndDate(1L, date)).thenReturn(List.of());
|
||||||
when(customerPetRepository.findById(22L)).thenReturn(Optional.of(otherCustomerPet));
|
when(customerPetRepository.findById(22L)).thenReturn(Optional.of(otherCustomerPet));
|
||||||
when(appointmentRepository.save(any(Appointment.class))).thenAnswer(invocation -> {
|
|
||||||
Appointment appt = invocation.getArgument(0);
|
|
||||||
appt.setAppointmentId(101L);
|
|
||||||
return appt;
|
|
||||||
});
|
|
||||||
|
|
||||||
var request = new com.petshop.backend.dto.appointment.AppointmentRequest();
|
var request = new com.petshop.backend.dto.appointment.AppointmentRequest();
|
||||||
request.setCustomerId(1L);
|
request.setCustomerId(1L);
|
||||||
@@ -221,46 +216,7 @@ class AppointmentServiceTest {
|
|||||||
request.setAppointmentStatus("Booked");
|
request.setAppointmentStatus("Booked");
|
||||||
request.setCustomerPetIds(List.of(22L));
|
request.setCustomerPetIds(List.of(22L));
|
||||||
|
|
||||||
var response = appointmentService.createAppointment(request);
|
assertThrows(IllegalArgumentException.class, () -> appointmentService.createAppointment(request));
|
||||||
assertEquals(101L, response.getAppointmentId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void createAppointmentAllowsAnyPetForAdmin() {
|
|
||||||
setAuthentication(99L, User.Role.ADMIN);
|
|
||||||
|
|
||||||
Customer otherCustomer = new Customer();
|
|
||||||
otherCustomer.setCustomerId(22L);
|
|
||||||
CustomerPet otherCustomerPet = new CustomerPet();
|
|
||||||
otherCustomerPet.setCustomerPetId(22L);
|
|
||||||
otherCustomerPet.setCustomer(otherCustomer);
|
|
||||||
|
|
||||||
when(customerRepository.findById(1L)).thenReturn(Optional.of(customer));
|
|
||||||
when(storeRepository.findById(1L)).thenReturn(Optional.of(store));
|
|
||||||
when(serviceRepository.findById(1L)).thenReturn(Optional.of(grooming));
|
|
||||||
when(employeeStoreRepository.findActiveByStoreStoreIdOrderByEmployeeEmployeeIdAsc(1L))
|
|
||||||
.thenReturn(List.of(new EmployeeStore(employee, store)));
|
|
||||||
when(appointmentRepository.findByStoreAndDate(1L, date)).thenReturn(List.of());
|
|
||||||
when(customerPetRepository.findById(22L)).thenReturn(Optional.of(otherCustomerPet));
|
|
||||||
when(appointmentRepository.save(any(Appointment.class))).thenAnswer(invocation -> {
|
|
||||||
Appointment appointment = invocation.getArgument(0);
|
|
||||||
appointment.setAppointmentId(101L);
|
|
||||||
return appointment;
|
|
||||||
});
|
|
||||||
|
|
||||||
var request = new com.petshop.backend.dto.appointment.AppointmentRequest();
|
|
||||||
request.setCustomerId(1L);
|
|
||||||
request.setStoreId(1L);
|
|
||||||
request.setServiceId(1L);
|
|
||||||
request.setAppointmentDate(date);
|
|
||||||
request.setAppointmentTime(LocalTime.of(10, 0));
|
|
||||||
request.setAppointmentStatus("Booked");
|
|
||||||
request.setCustomerPetIds(List.of(22L));
|
|
||||||
|
|
||||||
var response = appointmentService.createAppointment(request);
|
|
||||||
|
|
||||||
assertEquals(101L, response.getAppointmentId());
|
|
||||||
assertEquals(1L, response.getCustomerId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user