|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2024 the original author or authors. |
| 2 | + * Copyright 2002-2025 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
40 | 40 | import org.springframework.context.annotation.Bean;
|
41 | 41 | import org.springframework.context.annotation.Configuration;
|
42 | 42 | import org.springframework.context.annotation.Role;
|
| 43 | +import org.springframework.http.HttpStatusCode; |
| 44 | +import org.springframework.http.ResponseEntity; |
43 | 45 | import org.springframework.security.access.AccessDeniedException;
|
44 | 46 | import org.springframework.security.access.PermissionEvaluator;
|
45 | 47 | import org.springframework.security.access.annotation.Secured;
|
|
54 | 56 | import org.springframework.security.authorization.AuthorizationDeniedException;
|
55 | 57 | import org.springframework.security.authorization.method.AuthorizationAdvisor;
|
56 | 58 | import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory;
|
| 59 | +import org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory.TargetVisitor; |
57 | 60 | import org.springframework.security.authorization.method.AuthorizeReturnObject;
|
58 | 61 | import org.springframework.security.authorization.method.PrePostTemplateDefaults;
|
59 |
| -import org.springframework.security.config.Customizer; |
60 | 62 | import org.springframework.security.config.test.SpringTestContext;
|
61 | 63 | import org.springframework.security.config.test.SpringTestContextExtension;
|
62 | 64 | import org.springframework.security.core.Authentication;
|
|
65 | 67 | import org.springframework.security.test.context.support.WithMockUser;
|
66 | 68 | import org.springframework.stereotype.Component;
|
67 | 69 | import org.springframework.test.context.junit.jupiter.SpringExtension;
|
| 70 | +import org.springframework.web.servlet.ModelAndView; |
68 | 71 |
|
69 | 72 | import static org.assertj.core.api.Assertions.assertThat;
|
70 | 73 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
@@ -361,6 +364,48 @@ public void findByIdWhenUnauthorizedResultThenDenies() {
|
361 | 364 | assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> flight.getAltitude().block());
|
362 | 365 | }
|
363 | 366 |
|
| 367 | + @Test |
| 368 | + @WithMockUser(authorities = "airplane:read") |
| 369 | + public void findByIdWhenAuthorizedResponseEntityThenAuthorizes() { |
| 370 | + this.spring.register(AuthorizeResultConfig.class).autowire(); |
| 371 | + FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class); |
| 372 | + Flight flight = flights.webFindById("1").block().getBody(); |
| 373 | + assertThatNoException().isThrownBy(() -> flight.getAltitude().block()); |
| 374 | + assertThatNoException().isThrownBy(() -> flight.getSeats().block()); |
| 375 | + } |
| 376 | + |
| 377 | + @Test |
| 378 | + @WithMockUser(authorities = "seating:read") |
| 379 | + public void findByIdWhenUnauthorizedResponseEntityThenDenies() { |
| 380 | + this.spring.register(AuthorizeResultConfig.class).autowire(); |
| 381 | + FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class); |
| 382 | + Flight flight = flights.webFindById("1").block().getBody(); |
| 383 | + assertThatNoException().isThrownBy(() -> flight.getSeats().block()); |
| 384 | + assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> flight.getAltitude().block()); |
| 385 | + } |
| 386 | + |
| 387 | + @Test |
| 388 | + @WithMockUser(authorities = "airplane:read") |
| 389 | + public void findByIdWhenAuthorizedModelAndViewThenAuthorizes() { |
| 390 | + this.spring.register(AuthorizeResultConfig.class).autowire(); |
| 391 | + FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class); |
| 392 | + Flight flight = (Flight) flights.webViewFindById("1").block().getModel().get("flight"); |
| 393 | + assertThatNoException().isThrownBy(() -> flight.getAltitude().block()); |
| 394 | + assertThatNoException().isThrownBy(() -> flight.getSeats().block()); |
| 395 | + assertThat(flights.webViewFindById("5").block().getModel().get("flight")).isNull(); |
| 396 | + } |
| 397 | + |
| 398 | + @Test |
| 399 | + @WithMockUser(authorities = "seating:read") |
| 400 | + public void findByIdWhenUnauthorizedModelAndViewThenDenies() { |
| 401 | + this.spring.register(AuthorizeResultConfig.class).autowire(); |
| 402 | + FlightRepository flights = this.spring.getContext().getBean(FlightRepository.class); |
| 403 | + Flight flight = (Flight) flights.webViewFindById("1").block().getModel().get("flight"); |
| 404 | + assertThatNoException().isThrownBy(() -> flight.getSeats().block()); |
| 405 | + assertThatExceptionOfType(AccessDeniedException.class).isThrownBy(() -> flight.getAltitude().block()); |
| 406 | + assertThat(flights.webViewFindById("5").block().getModel().get("flight")).isNull(); |
| 407 | + } |
| 408 | + |
364 | 409 | @Test
|
365 | 410 | @WithMockUser(authorities = "seating:read")
|
366 | 411 | public void findAllWhenUnauthorizedResultThenDenies() {
|
@@ -659,8 +704,8 @@ public static class AuthorizeResultConfig {
|
659 | 704 |
|
660 | 705 | @Bean
|
661 | 706 | @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
662 |
| - static Customizer<AuthorizationAdvisorProxyFactory> skipValueTypes() { |
663 |
| - return (f) -> f.setTargetVisitor(AuthorizationAdvisorProxyFactory.TargetVisitor.defaultsSkipValueTypes()); |
| 707 | + static TargetVisitor skipValueTypes() { |
| 708 | + return TargetVisitor.defaultsSkipValueTypes(); |
664 | 709 | }
|
665 | 710 |
|
666 | 711 | @Bean
|
@@ -724,6 +769,22 @@ Mono<Void> remove(String id) {
|
724 | 769 | return Mono.empty();
|
725 | 770 | }
|
726 | 771 |
|
| 772 | + Mono<ResponseEntity<Flight>> webFindById(String id) { |
| 773 | + Flight flight = this.flights.get(id); |
| 774 | + if (flight == null) { |
| 775 | + return Mono.just(ResponseEntity.notFound().build()); |
| 776 | + } |
| 777 | + return Mono.just(ResponseEntity.ok(flight)); |
| 778 | + } |
| 779 | + |
| 780 | + Mono<ModelAndView> webViewFindById(String id) { |
| 781 | + Flight flight = this.flights.get(id); |
| 782 | + if (flight == null) { |
| 783 | + return Mono.just(new ModelAndView("error", HttpStatusCode.valueOf(404))); |
| 784 | + } |
| 785 | + return Mono.just(new ModelAndView("flights", Map.of("flight", flight))); |
| 786 | + } |
| 787 | + |
727 | 788 | }
|
728 | 789 |
|
729 | 790 | @AuthorizeReturnObject
|
|
0 commit comments