From 319293a59d38a9f7be26e0ce5b54f97f77a37048 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Tue, 10 Mar 2026 17:15:26 -0600 Subject: [PATCH] Fix backend validation --- pom.xml | 1 + .../backend/config/DataInitializer.java | 9 +++-- .../backend/controller/AuthController.java | 8 +++++ .../exception/GlobalExceptionHandler.java | 11 ++++++ .../service/StoreAssignmentService.java | 34 +++++++++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/petshop/backend/service/StoreAssignmentService.java diff --git a/pom.xml b/pom.xml index 1803f3ec..4357996d 100644 --- a/pom.xml +++ b/pom.xml @@ -130,6 +130,7 @@ docker-compose.dev.yml down -v + --remove-orphans diff --git a/src/main/java/com/petshop/backend/config/DataInitializer.java b/src/main/java/com/petshop/backend/config/DataInitializer.java index a9dd4b15..cff00f6c 100644 --- a/src/main/java/com/petshop/backend/config/DataInitializer.java +++ b/src/main/java/com/petshop/backend/config/DataInitializer.java @@ -2,6 +2,7 @@ package com.petshop.backend.config; import com.petshop.backend.entity.User; import com.petshop.backend.repository.UserRepository; +import com.petshop.backend.service.StoreAssignmentService; import com.petshop.backend.service.UserBusinessLinkageService; import org.springframework.boot.CommandLineRunner; import org.springframework.security.crypto.password.PasswordEncoder; @@ -13,11 +14,13 @@ public class DataInitializer implements CommandLineRunner { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; private final UserBusinessLinkageService userBusinessLinkageService; + private final StoreAssignmentService storeAssignmentService; - public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) { + public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService, StoreAssignmentService storeAssignmentService) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; this.userBusinessLinkageService = userBusinessLinkageService; + this.storeAssignmentService = storeAssignmentService; } @Override @@ -62,7 +65,7 @@ public class DataInitializer implements CommandLineRunner { } } // Ensure linked employee - userBusinessLinkageService.ensureLinkedEmployee(admin); + storeAssignmentService.assignStoreIfMissing(userBusinessLinkageService.ensureLinkedEmployee(admin), 1L); User staff = userRepository.findByUsername("staff").orElse(null); if (staff == null) { @@ -102,7 +105,7 @@ public class DataInitializer implements CommandLineRunner { } } // Ensure linked employee - userBusinessLinkageService.ensureLinkedEmployee(staff); + storeAssignmentService.assignStoreIfMissing(userBusinessLinkageService.ensureLinkedEmployee(staff), 1L); User customer = userRepository.findByUsername("customer").orElse(null); if (customer == null) { diff --git a/src/main/java/com/petshop/backend/controller/AuthController.java b/src/main/java/com/petshop/backend/controller/AuthController.java index 7aa04307..b5bc1900 100644 --- a/src/main/java/com/petshop/backend/controller/AuthController.java +++ b/src/main/java/com/petshop/backend/controller/AuthController.java @@ -17,6 +17,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -126,6 +127,13 @@ public class AuthController { Map error = new HashMap<>(); error.put("message", "Invalid username or password"); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error); + } catch (InternalAuthenticationServiceException e) { + if (e.getCause() instanceof DisabledException disabledException) { + Map error = new HashMap<>(); + error.put("message", disabledException.getMessage()); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(error); + } + throw e; } catch (DisabledException e) { Map error = new HashMap<>(); error.put("message", e.getMessage()); diff --git a/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java b/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java index 40e95bbc..bfcfe03d 100644 --- a/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java @@ -2,6 +2,7 @@ package com.petshop.backend.exception; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.dao.DataIntegrityViolationException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -71,6 +72,16 @@ public class GlobalExceptionHandler { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } + @ExceptionHandler(DataIntegrityViolationException.class) + public ResponseEntity handleDataIntegrityViolationException(DataIntegrityViolationException ex) { + ErrorResponse error = new ErrorResponse( + HttpStatus.BAD_REQUEST.value(), + "Operation violates existing data relationships", + LocalDateTime.now() + ); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleGenericException(Exception ex) { ErrorResponse error = new ErrorResponse( diff --git a/src/main/java/com/petshop/backend/service/StoreAssignmentService.java b/src/main/java/com/petshop/backend/service/StoreAssignmentService.java new file mode 100644 index 00000000..31cc18d5 --- /dev/null +++ b/src/main/java/com/petshop/backend/service/StoreAssignmentService.java @@ -0,0 +1,34 @@ +package com.petshop.backend.service; + +import com.petshop.backend.entity.Employee; +import com.petshop.backend.entity.EmployeeStore; +import com.petshop.backend.entity.StoreLocation; +import com.petshop.backend.exception.ResourceNotFoundException; +import com.petshop.backend.repository.EmployeeStoreRepository; +import com.petshop.backend.repository.StoreRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StoreAssignmentService { + + private final EmployeeStoreRepository employeeStoreRepository; + private final StoreRepository storeRepository; + + public StoreAssignmentService(EmployeeStoreRepository employeeStoreRepository, StoreRepository storeRepository) { + this.employeeStoreRepository = employeeStoreRepository; + this.storeRepository = storeRepository; + } + + @Transactional + public void assignStoreIfMissing(Employee employee, Long storeId) { + if (employeeStoreRepository.findByEmployeeEmployeeId(employee.getEmployeeId()).isPresent()) { + return; + } + + StoreLocation store = storeRepository.findById(storeId) + .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + storeId)); + + employeeStoreRepository.save(new EmployeeStore(employee, store)); + } +}