diff --git a/docs/customization.md b/docs/customization.md index 72e037e9a90..c4c36bf782f 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -646,3 +646,27 @@ Example: ``` java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml -o /tmp/java-okhttp/ --openapi-normalizer FIX_DUPLICATED_OPERATIONID=true ``` + +- `SET_BEARER_AUTH_FOR_NAME`: When set to the name of an openapi 2.0 securityDefinition, that securityDefinition will be converted to the openapi 3.0 bearerAuth securityScheme. + +Example: +``` +java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/2_0/globalSecurity.json -o /tmp/java-okhttp/ --openapi-normalizer SET_BEARER_AUTH_FOR_NAME=api_key +``` +Transforms this securityDefinition: +``` + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + }, + }, +``` +Into this securityScheme: +``` + securitySchemes: + api_key: + scheme: bearer + type: http +``` diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index d58b6a9bcf0..f75cb1fbef3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -26,6 +26,7 @@ import io.swagger.v3.oas.models.parameters.Parameter; 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 org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; @@ -101,6 +102,10 @@ public class OpenAPINormalizer { String fixDuplicatedOperationId; HashSet operationIdSet = new HashSet<>(); + // when set to true, if a securityScheme is found with the specified name, it will be converted to bearerAuth + final String SET_BEARER_AUTH_FOR_NAME = "SET_BEARER_AUTH_FOR_NAME"; + String bearerAuthSecuritySchemeName; + // when set to true, auto fix integer with maximum value 4294967295 (2^32-1) or long with 18446744073709551615 (2^64-1) // by adding x-unsigned to the schema final String ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE = "ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE"; @@ -167,6 +172,7 @@ public class OpenAPINormalizer { ruleNames.add(SET_TAGS_TO_OPERATIONID); ruleNames.add(SET_TAGS_TO_VENDOR_EXTENSION); ruleNames.add(FIX_DUPLICATED_OPERATIONID); + ruleNames.add(SET_BEARER_AUTH_FOR_NAME); ruleNames.add(ADD_UNSIGNED_TO_INTEGER_WITH_INVALID_MAX_VALUE); ruleNames.add(REFACTOR_ALLOF_WITH_PROPERTIES_ONLY); ruleNames.add(NORMALIZE_31SPEC); @@ -301,6 +307,11 @@ public class OpenAPINormalizer { LOGGER.error("SET_PRIMITIVE_TYPES_TO_NULLABLE rule must be in the form of `string|integer|number|boolean`, e.g. `string`, `integer|number`: {}", inputRules.get(SET_PRIMITIVE_TYPES_TO_NULLABLE)); } } + + bearerAuthSecuritySchemeName = inputRules.get(SET_BEARER_AUTH_FOR_NAME); + if (bearerAuthSecuritySchemeName != null) { + rules.put(SET_BEARER_AUTH_FOR_NAME, true); + } } /** @@ -322,6 +333,7 @@ public class OpenAPINormalizer { normalizeInfo(); normalizePaths(); + normalizeComponentsSecuritySchemes(); normalizeComponentsSchemas(); normalizeComponentsResponses(); } @@ -547,6 +559,36 @@ public class OpenAPINormalizer { } } + /** + * Normalizes securitySchemes in components + */ + private void normalizeComponentsSecuritySchemes() { + if (StringUtils.isEmpty(bearerAuthSecuritySchemeName)) { + return; + } + + Map schemes = openAPI.getComponents().getSecuritySchemes(); + if (schemes == null) { + return; + } + + for (String schemeKey : schemes.keySet()) { + if (schemeKey.equals(bearerAuthSecuritySchemeName)) { + SecurityScheme scheme = schemes.get(schemeKey); + scheme.setType(SecurityScheme.Type.HTTP); + scheme.setScheme("bearer"); + scheme.setIn(null); + scheme.setName(null); + scheme.setBearerFormat(null); + scheme.setFlows(null); + scheme.setOpenIdConnectUrl(null); + scheme.setExtensions(null); + scheme.set$ref(null); + schemes.put(schemeKey, scheme); + } + } + } + /** * Normalizes schemas in components */ @@ -560,7 +602,7 @@ public class OpenAPINormalizer { for (String schemaName : schemaNames) { Schema schema = schemas.get(schemaName); if (schema == null) { - LOGGER.warn("{} not fount found in openapi/components/schemas.", schemaName); + LOGGER.warn("{} not found in openapi/components/schemas.", schemaName); } else { // remove x-internal if needed if (schema.getExtensions() != null && getRule(REMOVE_X_INTERNAL)) { @@ -1053,7 +1095,6 @@ public class OpenAPINormalizer { } } - /** * If the schema contains anyOf/oneOf and properties, remove oneOf/anyOf as these serve as rules to * ensure inter-dependency between properties. It's a workaround as such validation is not supported at the moment. diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java index 34b06b9819d..85104bc2ea0 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java @@ -20,6 +20,7 @@ import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.media.*; import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.security.SecurityScheme; import org.openapitools.codegen.utils.ModelUtils; import org.testng.annotations.Test; @@ -942,4 +943,26 @@ public class OpenAPINormalizerTest { assertEquals(((Schema) apiResponse2.getContent().get("application/json").getSchema().getProperties().get("uuid")).getType(), "integer"); assertEquals(((Schema) apiResponse2.getContent().get("application/json").getSchema().getProperties().get("label")).getType(), "string"); } + + @Test + public void testOpenAPINormalizerBearerAuthSpec() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/2_0/globalSecurity.json"); + SecurityScheme scheme = openAPI.getComponents().getSecuritySchemes().get("api_key"); + assertEquals(scheme.getType(), SecurityScheme.Type.APIKEY); + assertEquals(scheme.getScheme(), null); + assertEquals(scheme.getName(), "api_key"); + assertEquals(scheme.getIn(), SecurityScheme.In.HEADER); + + Map inputRules = Map.of( + "SET_BEARER_AUTH_FOR_NAME", "api_key" + ); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, inputRules); + openAPINormalizer.normalize(); + + SecurityScheme scheme2 = openAPI.getComponents().getSecuritySchemes().get("api_key"); + assertEquals(scheme.getType(), SecurityScheme.Type.HTTP); + assertEquals(scheme.getScheme(), "bearer"); + assertEquals(scheme.getName(), null); + assertEquals(scheme.getIn(), null); + } }