From a9caf391694e89d0fff449afbac4a78d20733d27 Mon Sep 17 00:00:00 2001 From: Adrian Pionka Date: Sun, 21 Jan 2024 09:19:15 +0100 Subject: [PATCH] modify path to check user is authenticated --- .../AccessTokenPreAuthorizationFilter.java | 4 +- .../api/security/SecurityConfiguration.java | 10 ++--- .../pionas/quiz/web/home/HomeController.java | 6 +-- .../quiz/api/exam/ExamRestControllerIT.java | 26 +++++++++++- .../quiz/api/quiz/QuizRestControllerIT.java | 40 +++++++++++++------ .../quiz/web/home/HomeControllerIT.java | 19 +++++++++ 6 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 src/test/java/info/pionas/quiz/web/home/HomeControllerIT.java diff --git a/src/main/java/info/pionas/quiz/api/security/AccessTokenPreAuthorizationFilter.java b/src/main/java/info/pionas/quiz/api/security/AccessTokenPreAuthorizationFilter.java index a19a125..8680d0e 100644 --- a/src/main/java/info/pionas/quiz/api/security/AccessTokenPreAuthorizationFilter.java +++ b/src/main/java/info/pionas/quiz/api/security/AccessTokenPreAuthorizationFilter.java @@ -7,15 +7,15 @@ import lombok.AllArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import java.util.Optional; - +@Component @AllArgsConstructor class AccessTokenPreAuthorizationFilter extends OncePerRequestFilter { diff --git a/src/main/java/info/pionas/quiz/api/security/SecurityConfiguration.java b/src/main/java/info/pionas/quiz/api/security/SecurityConfiguration.java index d091af8..a4489f3 100644 --- a/src/main/java/info/pionas/quiz/api/security/SecurityConfiguration.java +++ b/src/main/java/info/pionas/quiz/api/security/SecurityConfiguration.java @@ -9,7 +9,7 @@ import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; @@ -28,7 +28,7 @@ @Configuration(proxyBeanMethods = false) @EnableWebSecurity @AllArgsConstructor -@EnableGlobalMethodSecurity(prePostEnabled = true) +@EnableMethodSecurity class SecurityConfiguration { @@ -64,7 +64,7 @@ public CorsFilter corsFilter() { } @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http, CustomAuthenticationManager customAuthenticationManager) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http, AccessTokenPreAuthorizationFilter accessTokenPreAuthorizationFilter) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorizeExchangeSpec -> @@ -72,6 +72,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, CustomAuthenti .requestMatchers(ApiConfiguration.API_CONTEXT + "/login").permitAll() .requestMatchers(ApiConfiguration.API_CONTEXT + "/register").permitAll() .requestMatchers(ApiConfiguration.API_CONTEXT + "/**").authenticated() + .requestMatchers("/**").permitAll() ) .formLogin(AbstractHttpConfigurer::disable) .httpBasic(AbstractHttpConfigurer::disable) @@ -79,9 +80,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http, CustomAuthenti httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(getAuthenticationEntryPoint()); httpSecurityExceptionHandlingConfigurer.accessDeniedHandler(getAccessDeniedHandler()); }) -// .authenticationManager(customAuthenticationManager) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .addFilterBefore(new AccessTokenPreAuthorizationFilter(customAuthenticationManager), UsernamePasswordAuthenticationFilter.class) + .addFilterBefore(accessTokenPreAuthorizationFilter, UsernamePasswordAuthenticationFilter.class) ; return http.build(); diff --git a/src/main/java/info/pionas/quiz/web/home/HomeController.java b/src/main/java/info/pionas/quiz/web/home/HomeController.java index 503b361..2f49ddf 100644 --- a/src/main/java/info/pionas/quiz/web/home/HomeController.java +++ b/src/main/java/info/pionas/quiz/web/home/HomeController.java @@ -5,8 +5,6 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; -import org.thymeleaf.spring6.context.webflux.IReactiveDataDriverContextVariable; -import org.thymeleaf.spring6.context.webflux.ReactiveDataDriverContextVariable; @Controller @AllArgsConstructor @@ -16,9 +14,7 @@ class HomeController { @RequestMapping("/") public String index(final Model model) { - IReactiveDataDriverContextVariable reactiveDataDrivenMode = - new ReactiveDataDriverContextVariable(quizService.getLastAdded(), 1); - model.addAttribute("quizes", reactiveDataDrivenMode); + model.addAttribute("quizes", quizService.getLastAdded()); return "home/index"; } diff --git a/src/test/java/info/pionas/quiz/api/exam/ExamRestControllerIT.java b/src/test/java/info/pionas/quiz/api/exam/ExamRestControllerIT.java index aadaba8..7949fd8 100644 --- a/src/test/java/info/pionas/quiz/api/exam/ExamRestControllerIT.java +++ b/src/test/java/info/pionas/quiz/api/exam/ExamRestControllerIT.java @@ -15,6 +15,7 @@ import org.springframework.test.context.jdbc.Sql; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.reactive.function.BodyInserters; +import reactor.core.publisher.Flux; import java.io.IOException; import java.util.Collections; @@ -27,7 +28,7 @@ class ExamRestControllerIT extends AbstractIT { @Test - void should_throw_unauthorized_when_try_to_end_exam_by_quest() { + void should_throw_unauthorized_when_try_to_end_exam_by_quest() throws IOException { //given //when final var response = webTestClient.post().uri("/api/v1/exam") @@ -36,7 +37,28 @@ void should_throw_unauthorized_when_try_to_end_exam_by_quest() { .returnResult(HttpClientErrorException.class); //then assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); - assertThat(response.getResponseBodyContent()).isEmpty(); + assertThat(response.getResponseBodyContent()).isNotNull(); + final var errorJson = objectMapper.readTree(response.getResponseBodyContent()); + String error = errorJson.get("error").textValue(); + assertThat(error).isNotNull(); + assertThat(error).isEqualTo("Unauthorized"); + } + + @Test + void should_throw_unauthorized_when_try_to_get_exams_by_quest() throws IOException { + //given + //when + final var response = webTestClient.get().uri("/api/v1/exam") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .returnResult(HttpClientErrorException.class); + //then + assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); + assertThat(response.getResponseBodyContent()).isNotNull(); + final var errorJson = objectMapper.readTree(response.getResponseBodyContent()); + String error = errorJson.get("error").textValue(); + assertThat(error).isNotNull(); + assertThat(error).isEqualTo("Unauthorized"); } @Test diff --git a/src/test/java/info/pionas/quiz/api/quiz/QuizRestControllerIT.java b/src/test/java/info/pionas/quiz/api/quiz/QuizRestControllerIT.java index a0fec3a..a2b648f 100644 --- a/src/test/java/info/pionas/quiz/api/quiz/QuizRestControllerIT.java +++ b/src/test/java/info/pionas/quiz/api/quiz/QuizRestControllerIT.java @@ -28,7 +28,7 @@ class QuizRestControllerIT extends AbstractIT { @Test - void should_throw_unauthorized_when_try_to_create_quiz_by_quest() { + void should_throw_unauthorized_when_try_to_create_quiz_by_quest() throws IOException { //given //when final var response = webTestClient.post().uri("/api/v1/quiz") @@ -37,7 +37,11 @@ void should_throw_unauthorized_when_try_to_create_quiz_by_quest() { .returnResult(HttpClientErrorException.class); //then assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); - assertThat(response.getResponseBodyContent()).isEmpty(); + assertThat(response.getResponseBodyContent()).isNotNull(); + final var errorJson = objectMapper.readTree(response.getResponseBodyContent()); + String error = errorJson.get("error").textValue(); + assertThat(error).isNotNull(); + assertThat(error).isEqualTo("Unauthorized"); } @Test @@ -108,7 +112,7 @@ void should_throw_forbidden_when_try_to_create_quiz() throws IOException { final var errors = StreamSupport .stream(errorJson.get("errors").spliterator(), false) .toList(); - assertThat(errors.getFirst().asText()).isEqualTo("Access is denied"); + assertThat(errors.getFirst().asText()).isEqualTo("Access Denied"); } @Test @@ -134,7 +138,7 @@ void should_throw_bad_request_when_try_to_create_quiz() throws IOException { } @Test - void should_throw_unauthorized_when_try_to_add_question_to_quiz_by_quest() { + void should_throw_unauthorized_when_try_to_add_question_to_quiz_by_quest() throws IOException { //given //when final var response = webTestClient.post().uri("/api/v1/quiz/f57342a1-8413-4d45-8465-6b41b8d72d3e/question") @@ -143,7 +147,11 @@ void should_throw_unauthorized_when_try_to_add_question_to_quiz_by_quest() { .returnResult(HttpClientErrorException.class); //then assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); - assertThat(response.getResponseBodyContent()).isEmpty(); + assertThat(response.getResponseBodyContent()).isNotNull(); + final var errorJson = objectMapper.readTree(response.getResponseBodyContent()); + String error = errorJson.get("error").textValue(); + assertThat(error).isNotNull(); + assertThat(error).isEqualTo("Unauthorized"); } @Test @@ -206,7 +214,7 @@ void should_throw_forbidden_when_try_to_add_question_to_quiz() throws IOExceptio final var errors = StreamSupport .stream(errorJson.get("errors").spliterator(), false) .toList(); - assertThat(errors.getFirst().asText()).isEqualTo("Access is denied"); + assertThat(errors.getFirst().asText()).isEqualTo("Access Denied"); } @Test @@ -254,7 +262,7 @@ void should_throw_not_found_when_try_add_question_but_quiz_by_id_not_exist() thr } @Test - void should_throw_unauthorized_when_try_to_delete_question_from_quiz_by_quest() { + void should_throw_unauthorized_when_try_to_delete_question_from_quiz_by_quest() throws IOException { //given //when final var response = webTestClient.delete().uri("/api/v1/quiz/b4a63897-60f7-4e94-846e-e199d8734144/question/ce703f5b-274c-4398-b855-d461887c7ed5") @@ -263,7 +271,11 @@ void should_throw_unauthorized_when_try_to_delete_question_from_quiz_by_quest() .returnResult(HttpClientErrorException.class); //then assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); - assertThat(response.getResponseBodyContent()).isEmpty(); + assertThat(response.getResponseBodyContent()).isNotNull(); + final var errorJson = objectMapper.readTree(response.getResponseBodyContent()); + String error = errorJson.get("error").textValue(); + assertThat(error).isNotNull(); + assertThat(error).isEqualTo("Unauthorized"); } @Test @@ -305,7 +317,7 @@ void should_throw_forbidden_when_try_to_delete_question_from_quiz() throws IOExc final var errors = StreamSupport .stream(errorJson.get("errors").spliterator(), false) .toList(); - assertThat(errors.getFirst().asText()).isEqualTo("Access is denied"); + assertThat(errors.getFirst().asText()).isEqualTo("Access Denied"); } @Test @@ -329,7 +341,7 @@ void should_throw_not_found_when_try_delete_question_but_quiz_by_id_not_exist() } @Test - void should_throw_unauthorized_when_try_to_update_question_to_quiz_by_quest() { + void should_throw_unauthorized_when_try_to_update_question_to_quiz_by_quest() throws IOException { //given //when final var response = webTestClient.patch().uri("/api/v1/quiz/f57342a1-8413-4d45-8465-6b41b8d72d3e/question") @@ -338,7 +350,11 @@ void should_throw_unauthorized_when_try_to_update_question_to_quiz_by_quest() { .returnResult(HttpClientErrorException.class); //then assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED); - assertThat(response.getResponseBodyContent()).isEmpty(); + assertThat(response.getResponseBodyContent()).isNotNull(); + final var errorJson = objectMapper.readTree(response.getResponseBodyContent()); + String error = errorJson.get("error").textValue(); + assertThat(error).isNotNull(); + assertThat(error).isEqualTo("Unauthorized"); } @Test @@ -402,7 +418,7 @@ void should_throw_forbidden_when_try_to_update_question_to_quiz() throws IOExcep final var errors = StreamSupport .stream(errorJson.get("errors").spliterator(), false) .toList(); - assertThat(errors.getFirst().asText()).isEqualTo("Access is denied"); + assertThat(errors.getFirst().asText()).isEqualTo("Access Denied"); } @Test diff --git a/src/test/java/info/pionas/quiz/web/home/HomeControllerIT.java b/src/test/java/info/pionas/quiz/web/home/HomeControllerIT.java new file mode 100644 index 0000000..4e87570 --- /dev/null +++ b/src/test/java/info/pionas/quiz/web/home/HomeControllerIT.java @@ -0,0 +1,19 @@ +package info.pionas.quiz.web.home; + +import info.pionas.quiz.api.AbstractIT; +import org.junit.jupiter.api.Test; + +class HomeControllerIT extends AbstractIT { + + @Test + void should_return_ok() { + //given + //when + final var response = webTestClient + .get().uri("/") + .exchange(); + //then + response.expectStatus().isOk(); + } + +} \ No newline at end of file