Skip to content

Commit

Permalink
Merge pull request #2814 from pascalgrimaud/springdoc-oauth2
Browse files Browse the repository at this point in the history
Add Springdoc module for OAuth2
  • Loading branch information
pascalgrimaud authored Jul 28, 2022
2 parents c5ee760 + 1676de0 commit 589e55d
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ public JHipsterModule buildSpringdocModule(JHipsterModuleProperties properties)
public JHipsterModule buildSpringdocModuleWithSecurityJWT(JHipsterModuleProperties properties) {
return springdocDomainService.buildSpringdocModuleWithSecurityJWT(properties);
}

public JHipsterModule buildSpringdocModuleWithSecurityOAuth2(JHipsterModuleProperties properties) {
return springdocDomainService.buildSpringdocModuleWithSecurityOAuth2(properties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public class SpringdocDomainService {
new ArtifactId("spring-boot-starter-webflux")
);

protected static final DependencyId OAUTH2_DEPENDENCY_ID = new DependencyId(
new GroupId("org.springframework.boot"),
new ArtifactId("spring-boot-starter-oauth2-client")
);

private final ProjectJavaDependenciesRepository projectJavaDependenciesRepository;
private final SpringdocModuleFactory springdocModuleFactory;

Expand All @@ -39,4 +44,13 @@ public JHipsterModule buildSpringdocModuleWithSecurityJWT(JHipsterModuleProperti
.map(d -> springdocModuleFactory.buildModuleWithSecurityJwtForWebflux(properties))
.orElse(springdocModuleFactory.buildModuleWithSecurityJwtForMvc(properties));
}

public JHipsterModule buildSpringdocModuleWithSecurityOAuth2(JHipsterModuleProperties properties) {
return projectJavaDependenciesRepository
.get(properties.projectFolder())
.dependencies()
.get(OAUTH2_DEPENDENCY_ID)
.map(d -> springdocModuleFactory.buildModuleWithSecurityOAuth2ForMvc(properties))
.orElse(springdocModuleFactory.buildModuleForMvc(properties));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class SpringdocModuleFactory {

private static final String SPRINGDOC_CONFIG_JAVA_FILE = "SpringdocConfiguration.java";
private static final String SPRINGDOC_CONFIG_SECURITY_JWT_JAVA_FILE = "SpringdocConfigurationSecurityJWT.java";
private static final String SPRINGDOC_CONFIG_SECURITY_OAUTH2_JAVA_FILE = "SpringdocConfigurationSecurityOAuth2.java";

private static final String SPRINGDOC_GROUP_ID = "org.springdoc";
private static final String SPRINGDOC_OPENAPI_VERSION_KEY = "springdoc-openapi.version";
Expand All @@ -34,23 +35,55 @@ public class SpringdocModuleFactory {
.versionSlug(SPRINGDOC_OPENAPI_VERSION_KEY)
.build();

public static final JavaDependency SPRINGDOC_OPENAPI_SECURITY_DEPENDENCY = JavaDependency
.builder()
.groupId(SPRINGDOC_GROUP_ID)
.artifactId("springdoc-openapi-security")
.versionSlug(SPRINGDOC_OPENAPI_VERSION_KEY)
.build();

public JHipsterModule buildModuleForMvc(JHipsterModuleProperties moduleProperties) {
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_UI_DEPENDENCY, SPRINGDOC_CONFIG_JAVA_FILE);
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_UI_DEPENDENCY, SPRINGDOC_CONFIG_JAVA_FILE).build();
}

public JHipsterModule buildModuleForWebflux(JHipsterModuleProperties moduleProperties) {
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_WEBFLUX_UI_DEPENDENCY, SPRINGDOC_CONFIG_JAVA_FILE);
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_WEBFLUX_UI_DEPENDENCY, SPRINGDOC_CONFIG_JAVA_FILE).build();
}

public JHipsterModule buildModuleWithSecurityJwtForMvc(JHipsterModuleProperties moduleProperties) {
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_UI_DEPENDENCY, SPRINGDOC_CONFIG_SECURITY_JWT_JAVA_FILE);
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_UI_DEPENDENCY, SPRINGDOC_CONFIG_SECURITY_JWT_JAVA_FILE).build();
}

public JHipsterModule buildModuleWithSecurityJwtForWebflux(JHipsterModuleProperties moduleProperties) {
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_WEBFLUX_UI_DEPENDENCY, SPRINGDOC_CONFIG_SECURITY_JWT_JAVA_FILE);
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_WEBFLUX_UI_DEPENDENCY, SPRINGDOC_CONFIG_SECURITY_JWT_JAVA_FILE).build();
}

private JHipsterModule buildModule(
public JHipsterModule buildModuleWithSecurityOAuth2ForMvc(JHipsterModuleProperties moduleProperties) {
// prettier-ignore
return buildModule(moduleProperties, SPRINGDOC_OPENAPI_UI_DEPENDENCY, SPRINGDOC_CONFIG_SECURITY_OAUTH2_JAVA_FILE)
.javaDependencies()
.addDependency(SPRINGDOC_OPENAPI_SECURITY_DEPENDENCY)
.and()
.springMainProperties()
.set(propertyKey("springdoc.swagger-ui.oauth.client-id"), propertyValue("web_app"))
.set(propertyKey("springdoc.swagger-ui.oauth.realm"), propertyValue("jhipster"))
.set(
propertyKey("springdoc.oauth2.authorization-url"),
propertyValue("http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/auth")
)
.and()
.springTestProperties()
.set(propertyKey("springdoc.swagger-ui.oauth.client-id"), propertyValue("web_app"))
.set(propertyKey("springdoc.swagger-ui.oauth.realm"), propertyValue("jhipster"))
.set(
propertyKey("springdoc.oauth2.authorization-url"),
propertyValue("http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/auth")
)
.and()
.build();
}

private JHipsterModuleBuilder buildModule(
JHipsterModuleProperties properties,
JavaDependency springdocJavaDependency,
String srcSpringdocJavaFile
Expand Down Expand Up @@ -80,8 +113,7 @@ private JHipsterModule buildModule(
.set(propertyKey("springdoc.swagger-ui.operationsSorter"), propertyValue("alpha"))
.set(propertyKey("springdoc.swagger-ui.tagsSorter"), propertyValue("alpha"))
.set(propertyKey("springdoc.swagger-ui.tryItOutEnabled"), propertyValue("true"))
.and()
.build();
.and();
//@formatter:on
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ class SpringdocModuleConfiguration {

private static final String SPRINGDOC_API_URL = "/api/servers/spring-boot/api-documentations/springdoc";

public static final String TAG_SERVER = "server";
public static final String TAG_SPRING = "spring";
public static final String TAG_SPRING_BOOT = "spring-boot";
public static final String TAG_DOCUMENTATION = "documentation";

@Bean
JHipsterModuleResource springdocModule(SpringdocApplicationService springdocApplicationService) {
return JHipsterModuleResource
Expand All @@ -20,7 +25,7 @@ JHipsterModuleResource springdocModule(SpringdocApplicationService springdocAppl
.slug("springdoc-openapi")
.propertiesDefinition(buildPropertiesDefinition())
.apiDoc(new JHipsterModuleApiDoc("Spring Boot - API Documentation", "Add springdoc-openapi"))
.tags("server", "spring", "spring-boot", "documentation")
.tags(TAG_SERVER, TAG_SPRING, TAG_SPRING_BOOT, TAG_DOCUMENTATION)
.factory(springdocApplicationService::buildSpringdocModule);
}

Expand All @@ -32,10 +37,22 @@ JHipsterModuleResource springdocWithSecurityJwtModule(SpringdocApplicationServic
.slug("springdoc-openapi-with-security-jwt")
.propertiesDefinition(buildPropertiesDefinition())
.apiDoc(new JHipsterModuleApiDoc("Spring Boot - API Documentation - Security", "Add springdoc-openapi with Security JWT"))
.tags("server", "spring", "spring-boot", "documentation")
.tags(TAG_SERVER, TAG_SPRING, TAG_SPRING_BOOT, TAG_DOCUMENTATION)
.factory(springdocApplicationService::buildSpringdocModuleWithSecurityJWT);
}

@Bean
JHipsterModuleResource springdocWithSecurityOAuth2Module(SpringdocApplicationService springdocApplicationService) {
return JHipsterModuleResource
.builder()
.legacyUrl(SPRINGDOC_API_URL + "/init-with-security-oauth2")
.slug("springdoc-openapi-with-security-oauth2")
.propertiesDefinition(buildPropertiesDefinition())
.apiDoc(new JHipsterModuleApiDoc("Spring Boot - API Documentation - Security", "Add springdoc-openapi with Security OAuth2"))
.tags(TAG_SERVER, TAG_SPRING, TAG_SPRING_BOOT, TAG_DOCUMENTATION, "authentication", "oauth2")
.factory(springdocApplicationService::buildSpringdocModuleWithSecurityOAuth2);
}

private JHipsterModulePropertiesDefinition buildPropertiesDefinition() {
return JHipsterModulePropertiesDefinition.builder().addBasePackage().addProjectBaseName().addIndentation().build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package {{packageName}}.technical.infrastructure.primary.springdoc;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import java.util.Arrays;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringdocConfiguration {
@Value("${application.version:undefined}")
private String version;
@Value("${springdoc.oauth2.authorization-url}")
private String authorizationUrl;
@Bean
public OpenAPI {{baseNameLowercase}}OpenAPI() {
return new OpenAPI()
.components(
new Components()
.addSecuritySchemes(
"security_auth",
new SecurityScheme()
.type(SecurityScheme.Type.OAUTH2)
.flows(new OAuthFlows().implicit(new OAuthFlow().authorizationUrl(authorizationUrl)))
)
)
.addSecurityItem(new SecurityRequirement().addList("security_auth", Arrays.asList("jhipster")))
.info(
new Info()
.title("{{apiTitle}}")
.description("{{apiDescription}}")
.version(version)
.license(new License().name("{{apiLicenseName}}").url("{{apiLicenseUrl}}"))
)
.externalDocs(new ExternalDocumentation().description("{{apiExternalDocDescription}}").url("{{apiExternalDocUrl}}"));
}

@Bean
public GroupedOpenApi {{baseNameLowercase}}AllOpenAPI() {
// prettier-ignore
return GroupedOpenApi.builder()
.group("all")
.pathsToMatch("/api/**")
.build();
}
}
17 changes: 17 additions & 0 deletions src/test/features/springdoc.feature
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ Feature: Springdoc modules
And I should have files in "src/test/resources/config"
| application.properties |

Scenario: Should add Springdoc for MVC with OAuth2 Security
When I apply modules to default project
| maven-java |
| springboot |
| springboot-oauth2 |
| springdoc-openapi-with-security-oauth2 |
Then I should have files in ""
| pom.xml |
And I should have "springdoc-openapi-ui" in "pom.xml"
And I should have files in "src/main/java/tech/jhipster/chips/technical/infrastructure/primary/springdoc"
| SpringdocConfiguration.java |
And I should have "OAUTH2" in "src/main/java/tech/jhipster/chips/technical/infrastructure/primary/springdoc/SpringdocConfiguration.java"
And I should have files in "src/main/resources/config"
| application.properties |
And I should have files in "src/test/resources/config"
| application.properties |

Scenario: Should add Springdoc for Webflux with JWT Security
When I apply modules to default project
| maven-java |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import tech.jhipster.lite.TestFileUtils;
import tech.jhipster.lite.UnitTest;
Expand Down Expand Up @@ -98,11 +99,52 @@ void shouldBuildModuleWithSecurityJwtForWebflux() {
assertAddedProperties(moduleAsserter);
}

@Test
@DisplayName("should build module with Security OAuth2 for MVC")
void shouldBuildModuleWithSecurityOAuth2ForMvc() {
JHipsterModuleProperties moduleProperties = JHipsterModulesFixture
.propertiesBuilder(TestFileUtils.tmpDirForTest())
.basePackage("tech.jhipster.free")
.projectBaseName("freelance")
.build();

JHipsterModule module = springdocModuleFactory.buildModuleWithSecurityOAuth2ForMvc(moduleProperties);

// prettier-ignore
ModuleAsserter moduleAsserter = assertThatModuleWithFiles(module, pomFile())
.createFile("src/main/java/tech/jhipster/free/technical/infrastructure/primary/springdoc/SpringdocConfiguration.java")
.containing("OAUTH2")
.and()
.createFile("pom.xml")
.containing("<artifactId>springdoc-openapi-ui</artifactId>")
.containing("<artifactId>springdoc-openapi-security</artifactId>")
.notContaining("<artifactId>springdoc-openapi-webflux-ui</artifactId>")
.and();

assertAddedPropertiesWithOAuth2(moduleAsserter);
}

private void assertAddedProperties(ModuleAsserter moduleFileAsserter) {
moduleFileAsserter
.createFile("src/main/resources/config/application.properties")
.containing("springdoc.swagger-ui.operationsSorter=alpha")
.containing("springdoc.swagger-ui.tagsSorter=alpha")
.containing("springdoc.swagger-ui.tryItOutEnabled=true");
}

private void assertAddedPropertiesWithOAuth2(ModuleAsserter moduleFileAsserter) {
assertAddedProperties(moduleFileAsserter);

// prettier-ignore
moduleFileAsserter
.createFile("src/main/resources/config/application.properties")
.containing("springdoc.swagger-ui.oauth.client-id=web_app")
.containing("springdoc.swagger-ui.oauth.realm=jhipster")
.containing("springdoc.oauth2.authorization-url=http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/auth")
.and()
.createFile("src/test/resources/config/application.properties")
.containing("springdoc.swagger-ui.oauth.client-id=web_app")
.containing("springdoc.swagger-ui.oauth.realm=jhipster")
.containing("springdoc.oauth2.authorization-url=http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/auth");
}
}

0 comments on commit 589e55d

Please sign in to comment.