From 909026143d5816727a44aec70b0bc27780e26148 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sun, 29 Mar 2026 21:52:45 -0600 Subject: [PATCH] Fix user linking --- .../backend/service/CustomerService.java | 9 ++++++++ .../migration/V9__backfill_user_accounts.sql | 2 ++ .../backend/service/CustomerServiceTest.java | 21 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/backend/src/main/java/com/petshop/backend/service/CustomerService.java b/backend/src/main/java/com/petshop/backend/service/CustomerService.java index a34bcb2b..fb4f75c0 100644 --- a/backend/src/main/java/com/petshop/backend/service/CustomerService.java +++ b/backend/src/main/java/com/petshop/backend/service/CustomerService.java @@ -13,6 +13,9 @@ import org.springframework.data.domain.Pageable; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +import static org.springframework.http.HttpStatus.CONFLICT; @Service public class CustomerService { @@ -57,6 +60,12 @@ public class CustomerService { customer = customerRepository.save(customer); Customer savedCustomer = customer; User user = userRepository.findByEmail(savedCustomer.getEmail()) + .map(existing -> { + if (existing.getRole() != User.Role.CUSTOMER) { + throw new ResponseStatusException(CONFLICT, "Email already exists for a different account type"); + } + return existing; + }) .orElseGet(() -> createLinkedUser(savedCustomer)); Customer linkedCustomer = userBusinessLinkageService.ensureLinkedCustomer(user); diff --git a/backend/src/main/resources/db/migration/V9__backfill_user_accounts.sql b/backend/src/main/resources/db/migration/V9__backfill_user_accounts.sql index 9a78abe3..273313a3 100644 --- a/backend/src/main/resources/db/migration/V9__backfill_user_accounts.sql +++ b/backend/src/main/resources/db/migration/V9__backfill_user_accounts.sql @@ -41,11 +41,13 @@ WHERE e.user_id IS NULL UPDATE customer c JOIN users u ON u.email = c.email + AND u.role = 'CUSTOMER' SET c.user_id = u.id WHERE c.user_id IS NULL; UPDATE employee e JOIN users u ON u.email = e.email + AND u.role IN ('STAFF', 'ADMIN') SET e.user_id = u.id WHERE e.user_id IS NULL; diff --git a/backend/src/test/java/com/petshop/backend/service/CustomerServiceTest.java b/backend/src/test/java/com/petshop/backend/service/CustomerServiceTest.java index b9152511..6d2bfad2 100644 --- a/backend/src/test/java/com/petshop/backend/service/CustomerServiceTest.java +++ b/backend/src/test/java/com/petshop/backend/service/CustomerServiceTest.java @@ -12,10 +12,12 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.web.server.ResponseStatusException; import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; @@ -82,4 +84,23 @@ class CustomerServiceTest { assertEquals("Pat Owner", createdUser.getFullName()); assertEquals("200-000-0007", createdUser.getPhone()); } + + @Test + void createCustomerRejectsExistingNonCustomerEmail() { + CustomerRequest request = new CustomerRequest(); + request.setFirstName("Pat"); + request.setLastName("Owner"); + request.setEmail("pat@example.com"); + + User existing = new User(); + existing.setId(22L); + existing.setUsername("staff1"); + existing.setEmail("pat@example.com"); + existing.setRole(User.Role.STAFF); + + when(customerRepository.save(any(Customer.class))).thenAnswer(invocation -> invocation.getArgument(0)); + when(userRepository.findByEmail("pat@example.com")).thenReturn(Optional.of(existing)); + + assertThrows(ResponseStatusException.class, () -> customerService.createCustomer(request)); + } }