mirror of https://github.com/halo-dev/halo
Refine Swagger API with group (#2273)
#### What type of PR is this? /kind feature /area core /milestone 2.0 #### What this PR does / why we need it: 1. Add grouped OpenAPI <img width="505" alt="image" src="https://user-images.githubusercontent.com/16865714/180638783-acd5f437-b5d0-4701-9ebb-3221540f167c.png"> 3. Enable basic authentication on API endpoints. ```bash curl -s -u admin:iY4PcvZLN4Dm0woV --basic 'http://localhost:8090/api/v1alpha1/users' ``` #### Does this PR introduce a user-facing change? ```release-note None ```pull/2274/head
parent
d85c83bf6e
commit
71f9209006
|
@ -3,7 +3,9 @@ package run.halo.app.config;
|
||||||
import io.swagger.v3.oas.models.Components;
|
import io.swagger.v3.oas.models.Components;
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
import io.swagger.v3.oas.models.info.Info;
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
|
import org.springdoc.core.models.GroupedOpenApi;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ -13,14 +15,53 @@ public class SwaggerConfig {
|
||||||
@Bean
|
@Bean
|
||||||
OpenAPI customOpenAPI() {
|
OpenAPI customOpenAPI() {
|
||||||
return new OpenAPI()
|
return new OpenAPI()
|
||||||
|
// See https://swagger.io/docs/specification/authentication/ for more.
|
||||||
.components(new Components()
|
.components(new Components()
|
||||||
.addSecuritySchemes("basicScheme", new SecurityScheme()
|
.addSecuritySchemes("BasicAuth", new SecurityScheme()
|
||||||
.type(SecurityScheme.Type.HTTP).scheme("basic"))
|
.type(SecurityScheme.Type.HTTP).scheme("basic"))
|
||||||
.addSecuritySchemes("bearerAuth", new SecurityScheme()
|
.addSecuritySchemes("BearerAuth", new SecurityScheme()
|
||||||
.type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT"))
|
.type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT"))
|
||||||
)
|
)
|
||||||
|
.addSecurityItem(new SecurityRequirement().addList("BasicAuth").addList("BearerAuth"))
|
||||||
.info(new Info().title("Halo Next API")
|
.info(new Info().title("Halo Next API")
|
||||||
.version("2.0.0"));
|
.version("2.0.0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
GroupedOpenApi extensionCoreApi() {
|
||||||
|
return GroupedOpenApi.builder()
|
||||||
|
.group("CoreAPI")
|
||||||
|
.displayName("Core API")
|
||||||
|
.pathsToMatch("/api/**")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
GroupedOpenApi extensionApi() {
|
||||||
|
return GroupedOpenApi.builder()
|
||||||
|
.group("ExtensionAPI")
|
||||||
|
.displayName("Extension API")
|
||||||
|
.pathsToMatch("/apis/**")
|
||||||
|
.pathsToExclude("/apis/api.halo.run/**", "/apis/plugin.api.halo.run/**")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
GroupedOpenApi systemCustomApi() {
|
||||||
|
return GroupedOpenApi.builder()
|
||||||
|
.group("SystemCustomAPI")
|
||||||
|
.displayName("System Custom API")
|
||||||
|
.pathsToMatch("/apis/api.halo.run/**")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
GroupedOpenApi pluginCustomApi() {
|
||||||
|
return GroupedOpenApi.builder()
|
||||||
|
.group("PluginCustomAPI")
|
||||||
|
.displayName("Plugin Custom API")
|
||||||
|
.pathsToMatch("/apis/plugin.api.halo.run/**")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ public class WebServerSecurityConfig {
|
||||||
.securityMatcher(pathMatchers("/api/**", "/apis/**"))
|
.securityMatcher(pathMatchers("/api/**", "/apis/**"))
|
||||||
.authorizeExchange(exchanges ->
|
.authorizeExchange(exchanges ->
|
||||||
exchanges.anyExchange().access(new RequestInfoAuthorizationManager(roleService)))
|
exchanges.anyExchange().access(new RequestInfoAuthorizationManager(roleService)))
|
||||||
|
.httpBasic(withDefaults())
|
||||||
// for reuse the JWT authentication
|
// for reuse the JWT authentication
|
||||||
.oauth2ResourceServer().jwt();
|
.oauth2ResourceServer().jwt();
|
||||||
|
|
||||||
|
@ -82,7 +83,6 @@ public class WebServerSecurityConfig {
|
||||||
context);
|
context);
|
||||||
|
|
||||||
http.addFilterAt(loginFilter, SecurityWebFiltersOrder.FORM_LOGIN);
|
http.addFilterAt(loginFilter, SecurityWebFiltersOrder.FORM_LOGIN);
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,8 @@ public class WebServerSecurityConfig {
|
||||||
@Order(0)
|
@Order(0)
|
||||||
SecurityWebFilterChain webFilterChain(ServerHttpSecurity http) {
|
SecurityWebFilterChain webFilterChain(ServerHttpSecurity http) {
|
||||||
http.authorizeExchange(exchanges -> exchanges.pathMatchers(
|
http.authorizeExchange(exchanges -> exchanges.pathMatchers(
|
||||||
"/actuator/**"
|
"/actuator/**",
|
||||||
|
"/swagger-ui.html", "/webjars/**", "/v3/api-docs/**"
|
||||||
).permitAll())
|
).permitAll())
|
||||||
.cors(corsSpec -> corsSpec.configurationSource(apiCorsConfigurationSource()))
|
.cors(corsSpec -> corsSpec.configurationSource(apiCorsConfigurationSource()))
|
||||||
.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
|
.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
|
||||||
|
|
|
@ -31,14 +31,10 @@ springdoc:
|
||||||
enabled: true
|
enabled: true
|
||||||
swagger-ui:
|
swagger-ui:
|
||||||
enabled: true
|
enabled: true
|
||||||
show-login-endpoint: true
|
|
||||||
show-actuator: true
|
show-actuator: true
|
||||||
use-management-port: false
|
|
||||||
|
|
||||||
management:
|
management:
|
||||||
endpoints:
|
endpoints:
|
||||||
web:
|
web:
|
||||||
exposure:
|
exposure:
|
||||||
include: openapi, swagger-ui
|
include: "*"
|
||||||
server:
|
|
||||||
port: 9090
|
|
||||||
|
|
Loading…
Reference in New Issue