diff --git a/src/main/java/com/amplifiers/pathfinder/config/SecurityConfiguration.java b/src/main/java/com/amplifiers/pathfinder/config/SecurityConfiguration.java index a6916d8..0b1f819 100644 --- a/src/main/java/com/amplifiers/pathfinder/config/SecurityConfiguration.java +++ b/src/main/java/com/amplifiers/pathfinder/config/SecurityConfiguration.java @@ -1,9 +1,13 @@ package com.amplifiers.pathfinder.config; import com.amplifiers.pathfinder.auth.CustomAuthenticationEntryPoint; +import com.amplifiers.pathfinder.exception.GlobalExceptionHandler; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -17,6 +21,8 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import static com.amplifiers.pathfinder.entity.user.Permission.*; import static com.amplifiers.pathfinder.entity.user.Role.ADMIN; @@ -47,13 +53,13 @@ public class SecurityConfiguration { private final AuthenticationProvider authenticationProvider; private final LogoutService logoutService; private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; - + private final GlobalExceptionHandler globalExceptionHandler; @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOriginPatterns(Arrays.asList("*")); - configuration.setAllowedMethods(Arrays.asList("GET","POST","PATCH", "PUT", "DELETE", "OPTIONS", "HEAD")); + configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS", "HEAD")); configuration.setAllowCredentials(true); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setExposedHeaders(Arrays.asList("X-Get-Header")); @@ -65,7 +71,7 @@ public CorsConfigurationSource corsConfigurationSource() { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http - .cors((cors)->cors.configurationSource(corsConfigurationSource())) + .cors((cors) -> cors.configurationSource(corsConfigurationSource())) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(req -> req.requestMatchers(WHITE_LIST_URL) @@ -88,7 +94,17 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti ) .exceptionHandling(exceptionHandling -> exceptionHandling - .defaultAuthenticationEntryPointFor(customAuthenticationEntryPoint, request -> true) + .authenticationEntryPoint(customAuthenticationEntryPoint) // 401 Unauthorized + .accessDeniedHandler((request, response, accessDeniedException) -> { // 403 Forbidden + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setStatus(HttpStatus.FORBIDDEN.value()); + Map body = new HashMap<>(); + body.put("status_code", HttpStatus.FORBIDDEN.value()); + body.put("error", "Forbidden"); + body.put("message", "Access denied. You do not have permission to access this resource."); + body.put("path", request.getServletPath()); + new ObjectMapper().writeValue(response.getOutputStream(), body); + }) ); return http.build(); } diff --git a/src/main/java/com/amplifiers/pathfinder/entity/gig/PrivateGigController.java b/src/main/java/com/amplifiers/pathfinder/entity/gig/PrivateGigController.java index 3fb62dd..db0d7ba 100644 --- a/src/main/java/com/amplifiers/pathfinder/entity/gig/PrivateGigController.java +++ b/src/main/java/com/amplifiers/pathfinder/entity/gig/PrivateGigController.java @@ -96,7 +96,7 @@ public String deleteGig( @GetMapping("/recommendations") @ResponseStatus(HttpStatus.OK) public ResponseEntity getRecommendationsForUser() { - return ResponseEntity.ok(service.getRecommendationsForUser("")); + return ResponseEntity.ok(service.getRecommendationsForUser(null)); } @GetMapping("/recommendations/popular-gigs") diff --git a/src/main/java/com/amplifiers/pathfinder/exception/GlobalExceptionHandler.java b/src/main/java/com/amplifiers/pathfinder/exception/GlobalExceptionHandler.java index b407d98..461c4ed 100644 --- a/src/main/java/com/amplifiers/pathfinder/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/amplifiers/pathfinder/exception/GlobalExceptionHandler.java @@ -5,23 +5,17 @@ import lombok.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.http.HttpHeaders; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.transaction.TransactionSystemException; -import org.springframework.validation.FieldError; -import org.springframework.web.bind.MethodArgumentNotValidException; + import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; -import org.springframework.context.support.DefaultMessageSourceResolvable; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7761c04..4f4ecc5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -13,6 +13,11 @@ spring: multipart: max-file-size: 100MB max-request-size: 100MB + mvc: + throw-exception-if-no-handler-found: true + web: + resources: + add-mappings: false application: security: diff --git a/src/test/java/com/amplifiers/pathfinder/payment/PaymentServiceTest.java b/src/test/java/com/amplifiers/pathfinder/payment/PaymentServiceTest.java index c27e86e..1ffef16 100644 --- a/src/test/java/com/amplifiers/pathfinder/payment/PaymentServiceTest.java +++ b/src/test/java/com/amplifiers/pathfinder/payment/PaymentServiceTest.java @@ -3,11 +3,12 @@ import com.amplifiers.pathfinder.entity.enrollment.Enrollment; import com.amplifiers.pathfinder.entity.enrollment.EnrollmentRepository; import com.amplifiers.pathfinder.entity.gig.Gig; +import com.amplifiers.pathfinder.entity.gig.GigRepository; import com.amplifiers.pathfinder.entity.notification.NotificationService; -import com.amplifiers.pathfinder.sslcommerz.TransactionResponseValidator; import com.amplifiers.pathfinder.entity.transaction.Transaction; import com.amplifiers.pathfinder.entity.transaction.TransactionRepository; import com.amplifiers.pathfinder.entity.user.User; +import com.amplifiers.pathfinder.sslcommerz.TransactionResponseValidator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -32,6 +33,8 @@ class PaymentServiceTest { private NotificationService notificationService; @Mock private EnrollmentRepository enrollmentRepository; + @Mock + private GigRepository gigRepository; private PaymentService paymentService; @@ -41,7 +44,7 @@ class PaymentServiceTest { @BeforeEach void setUp() { - paymentService = new PaymentService(transactionRepository, transactionResponseValidator, notificationService, enrollmentRepository); + paymentService = new PaymentService(transactionRepository, transactionResponseValidator, notificationService, enrollmentRepository, gigRepository); User buyer = new User(); buyer.setFirstName("John");