Skip to content

Commit 7ad9761

Browse files
committed
squash
# Conflicts: # modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java # modules/openapi-generator/src/main/resources/JavaJaxRS/spec/libraries/quarkus/apiInterface.mustache # modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java
1 parent 796729e commit 7ad9761

15 files changed

Lines changed: 402 additions & 1 deletion

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaJAXRSSpecServerCodegen.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,13 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
360360
additionalProperties.put("hasResponseStatusAnnotations", true);
361361
}
362362
}
363+
if (QUARKUS_LIBRARY.equals(getLibrary())) {
364+
for (CodegenOperation op : objs.getOperations().getOperation()) {
365+
if (shouldAddAuthenticatedAnnotation(op)){
366+
op.vendorExtensions.put("x-quarkus-authenticated", true);
367+
}
368+
}
369+
}
363370
return objs;
364371
}
365372

@@ -384,4 +391,16 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
384391
}
385392
return result;
386393
}
394+
395+
protected boolean shouldAddAuthenticatedAnnotation(CodegenOperation op) {
396+
if (!op.hasAuthMethods) {
397+
return false;
398+
}
399+
return op.authMethods.stream().anyMatch(m ->
400+
(Boolean.TRUE.equals(m.isOAuth) && (m.scopes == null || m.scopes.isEmpty())) ||
401+
(Boolean.TRUE.equals(m.isOpenId) && (m.scopes == null || m.scopes.isEmpty())) ||
402+
Boolean.TRUE.equals(m.isBasicBasic) ||
403+
Boolean.TRUE.equals(m.isApiKey)
404+
);
405+
}
387406
}

modules/openapi-generator/src/main/resources/JavaJaxRS/spec/libraries/quarkus/apiInterface.mustache

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,7 @@
5353
{{#vendorExtensions.x-java-success-response-code}}
5454
@ResponseStatus({{{vendorExtensions.x-java-success-response-code}}})
5555
{{/vendorExtensions.x-java-success-response-code}}
56+
{{#vendorExtensions.x-quarkus-authenticated}}
57+
@io.quarkus.security.Authenticated
58+
{{/vendorExtensions.x-quarkus-authenticated}}
5659
{{#supportAsync}}{{>returnAsyncTypeInterface}}{{/supportAsync}}{{^supportAsync}}{{#returnJBossResponse}}{{>returnResponseTypeInterface}}{{/returnJBossResponse}}{{^returnJBossResponse}}{{#returnResponse}}Response{{/returnResponse}}{{^returnResponse}}{{>returnTypeInterface}}{{/returnResponse}}{{/returnJBossResponse}}{{/supportAsync}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>cookieParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}});

modules/openapi-generator/src/main/resources/JavaJaxRS/spec/libraries/quarkus/apiMethod.mustache

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
{{^vendorExtensions.x-java-is-response-void}}@org.eclipse.microprofile.openapi.annotations.media.Content(schema = @org.eclipse.microprofile.openapi.annotations.media.Schema(implementation = {{{baseType}}}.class{{#vendorExtensions.x-microprofile-open-api-return-schema-container}}, type = {{{.}}} {{/vendorExtensions.x-microprofile-open-api-return-schema-container}}{{#vendorExtensions.x-microprofile-open-api-return-unique-items}}, uniqueItems = true {{/vendorExtensions.x-microprofile-open-api-return-unique-items}})){{/vendorExtensions.x-java-is-response-void}}
4848
}){{^-last}},{{/-last}}{{/responses}}
4949
}){{/hasProduces}}{{/useMicroProfileOpenAPIAnnotations}}
50+
{{#vendorExtensions.x-quarkus-authenticated}}
51+
@io.quarkus.security.Authenticated
52+
{{/vendorExtensions.x-quarkus-authenticated}}
5053
public {{#supportAsync}}{{#useMutiny}}Uni{{/useMutiny}}{{^useMutiny}}CompletionStage{{/useMutiny}}<{{/supportAsync}}{{#returnJBossResponse}}{{>returnResponseTypeInterface}}{{/returnJBossResponse}}{{^returnJBossResponse}}Response{{/returnJBossResponse}}{{#supportAsync}}>{{/supportAsync}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>cookieParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}) {
5154
return {{#supportAsync}}{{#useMutiny}}Uni.createFrom().item({{/useMutiny}}{{^useMutiny}}CompletableFuture.supplyAsync(() -> {{/useMutiny}}{{/supportAsync}}Response.ok().entity("magic!").build(){{#supportAsync}}){{/supportAsync}};
5255
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java

Lines changed: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ public void generateApiWithAsyncSupportAndInterfaceOnlyAndJBossResponse() throws
552552
//And the generated interface contains CompletionStage<RestResponse<Pet>>
553553
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/PetApi.java");
554554
assertFileContains(output.toPath().resolve("src/gen/java/org/openapitools/api/PetApi.java"),
555-
"\nimport org.jboss.resteasy.reactive.RestResponse;\n",
555+
"\nimport org.jboss.resteasy.reactive.RestResponse;\n",
556556
"\nimport java.util.concurrent.CompletionStage;\n",
557557
"CompletionStage<RestResponse<Pet>> addPet", "CompletionStage<RestResponse<Void>> deletePet");
558558
}
@@ -1545,4 +1545,226 @@ public void generateQuarkusConcreteClassDoesNotAddResponseStatusAnnotation() thr
15451545
"@ResponseStatus",
15461546
"import org.jboss.resteasy.reactive.ResponseStatus");
15471547
}
1548+
1549+
@Test
1550+
public void generateQuarkusInterfaceWithAuthenticatedForOAuth2EmptyScopes() throws Exception {
1551+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1552+
output.deleteOnExit();
1553+
1554+
final OpenAPI openAPI = new OpenAPIParser()
1555+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-no-scopes.yaml", null, new ParseOptions()).getOpenAPI();
1556+
1557+
codegen.setOutputDir(output.getAbsolutePath());
1558+
codegen.setLibrary(QUARKUS_LIBRARY);
1559+
codegen.additionalProperties().put(INTERFACE_ONLY, true);
1560+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1561+
1562+
final ClientOptInput input = new ClientOptInput()
1563+
.openAPI(openAPI)
1564+
.config(codegen);
1565+
1566+
final DefaultGenerator generator = new DefaultGenerator();
1567+
final List<File> files = generator.opts(input).generate();
1568+
1569+
validateJavaSourceFiles(files);
1570+
1571+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1572+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1573+
assertFileContains(defaultApi, "@io.quarkus.security.Authenticated");
1574+
}
1575+
1576+
@Test
1577+
public void generateQuarkusImplWithAuthenticatedForOAuth2EmptyScopes() throws Exception {
1578+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1579+
output.deleteOnExit();
1580+
1581+
final OpenAPI openAPI = new OpenAPIParser()
1582+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-no-scopes.yaml", null, new ParseOptions()).getOpenAPI();
1583+
1584+
codegen.setOutputDir(output.getAbsolutePath());
1585+
codegen.setLibrary(QUARKUS_LIBRARY);
1586+
codegen.additionalProperties().put(INTERFACE_ONLY, false);
1587+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1588+
1589+
final ClientOptInput input = new ClientOptInput()
1590+
.openAPI(openAPI)
1591+
.config(codegen);
1592+
1593+
final DefaultGenerator generator = new DefaultGenerator();
1594+
final List<File> files = generator.opts(input).generate();
1595+
1596+
validateJavaSourceFiles(files);
1597+
1598+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1599+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1600+
assertFileContains(defaultApi, "@io.quarkus.security.Authenticated");
1601+
}
1602+
1603+
@Test
1604+
public void generateQuarkusInterfaceWithoutAuthenticatedForOAuth2WithScopes() throws Exception {
1605+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1606+
output.deleteOnExit();
1607+
1608+
final OpenAPI openAPI = new OpenAPIParser()
1609+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-with-scopes.yaml", null, new ParseOptions()).getOpenAPI();
1610+
1611+
codegen.setOutputDir(output.getAbsolutePath());
1612+
codegen.setLibrary(QUARKUS_LIBRARY);
1613+
codegen.additionalProperties().put(INTERFACE_ONLY, true);
1614+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1615+
1616+
final ClientOptInput input = new ClientOptInput()
1617+
.openAPI(openAPI)
1618+
.config(codegen);
1619+
1620+
final DefaultGenerator generator = new DefaultGenerator();
1621+
final List<File> files = generator.opts(input).generate();
1622+
1623+
validateJavaSourceFiles(files);
1624+
1625+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1626+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1627+
assertFileNotContains(defaultApi, "@io.quarkus.security.Authenticated");
1628+
}
1629+
1630+
@Test
1631+
public void generateQuarkusImplWithoutAuthenticatedForOAuth2WithScopes() throws Exception {
1632+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1633+
output.deleteOnExit();
1634+
1635+
final OpenAPI openAPI = new OpenAPIParser()
1636+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-with-scopes.yaml", null, new ParseOptions()).getOpenAPI();
1637+
1638+
codegen.setOutputDir(output.getAbsolutePath());
1639+
codegen.setLibrary(QUARKUS_LIBRARY);
1640+
codegen.additionalProperties().put(INTERFACE_ONLY, false);
1641+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1642+
1643+
final ClientOptInput input = new ClientOptInput()
1644+
.openAPI(openAPI)
1645+
.config(codegen);
1646+
1647+
final DefaultGenerator generator = new DefaultGenerator();
1648+
final List<File> files = generator.opts(input).generate();
1649+
1650+
validateJavaSourceFiles(files);
1651+
1652+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1653+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1654+
assertFileNotContains(defaultApi, "@io.quarkus.security.Authenticated");
1655+
}
1656+
1657+
@Test
1658+
public void generateQuarkusInterfaceWithAuthenticatedOnceForOAuth2MultipleFlowsNoScopes() throws Exception {
1659+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1660+
output.deleteOnExit();
1661+
1662+
final OpenAPI openAPI = new OpenAPIParser()
1663+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-multi-flow-no-scopes.yaml", null, new ParseOptions()).getOpenAPI();
1664+
1665+
codegen.setOutputDir(output.getAbsolutePath());
1666+
codegen.setLibrary(QUARKUS_LIBRARY);
1667+
codegen.additionalProperties().put(INTERFACE_ONLY, true);
1668+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1669+
1670+
final ClientOptInput input = new ClientOptInput()
1671+
.openAPI(openAPI)
1672+
.config(codegen);
1673+
1674+
final DefaultGenerator generator = new DefaultGenerator();
1675+
final List<File> files = generator.opts(input).generate();
1676+
1677+
validateJavaSourceFiles(files);
1678+
1679+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1680+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1681+
String content = Files.readString(defaultApi);
1682+
Assert.assertEquals(TestUtils.countOccurrences(content, "@io\\.quarkus\\.security\\.Authenticated"), 1);
1683+
}
1684+
1685+
@Test
1686+
public void generateQuarkusImplWithAuthenticatedOnceForOAuth2MultipleFlowsNoScopes() throws Exception {
1687+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1688+
output.deleteOnExit();
1689+
1690+
final OpenAPI openAPI = new OpenAPIParser()
1691+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-multi-flow-no-scopes.yaml", null, new ParseOptions()).getOpenAPI();
1692+
1693+
codegen.setOutputDir(output.getAbsolutePath());
1694+
codegen.setLibrary(QUARKUS_LIBRARY);
1695+
codegen.additionalProperties().put(INTERFACE_ONLY, false);
1696+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1697+
1698+
final ClientOptInput input = new ClientOptInput()
1699+
.openAPI(openAPI)
1700+
.config(codegen);
1701+
1702+
final DefaultGenerator generator = new DefaultGenerator();
1703+
final List<File> files = generator.opts(input).generate();
1704+
1705+
validateJavaSourceFiles(files);
1706+
1707+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1708+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1709+
String content = Files.readString(defaultApi);
1710+
Assert.assertEquals(TestUtils.countOccurrences(content, "@io\\.quarkus\\.security\\.Authenticated"), 1);
1711+
}
1712+
1713+
@Test
1714+
public void generateQuarkusInterfaceWithAuthenticatedWhenOrSchemesIncludeEmptyScopes() throws Exception {
1715+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1716+
output.deleteOnExit();
1717+
1718+
final OpenAPI openAPI = new OpenAPIParser()
1719+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-or-empty-and-scoped.yaml", null, new ParseOptions()).getOpenAPI();
1720+
1721+
codegen.setOutputDir(output.getAbsolutePath());
1722+
codegen.setLibrary(QUARKUS_LIBRARY);
1723+
codegen.additionalProperties().put(INTERFACE_ONLY, true);
1724+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1725+
1726+
final ClientOptInput input = new ClientOptInput()
1727+
.openAPI(openAPI)
1728+
.config(codegen);
1729+
1730+
final DefaultGenerator generator = new DefaultGenerator();
1731+
final List<File> files = generator.opts(input).generate();
1732+
1733+
validateJavaSourceFiles(files);
1734+
1735+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1736+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1737+
// getItems (empty-scope OR scoped) → @Authenticated; createItem (scoped only) → none: count must be exactly 1
1738+
String content = Files.readString(defaultApi);
1739+
Assert.assertEquals(TestUtils.countOccurrences(content, "@io\\.quarkus\\.security\\.Authenticated"), 1);
1740+
}
1741+
1742+
@Test
1743+
public void generateQuarkusImplWithAuthenticatedWhenOrSchemesIncludeEmptyScopes() throws Exception {
1744+
final File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
1745+
output.deleteOnExit();
1746+
1747+
final OpenAPI openAPI = new OpenAPIParser()
1748+
.readLocation("src/test/resources/3_0/jaxrs-spec/quarkus-oauth2-or-empty-and-scoped.yaml", null, new ParseOptions()).getOpenAPI();
1749+
1750+
codegen.setOutputDir(output.getAbsolutePath());
1751+
codegen.setLibrary(QUARKUS_LIBRARY);
1752+
codegen.additionalProperties().put(INTERFACE_ONLY, false);
1753+
codegen.additionalProperties().put(USE_JAKARTA_EE, true);
1754+
1755+
final ClientOptInput input = new ClientOptInput()
1756+
.openAPI(openAPI)
1757+
.config(codegen);
1758+
1759+
final DefaultGenerator generator = new DefaultGenerator();
1760+
final List<File> files = generator.opts(input).generate();
1761+
1762+
validateJavaSourceFiles(files);
1763+
1764+
final Path defaultApi = output.toPath().resolve("src/gen/java/org/openapitools/api/ItemsApi.java");
1765+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/api/ItemsApi.java");
1766+
// getItems (empty-scope OR scoped) → @Authenticated; createItem (scoped only) → none: count must be exactly 1
1767+
String content = Files.readString(defaultApi);
1768+
Assert.assertEquals(TestUtils.countOccurrences(content, "@io\\.quarkus\\.security\\.Authenticated"), 1);
1769+
}
15481770
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
openapi: 3.0.1
2+
info:
3+
title: Quarkus OAuth2 multi-flow no scopes test
4+
version: '1.0'
5+
servers:
6+
- url: 'http://localhost:8080/'
7+
paths:
8+
/items:
9+
get:
10+
operationId: getItems
11+
summary: Get items
12+
security:
13+
- oauth2_scheme: []
14+
responses:
15+
'200':
16+
description: OK
17+
post:
18+
operationId: createItem
19+
summary: Create item
20+
responses:
21+
'201':
22+
description: Created
23+
components:
24+
securitySchemes:
25+
oauth2_scheme:
26+
type: oauth2
27+
flows:
28+
authorizationCode:
29+
authorizationUrl: https://example.com/oauth/authorize
30+
tokenUrl: https://example.com/oauth/token
31+
scopes: {}
32+
implicit:
33+
authorizationUrl: https://example.com/api/oauth/dialog
34+
scopes: {}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
openapi: 3.0.1
2+
info:
3+
title: Quarkus OAuth2 no scopes test
4+
version: '1.0'
5+
servers:
6+
- url: 'http://localhost:8080/'
7+
paths:
8+
/items:
9+
get:
10+
operationId: getItems
11+
summary: Get items
12+
security:
13+
- oauth2_scheme: []
14+
responses:
15+
'200':
16+
description: OK
17+
post:
18+
operationId: createItem
19+
summary: Create item
20+
responses:
21+
'201':
22+
description: Created
23+
components:
24+
securitySchemes:
25+
oauth2_scheme:
26+
type: oauth2
27+
flows:
28+
clientCredentials:
29+
tokenUrl: https://example.com/oauth/token
30+
scopes: {}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
openapi: 3.0.1
2+
info:
3+
title: Quarkus OAuth2 OR empty-and-scoped test
4+
version: '1.0'
5+
servers:
6+
- url: 'http://localhost:8080/'
7+
paths:
8+
/items:
9+
get:
10+
operationId: getItems
11+
summary: Get items — OR any-authenticated OR scoped
12+
security:
13+
- oauth2_no_scope: []
14+
- oauth2_with_scope:
15+
- admin
16+
responses:
17+
'200':
18+
description: OK
19+
post:
20+
operationId: createItem
21+
summary: Create item — scoped only
22+
security:
23+
- oauth2_with_scope:
24+
- admin
25+
responses:
26+
'201':
27+
description: Created
28+
components:
29+
securitySchemes:
30+
oauth2_no_scope:
31+
type: oauth2
32+
flows:
33+
clientCredentials:
34+
tokenUrl: https://example.com/oauth/token
35+
scopes: {}
36+
oauth2_with_scope:
37+
type: oauth2
38+
flows:
39+
clientCredentials:
40+
tokenUrl: https://example.com/oauth/token
41+
scopes:
42+
admin: Admin access

0 commit comments

Comments
 (0)