Skip to content

Commit 30d5501

Browse files
enable-security-generation | additional-api-type-annotations (#431)
* enable-security-generation | additional-api-type-annotations * removal of custom-register-providers and client-headers-factory * documentation | fixes * Update README.md Co-authored-by: Helber Belmiro <[email protected]> * global configs | fixes * config name validation | default-security-schema | refactor * fixes * OpenApiConfigValidator * config items refactor * Update deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiConfigValidator.java Co-authored-by: Helber Belmiro <[email protected]> * Update deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java Co-authored-by: Helber Belmiro <[email protected]> * Update deployment/src/test/java/io/quarkiverse/openapi/generator/deployment/OpenApiConfigValidatorTest.java Co-authored-by: Helber Belmiro <[email protected]> * last fixes * switch default values * token propagation factory --------- Co-authored-by: Helber Belmiro <[email protected]>
1 parent 60d6605 commit 30d5501

File tree

28 files changed

+504
-1397
lines changed

28 files changed

+504
-1397
lines changed

README.md

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ If a base package name is not provided, it will be used the default `org.openapi
7676

7777
Configuring `additional-model-type-annotations` will add all annotations to the generated model files (extra details can be found in [OpenApi Generator Doc](https://openapi-generator.tech/docs/generators/java/#config-options)).
7878

79+
The same way you can add any additional annotations to the generated api files with `additional-api-type-annotations`. Given you want to include Foo and Bar annotations, you must define additional-api-type-annotations as:
80+
81+
```properties
82+
quarkus.openapi-generator.codegen.spec.petstore_json.additional-api-type-annotations[email protected];@org.test.Bar
83+
```
84+
7985
> **⚠️** Note that the file name`petstore_json`is used to configure the specific information for each spec. We follow the [Environment Variables Mapping Rules](https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#environment-variables-mapping-rules) from Microprofile Configuration to sanitize the OpenAPI spec filename. Any non-alphabetic characters are replaced by an underscore `_`.
8086
8187
Run `mvn compile` to generate your classes in `target/generated-sources/open-api-json` path:
@@ -237,9 +243,9 @@ pattern: `quarkus.openapi-generator.[filename].auth.[security_scheme_name].[auth
237243
238244
If the OpenAPI specification file has `securitySchemes` definitions, but no [Security Requirement Object](https://spec.openapis.org/oas/v3.1.0#security-requirement-object) definitions, the generator can be configured to create these by default. In this case, for all operations without a security requirement the default one will be created. Note that the property value needs to match the name of a security scheme object definition, eg. `api_key` or `basic_auth` in the `securitySchemes` list above.
239245

240-
| Description | Property Key | Example |
241-
| -------------------- | -------------------------------------------------------------- | ---------------------------------------------------- |
242-
| Create security for the referenced security scheme | `quarkus.openapi-generator.codegen.default.security.scheme` | `quarkus.openapi-generator.codegen.default.security.scheme=api_key` |
246+
| Description | Property Key | Example |
247+
| -------------------- |-------------------------------------------------------------|---------------------------------------------------------------------|
248+
| Create security for the referenced security scheme | `quarkus.openapi-generator.codegen.default-security-scheme` | `quarkus.openapi-generator.codegen.default-security-scheme=api_key` |
243249

244250
See the module [security](integration-tests/security) for an example of how to use this feature.
245251

@@ -331,6 +337,9 @@ RESTEasy Reactive:
331337
<artifactId>quarkus-oidc-client-reactive-filter</artifactId>
332338
</dependency>
333339
```
340+
If authentication support doesn't suit your needs you can decide to disable it with `enable-security-generation=false`. In such case CompositeAuthenticationProvider and AuthenticationPropagationHeadersFactory wont be generated and used with your api.
341+
The option can be set globally with `quarkus.openapi-generator.codegen.enable-security-generation` or per api `quarkus.openapi-generator.codegen.spec.my_spec_yml.enable-security-generation`
342+
Custom authentication provider can be used with `additional-api-type-annotations`
334343

335344
See the module [generation-tests](integration-tests/generation-tests) for an example of how to use this feature.
336345

@@ -419,17 +428,7 @@ The token propagation can be used with type "oauth2" or "bearer" security scheme
419428
| `quarkus.openapi-generator.[filename].auth.[security_scheme_name].token-propagation=[true,false]` | `quarkus.openapi-generator.petstore_json.auth.petstore_auth.token-propagation=true`<br/>Enables the token propagation for all the operations that are secured with the `petstore_auth` scheme in the `petstore_json` file.
420429
| `quarkus.openapi-generator.[filename].auth.[security_scheme_name].header-name=[http_header_name]` | `quarkus.openapi-generator.petstore_json.auth.petstore_auth.header-name=MyHeaderName`<br/>Says that the authorization token to propagate will be read from the HTTP header `MyHeaderName` instead of the standard HTTP `Authorization` header.
421430

422-
## Headers propagation
423-
Custom headers propagation can be set via MicroProfile configuration `org.eclipse.microprofile.rest.client.propagateHeaders`.
424-
In order to consider this configuration you must force `@RegisterClientHeaders` to use its default MicroProfile `ClientHeadersFactory` implementation. Therefore there is an option `client-headers-factory` where you can set any implementation of `ClientHeadersFactory`.
425431

426-
| Description | Property Key | Example |
427-
| -------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
428-
| Bearer Token | `quarkus.openapi-generator.codegen.spec.[fileName].client-headers-factory` | `quarkus.openapi-generator.codegen.spec.open_weather_yaml.client-headers-factory=org.eclipse.microprofile.rest.client.ext.DefaultClientHeadersFactoryImpl` |
429-
430-
If `client-headers-factory` is set to `none` `@RegisterClientHeaders` will use its default implicit implementation as in the example above.
431-
432-
If no option is set then default generated `AuthenticationPropagationHeadersFactory` class is used.
433432

434433
## Circuit Breaker
435434

@@ -676,16 +675,6 @@ file. By default, these operations are generated. You can fine tune this behavio
676675

677676
Use the property key `<base_package>.api.MyClass.generateDeprecated=false` to disable the deprecated operations in the given API. For example `org.acme.openapi.simple.api.DefaultApi.generatedDeprecated=false`.
678677

679-
## Custom Register Providers for generated api
680-
681-
In some cases, we need custom `RegisterProvider` for generated api, e.g. logging. You can define your own Providers in `application.properties` :
682-
683-
| Property Key | Example |
684-
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
685-
| `quarkus.openapi-generator.codegen.spec.[filename].custom-register-providers` | `quarkus.openapi-generator.codegen.spec.simple_openapi_json.custom-register-providers=org.test.Foo,org.test.Bar`<br/>Provider classes are separated by commas |
686-
687-
With the above configuration, the extension generates your Rest Clients with a code similar to the following:
688-
689678
```java
690679
package org.acme.openapi.simple.api;
691680

Lines changed: 49 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.quarkiverse.openapi.generator.deployment;
22

33
import java.nio.file.Path;
4+
import java.util.Arrays;
5+
import java.util.List;
46
import java.util.Map;
7+
import java.util.stream.Collectors;
58

69
import io.quarkiverse.openapi.generator.deployment.codegen.OpenApiGeneratorOutputPaths;
710
import io.quarkus.runtime.annotations.ConfigItem;
@@ -11,56 +14,56 @@
1114

1215
// This configuration is read in codegen phase (before build time), the annotation is for document purposes and avoiding quarkus warns
1316
@ConfigRoot(name = CodegenConfig.CODEGEN_TIME_CONFIG_PREFIX, phase = ConfigPhase.BUILD_TIME)
14-
public class CodegenConfig {
17+
public class CodegenConfig extends GlobalCodegenConfig {
1518

1619
static final String CODEGEN_TIME_CONFIG_PREFIX = "openapi-generator.codegen";
1720

1821
public static final String API_PKG_SUFFIX = ".api";
1922
public static final String MODEL_PKG_SUFFIX = ".model";
20-
public static final String VERBOSE_PROPERTY_NAME = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".verbose";
21-
public static final String INPUT_BASE_DIR = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".input-base-dir";
22-
public static final String INCLUDE_FILES = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".include";
23-
public static final String EXCLUDE_FILES = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".exclude";
24-
public static final String VALIDATE_SPEC_PROPERTY_NAME = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".validateSpec";
25-
public static final String DEFAULT_SECURITY_SCHEME = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".default.security.scheme";
2623
// package visibility for unit tests
24+
static final String BUILD_TIME_GLOBAL_PREFIX_FORMAT = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".%s";
2725
static final String BUILD_TIME_SPEC_PREFIX_FORMAT = "quarkus." + CODEGEN_TIME_CONFIG_PREFIX + ".spec.%s";
28-
private static final String BASE_PACKAGE_PROP_FORMAT = "%s.base-package";
29-
private static final String SKIP_FORM_MODEL_PROP_FORMAT = "%s.skip-form-model";
30-
private static final String MUTINY_PROP_FORMAT = "%s.mutiny";
31-
private static final String ADDITIONAL_MODEL_TYPE_ANNOTATIONS_PROP_FORMAT = "%s.additional-model-type-annotations";
32-
private static final String TYPE_MAPPINGS_PROP_FORMAT = "%s.type-mappings";
33-
private static final String IMPORT_MAPPINGS_PROP_FORMAT = "%s.import-mappings";
34-
private static final String NORMALIZER_PROP_FORMAT = "%s.open-api-normalizer";
35-
private static final String CUSTOM_REGISTER_PROVIDERS_FORMAT = "%s.custom-register-providers";
36-
37-
private static final String RETURN_RESPONSE_PROP_FORMAT = "%s.return-response";
38-
private static final String CLIENT_HEADER_FACTORY_PROP_FORMAT = "%s.client-headers-factory";
26+
27+
public static final List<String> SUPPORTED_CONFIGURATIONS = Arrays.stream(ConfigName.values()).map(cn -> cn.name)
28+
.collect(Collectors.toList());
29+
30+
public enum ConfigName {
31+
//global configs
32+
VERBOSE("verbose"),
33+
INPUT_BASE_DIR("input-base-dir"),
34+
INCLUDE("include"),
35+
EXCLUDE("exclude"),
36+
VALIDATE_SPEC("validateSpec"),
37+
DEFAULT_SECURITY_SCHEME("default-security-scheme"),
38+
39+
//spec configs only
40+
BASE_PACKAGE("base-package"),
41+
42+
//global & spec configs
43+
SKIP_FORM_MODEL("skip-form-model"),
44+
MUTINY("mutiny"),
45+
ADDITIONAL_MODEL_TYPE_ANNOTATIONS("additional-model-type-annotations"),
46+
ADDITIONAL_API_TYPE_ANNOTATIONS("additional-api-type-annotations"),
47+
TYPE_MAPPINGS("type-mappings"),
48+
IMPORT_MAPPINGS("import-mappings"),
49+
NORMALIZER("open-api-normalizer"),
50+
RETURN_RESPONSE("return-response"),
51+
ENABLE_SECURITY_GENERATION("enable-security-generation");
52+
53+
private final String name;
54+
55+
ConfigName(String name) {
56+
this.name = name;
57+
}
58+
59+
}
3960

4061
/**
4162
* OpenAPI Spec details for codegen configuration.
4263
*/
4364
@ConfigItem(name = "spec")
4465
public Map<String, SpecItemConfig> specItem;
4566

46-
/**
47-
* Whether to log the internal generator codegen process in the default output or not.
48-
*/
49-
@ConfigItem(name = "verbose", defaultValue = "false")
50-
public boolean verbose;
51-
52-
/**
53-
* Whether or not to skip validating the input spec prior to generation. By default, invalid specifications will result in
54-
* an error.
55-
*/
56-
@ConfigItem(name = "validateSpec", defaultValue = "true")
57-
public boolean validateSpec;
58-
/**
59-
* Security type for which security constraints should be created automatically if not explicitly defined
60-
*/
61-
@ConfigItem(name = "default.security.scheme", defaultValue = "none")
62-
public String defaultSecurityScheme;
63-
6467
public static String resolveApiPackage(final String basePackage) {
6568
return String.format("%s%s", basePackage, API_PKG_SUFFIX);
6669
}
@@ -69,32 +72,18 @@ public static String resolveModelPackage(final String basePackage) {
6972
return String.format("%s%s", basePackage, MODEL_PKG_SUFFIX);
7073
}
7174

72-
public static String getBasePackagePropertyName(final Path openApiFilePath) {
73-
return String.format(BASE_PACKAGE_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
74-
}
75-
76-
public static String getSkipFormModelPropertyName(final Path openApiFilePath) {
77-
return String.format(SKIP_FORM_MODEL_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
78-
}
79-
80-
public static String getMutinyPropertyName(final Path openApiFilePath) {
81-
return String.format(MUTINY_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
82-
}
83-
84-
public static String getAdditionalModelTypeAnnotationsPropertyName(final Path openApiFilePath) {
85-
return String.format(ADDITIONAL_MODEL_TYPE_ANNOTATIONS_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
86-
}
87-
88-
public static String getTypeMappingsPropertyName(final Path openApiFilePath) {
89-
return String.format(TYPE_MAPPINGS_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
90-
}
91-
92-
public static String getImportMappingsPropertyName(final Path openApiFilePath) {
93-
return String.format(IMPORT_MAPPINGS_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
75+
/**
76+
* Return global config name, openapi-generator.codegen.config-name
77+
*/
78+
public static String getGlobalConfigName(ConfigName configName) {
79+
return String.format(BUILD_TIME_GLOBAL_PREFIX_FORMAT, configName.name);
9480
}
9581

96-
public static String getNormalizerPropertyName(final Path openApiFilePath) {
97-
return String.format(NORMALIZER_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
82+
/**
83+
* Return spec config name openapi-generator.codegen.spec.%s.config-name
84+
*/
85+
public static String getSpecConfigName(ConfigName configName, final Path openApiFilePath) {
86+
return String.format("%s.%s", getBuildTimeSpecPropertyPrefix(openApiFilePath), configName.name);
9887
}
9988

10089
/**
@@ -111,16 +100,4 @@ public static String getSanitizedFileName(final Path openApiFilePath) {
111100
return StringUtil
112101
.replaceNonAlphanumericByUnderscores(OpenApiGeneratorOutputPaths.getRelativePath(openApiFilePath).toString());
113102
}
114-
115-
public static String getCustomRegisterProvidersFormat(final Path openApiFilePath) {
116-
return String.format(CUSTOM_REGISTER_PROVIDERS_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
117-
}
118-
119-
public static String getReturnResponsePropertyName(final Path openApiFilePath) {
120-
return String.format(RETURN_RESPONSE_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
121-
}
122-
123-
public static String getClientHeaderFactoryPropertyName(final Path openApiFilePath) {
124-
return String.format(CLIENT_HEADER_FACTORY_PROP_FORMAT, getBuildTimeSpecPropertyPrefix(openApiFilePath));
125-
}
126103
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package io.quarkiverse.openapi.generator.deployment;
2+
3+
import java.util.Map;
4+
import java.util.Optional;
5+
6+
import io.quarkus.runtime.annotations.ConfigGroup;
7+
import io.quarkus.runtime.annotations.ConfigItem;
8+
9+
/*
10+
* Model for the configuration of this extension.
11+
* It's used for documentation purposes only.
12+
* The configuration is consumed in the codegen phase, before build time.
13+
* Not meant to be used outside this scope.
14+
* Config items can be applied on spec and globally as well
15+
*/
16+
@ConfigGroup
17+
public class CommonItemConfig {
18+
19+
/**
20+
* Whether to skip the generation of models for form parameters
21+
*/
22+
@ConfigItem(name = "skip-form-model")
23+
public Optional<Boolean> skipFormModel;
24+
25+
/**
26+
* Type Mapping is an OpenAPI Generator configuration specifying which Java types (the values) should be used for a
27+
* given OAS datatype (the keys of this map)
28+
*/
29+
@ConfigItem(name = "type-mappings")
30+
public Map<String, String> typeMappings;
31+
32+
/**
33+
* Import Mapping is an OpenAPI Generator configuration specifying which Java types (the values) should be
34+
* imported when a given OAS datatype (the keys of this map) is used
35+
*/
36+
@ConfigItem(name = "import-mappings")
37+
public Map<String, String> importMappings;
38+
39+
/**
40+
* The specified annotations will be added to the generated model files
41+
*/
42+
@ConfigItem(name = "additional-model-type-annotations")
43+
public Optional<String> additionalModelTypeAnnotations;
44+
45+
/**
46+
* The specified annotations will be added to the generated api files
47+
*/
48+
@ConfigItem(name = "additional-api-type-annotations")
49+
public Optional<String> additionalApiTypeAnnotations;
50+
51+
/**
52+
* Defines if the methods should return {@link javax.ws.rs.core.Response} or a model. Default is <code>false</code>.
53+
*/
54+
@ConfigItem(name = "return-response")
55+
public Optional<Boolean> returnResponse;
56+
57+
/**
58+
* Defines if security support classes should be generated
59+
*/
60+
@ConfigItem(name = "enable-security-generation")
61+
public Optional<String> enableSecurityGeneration;
62+
63+
/**
64+
* Defines the normalizer options.
65+
*/
66+
@ConfigItem(name = "open-api-normalizer")
67+
public Map<String, String> normalizer;
68+
69+
/**
70+
* Enable SmallRye Mutiny support. If you set this to `true`, all return types will be wrapped in `io.smallrye.mutiny.Uni`.
71+
*/
72+
@ConfigItem(name = "mutiny")
73+
public Optional<Boolean> supportMutiny;
74+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package io.quarkiverse.openapi.generator.deployment;
2+
3+
import java.util.Optional;
4+
5+
import io.quarkus.runtime.annotations.ConfigGroup;
6+
import io.quarkus.runtime.annotations.ConfigItem;
7+
8+
/*
9+
* Model for the configuration of this extension.
10+
* It's used for documentation purposes only.
11+
* The configuration is consumed in the codegen phase, before build time.
12+
* Not meant to be used outside this scope.
13+
* Config items can be applied only globally
14+
*/
15+
@ConfigGroup
16+
public class GlobalCodegenConfig extends CommonItemConfig {
17+
18+
/**
19+
* Whether to log the internal generator codegen process in the default output or not.
20+
*/
21+
@ConfigItem(name = "verbose", defaultValue = "false")
22+
public boolean verbose;
23+
24+
/**
25+
* Option to change the directory where OpenAPI files must be found.
26+
*/
27+
@ConfigItem(name = "input-base-dir")
28+
public Optional<String> inputBaseDir;
29+
30+
/**
31+
* Whether or not to skip validating the input spec prior to generation. By default, invalid specifications will result in
32+
* an error.
33+
*/
34+
@ConfigItem(name = "validateSpec", defaultValue = "true")
35+
public boolean validateSpec;
36+
37+
/**
38+
* Option to specify files for which generation should be executed only
39+
*/
40+
@ConfigItem(name = "include")
41+
public Optional<String> include;
42+
43+
/**
44+
* Option to exclude file from generation
45+
*/
46+
@ConfigItem(name = "exclude")
47+
public Optional<String> exclude;
48+
49+
/**
50+
* Create security for the referenced security scheme
51+
*/
52+
@ConfigItem(name = "default-security-scheme")
53+
public Optional<String> defaultSecuritySchema;
54+
55+
}

0 commit comments

Comments
 (0)