Skip to content

Commit

Permalink
#77 made the oas dependency optional and conditional
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioformosa committed Oct 21, 2022
1 parent b2906d0 commit 7f00f5d
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

public class OpenAPIConfigConsts {

final static public String BASIC_AUTH_SEC_OAS_SCHEME = "basic-auth";
final static public String QUARTZ_MANAGER_SEC_OAS_SCHEMA = "quartz-manager-auth";

}
61 changes: 30 additions & 31 deletions quartz-manager-parent/quartz-manager-starter-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,21 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-core</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down Expand Up @@ -116,28 +118,28 @@
</dependency>

<!-- Reactor -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-net</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>io.projectreactor.spring</groupId>
<artifactId>reactor-spring-context</artifactId>
<version>2.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.projectreactor</groupId>-->
<!-- <artifactId>reactor-core</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>io.projectreactor</groupId>-->
<!-- <artifactId>reactor-net</artifactId>-->
<!-- <version>2.0.8.RELEASE</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>io.projectreactor.spring</groupId>-->
<!-- <artifactId>reactor-spring-context</artifactId>-->
<!-- <version>2.0.7.RELEASE</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>io.netty</groupId>-->
<!-- <artifactId>netty-all</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-aop</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
Expand All @@ -148,16 +150,13 @@
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc-openapi.version}</version>
<optional>true</optional>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springdoc</groupId>-->
<!-- <artifactId>springdoc-openapi-security</artifactId>-->
<!-- <version>${openapi.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.1.11</version>
<optional>true</optional>
</dependency>

<!-- TEST -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,68 +1,49 @@
package it.fabioformosa.quartzmanager.api.configuration;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.oas.models.security.SecurityScheme;
import it.fabioformosa.quartzmanager.api.common.config.OpenAPIConfigConsts;
import it.fabioformosa.quartzmanager.api.common.config.QuartzManagerPaths;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.Optional;


@Slf4j
@Configuration
public class OpenApiConfig {

@ConditionalOnProperty(name = "quartz-manager.oas.enabled")
@ConditionalOnMissingBean
@Bean
public OpenAPI customOpenAPI(@Autowired(required = false) SecurityDiscover securityDiscover) {
OpenAPI openAPI = new OpenAPI()
.info(apiInfo());

if(securityDiscover != null)
openAPI
.components(new Components().addSecuritySchemes(OpenAPIConfigConsts.BASIC_AUTH_SEC_OAS_SCHEME, buildBasicAuthScheme()))
.path(QuartzManagerPaths.QUARTZ_MANAGER_LOGIN_PATH,
new PathItem().post(new Operation()
.operationId("login")
.tags(Arrays.asList("auth"))
.requestBody(new RequestBody().content(
new Content().addMediaType("application/x-www-form-urlencoded", new MediaType().schema(new Schema().type("object")
.addProperties("username", new StringSchema())
.addProperties("password", new PasswordSchema())
.required(Arrays.asList("username", "password"))
))))
.responses(new ApiResponses().addApiResponse("200", new ApiResponse().description("JWT Token to authenticate the next requests")))
.responses(new ApiResponses().addApiResponse("401", new ApiResponse().description("Unauthorized - Username or password are incorrect!")))
));

return openAPI;
}

private SecurityScheme buildBasicAuthScheme() {
return new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT");
}


private Info apiInfo() {
return new Info()
public OpenAPI quartzManagerOpenAPI() {
log.info("No OpenAPI found! Quart Manager is creating it...");
return new OpenAPI().info(new Info()
.title("QUARTZ MANAGER API")
.description("Quartz Manager - REST API")
.version("1.0.0")
.license(new License()
.name("Apache License 2.0")
.url("https://github.com/fabioformosa/quartz-manager/blob/master/LICENSE"));
}
.url("https://github.com/fabioformosa/quartz-manager/blob/master/LICENSE")));
}

@ConditionalOnProperty(name = "quartz-manager.oas.enabled")
@Bean
public GroupedOpenApi quartzManagerStoreOpenApi(@Autowired(required = false) @Qualifier("quartzManagerOpenApiCustomiser") Optional<OpenApiCustomiser> openApiCustomiser) {
String paths[] = {QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/**"};
GroupedOpenApi.Builder groupedOpenApiBuilder = GroupedOpenApi.builder().group("quartz-manager").pathsToMatch(paths);
openApiCustomiser.ifPresent(oaCustomizer -> groupedOpenApiBuilder.addOpenApiCustomiser(oaCustomizer));
return groupedOpenApiBuilder.build();
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import java.util.stream.Collectors;

@RequestMapping(QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/jobs")
@SecurityRequirement(name = OpenAPIConfigConsts.BASIC_AUTH_SEC_OAS_SCHEME)
@SecurityRequirement(name = OpenAPIConfigConsts.QUARTZ_MANAGER_SEC_OAS_SCHEMA)
@RestController
public class JobController {
final private JobService jobService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import static it.fabioformosa.quartzmanager.api.common.config.OpenAPIConfigConsts.BASIC_AUTH_SEC_OAS_SCHEME;
import static it.fabioformosa.quartzmanager.api.common.config.OpenAPIConfigConsts.QUARTZ_MANAGER_SEC_OAS_SCHEMA;
import static it.fabioformosa.quartzmanager.api.common.config.QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH;

/**
Expand All @@ -27,7 +27,7 @@
*/
@Slf4j
@RestController
@SecurityRequirement(name = BASIC_AUTH_SEC_OAS_SCHEME)
@SecurityRequirement(name = QUARTZ_MANAGER_SEC_OAS_SCHEMA)
@RequestMapping(SchedulerController.SCHEDULER_CONTROLLER_BASE_URL)
public class SchedulerController {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

@Slf4j
@RequestMapping(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL)
@SecurityRequirement(name = OpenAPIConfigConsts.BASIC_AUTH_SEC_OAS_SCHEME)
@SecurityRequirement(name = OpenAPIConfigConsts.QUARTZ_MANAGER_SEC_OAS_SCHEMA)
@RestController
public class SimpleTriggerController {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

import java.util.List;

import static it.fabioformosa.quartzmanager.api.common.config.OpenAPIConfigConsts.BASIC_AUTH_SEC_OAS_SCHEME;
import static it.fabioformosa.quartzmanager.api.common.config.OpenAPIConfigConsts.QUARTZ_MANAGER_SEC_OAS_SCHEMA;
import static it.fabioformosa.quartzmanager.api.common.config.QuartzManagerPaths.QUARTZ_MANAGER_BASE_CONTEXT_PATH;

@Slf4j
@RequestMapping(TriggerController.TRIGGER_CONTROLLER_BASE_URL)
@SecurityRequirement(name = BASIC_AUTH_SEC_OAS_SCHEME)
@SecurityRequirement(name = QUARTZ_MANAGER_SEC_OAS_SCHEMA)
@RestController
public class TriggerController {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc-openapi.version}</version>
<optional>true</optional>
</dependency>

<!-- TEST -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class QuartzManagerSecurityConfig {

private static final String[] PATTERNS_SWAGGER_UI = {"/swagger-ui.html", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**"};
private static final String[] PATTERNS_SWAGGER_UI = {"/swagger-ui/**", "/swagger-ui.html", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**"};
public static final String QUARTZ_MANAGER_API_ANT_MATCHER = QUARTZ_MANAGER_BASE_CONTEXT_PATH + "/**";
public static final String QUARTZ_MANAGER_UI_ANT_MATCHER = QuartzManagerPaths.WEBJAR_PATH + "/**";

Expand Down Expand Up @@ -121,11 +121,14 @@ public SecurityFilterChain filterChain(HttpSecurity http, @Qualifier("quartzMana
}

@Bean(name = "quartzManagerWebSecurityCustomizer")
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) ->
public WebSecurityCustomizer webSecurityCustomizer(@Value("${quartz-manager.oas.enabled:false}") Boolean oasEnabled) {
return (web) -> {
web.ignoring()//
.antMatchers(HttpMethod.GET, PATTERNS_SWAGGER_UI) //
.antMatchers(HttpMethod.GET, QUARTZ_MANAGER_UI_ANT_MATCHER);
if(BooleanUtils.isNotFalse(oasEnabled))
web.ignoring()
.antMatchers(HttpMethod.GET, PATTERNS_SWAGGER_UI);
};
}

@Bean(name = "quartzManagerCorsConfigurationSource")
Expand All @@ -151,8 +154,7 @@ public JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler() {
return jwtAuthenticationSuccessHandler;
}

// @Bean
public JwtTokenAuthenticationFilter jwtAuthenticationTokenFilter(UserDetailsService userDetailsService) throws Exception {
public JwtTokenAuthenticationFilter jwtAuthenticationTokenFilter(UserDetailsService userDetailsService) {
return new JwtTokenAuthenticationFilter(jwtTokenHelper(), userDetailsService);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package it.fabioformosa.quartzmanager.api.security.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.oas.models.security.SecurityScheme;
import it.fabioformosa.quartzmanager.api.common.config.OpenAPIConfigConsts;
import it.fabioformosa.quartzmanager.api.common.config.QuartzManagerPaths;
import it.fabioformosa.quartzmanager.api.security.properties.JwtSecurityProperties;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

import java.util.Arrays;

@Slf4j
@ConditionalOnProperty(name = "quartz-manager.oas.enabled")
@Configuration
public class SecurityOpenApiConfig {

@Order(Ordered.HIGHEST_PRECEDENCE)
@Bean("quartzManagerOpenApiCustomiser")
public OpenApiCustomiser configureQuartzManagerOpenAPI(JwtSecurityProperties jwtSecurityProps) {
return openAPI -> {
if (jwtSecurityProps.getCookieStrategy().isEnabled() == false)
openAPI
.components(new Components().addSecuritySchemes(OpenAPIConfigConsts.QUARTZ_MANAGER_SEC_OAS_SCHEMA, buildBasicAuthScheme()));

openAPI.path(QuartzManagerPaths.QUARTZ_MANAGER_LOGIN_PATH,
new PathItem().post(new Operation()
.operationId("login")
.tags(Arrays.asList("auth"))
.requestBody(new RequestBody().content(
new Content().addMediaType("application/x-www-form-urlencoded", new MediaType().schema(new Schema().type("object")
.addProperties("username", new StringSchema())
.addProperties("password", new PasswordSchema())
.required(Arrays.asList("username", "password"))
))))
.responses(new ApiResponses().addApiResponse("200", new ApiResponse().description("JWT Token to authenticate the next requests")))
.responses(new ApiResponses().addApiResponse("401", new ApiResponse().description("Unauthorized - Username or password are incorrect!")))
));
};
}

private SecurityScheme buildBasicAuthScheme() {
return new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("A JWT Token in required to access this API. You can obtain a JWT Token by providing the username and password in the login API");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

@RestController
@Hidden
@SecurityRequirement(name = OpenAPIConfigConsts.BASIC_AUTH_SEC_OAS_SCHEME)
@SecurityRequirement(name = OpenAPIConfigConsts.QUARTZ_MANAGER_SEC_OAS_SCHEMA)
@RequestMapping(value = QUARTZ_MANAGER_AUTH_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {

Expand Down
8 changes: 7 additions & 1 deletion quartz-manager-parent/quartz-manager-web-showcase/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<springfox.version>2.9.2</springfox.version>
<springdoc-openapi.version>1.5.12</springdoc-openapi.version>
<java.version>9</java.version>
</properties>

Expand Down Expand Up @@ -66,6 +66,12 @@
</dependency>

<!-- MISC -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc-openapi.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
Expand Down
Loading

0 comments on commit 7f00f5d

Please sign in to comment.