Skip to content

Commit e8ec8eb

Browse files
committed
Implement new filter logic
Add test for it Optimize old filter logic
1 parent 0add23e commit e8ec8eb

3 files changed

Lines changed: 321 additions & 17 deletions

File tree

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

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ public OpenAPINormalizer(OpenAPI openAPI, Map<String, String> inputRules) {
213213
ruleNames.add(NORMALIZE_31SPEC);
214214
ruleNames.add(REMOVE_X_INTERNAL);
215215
ruleNames.add(FILTER);
216+
ruleNames.add(SECURITY_SCHEMES_FILTER);
216217
ruleNames.add(SET_CONTAINER_TO_NULLABLE);
217218
ruleNames.add(SET_PRIMITIVE_TYPES_TO_NULLABLE);
218219
ruleNames.add(SIMPLIFY_ONEOF_ANYOF_ENUM);
@@ -287,6 +288,11 @@ public void processRules(Map<String, String> inputRules) {
287288
// actual parsing is delayed to allow customization of the Filter processing
288289
}
289290

291+
if (inputRules.get(SECURITY_SCHEMES_FILTER) != null) {
292+
rules.put(SECURITY_SCHEMES_FILTER, true);
293+
// actual parsing is delayed to allow customization of the Filter processing
294+
}
295+
290296
if (inputRules.get(SET_CONTAINER_TO_NULLABLE) != null) {
291297
rules.put(SET_CONTAINER_TO_NULLABLE, true);
292298
setContainerToNullable = new HashSet<>(Arrays.asList(inputRules.get(SET_CONTAINER_TO_NULLABLE).split("[|]")));
@@ -403,6 +409,15 @@ protected void normalizePaths() {
403409
return;
404410
}
405411

412+
OperationsFilter filter = null;
413+
if (Boolean.TRUE.equals(getRule(FILTER))) {
414+
String filters = inputRules.get(FILTER);
415+
filter = createOperationsFilter(this.openAPI, filters);
416+
if (!filter.parse()) {
417+
filter = null;
418+
}
419+
}
420+
406421
for (Map.Entry<String, PathItem> pathsEntry : paths.entrySet()) {
407422
PathItem path = pathsEntry.getValue();
408423
List<Operation> operations = new ArrayList<>(path.readOperations());
@@ -418,14 +433,10 @@ protected void normalizePaths() {
418433
"trace", PathItem::getTrace
419434
);
420435

421-
if (Boolean.TRUE.equals(getRule(FILTER))) {
422-
String filters = inputRules.get(FILTER);
423-
OperationsFilter filter = createOperationsFilter(this.openAPI, filters);
424-
if (filter.parse()) {
425-
// Iterates over each HTTP method in methodMap, retrieves the corresponding Operations from the PathItem,
426-
// and marks it as internal (`x-internal=true`) if the method/operationId/tag/path is not in the filters.
427-
filter.apply(pathsEntry.getKey(), path, methodMap);
428-
}
436+
if (filter != null && filter.hasFilter()) {
437+
// Iterates over each HTTP method in methodMap, retrieves the corresponding Operations from the PathItem,
438+
// and marks it as internal (`x-internal=true`) if the method/operationId/tag/path is not in the filters.
439+
filter.apply(pathsEntry.getKey(), path, methodMap);
429440
}
430441

431442
// Include callback operation as well
@@ -603,15 +614,19 @@ protected void normalizeHeaders(Map<String, Header> headers) {
603614
* Normalizes securitySchemes in components
604615
*/
605616
protected void normalizeComponentsSecuritySchemes() {
606-
if (StringUtils.isEmpty(bearerAuthSecuritySchemeName)) {
607-
return;
608-
}
609-
610617
Map<String, SecurityScheme> schemes = openAPI.getComponents().getSecuritySchemes();
611618
if (schemes == null) {
612619
return;
613620
}
614621

622+
SecuritySchemesFilter filter = null;
623+
if (Boolean.TRUE.equals(getRule(SECURITY_SCHEMES_FILTER))) {
624+
filter = createSecuritySchemesFilter(openAPI, inputRules.get(SECURITY_SCHEMES_FILTER));
625+
if (!filter.parse()) {
626+
filter = null;
627+
}
628+
}
629+
615630
for (String schemeKey : schemes.keySet()) {
616631
if (schemeKey.equals(bearerAuthSecuritySchemeName)) {
617632
SecurityScheme scheme = schemes.get(schemeKey);
@@ -626,6 +641,14 @@ protected void normalizeComponentsSecuritySchemes() {
626641
scheme.set$ref(null);
627642
schemes.put(schemeKey, scheme);
628643
}
644+
645+
// At first we transform a scheme to HTTP bearer and then apply the filter.
646+
// It may happen that bearer scheme will be filtered out on this step.
647+
// To keep the scheme - change filter input.
648+
if (filter != null && filter.hasFilter()) {
649+
SecurityScheme scheme = schemes.get(schemeKey);
650+
filter.apply(schemeKey, scheme);
651+
}
629652
}
630653
}
631654

@@ -1955,7 +1978,7 @@ private void normalizeExclusiveMinMax31(Schema<?> schema) {
19551978

19561979
// ===================== end of rules =====================
19571980

1958-
// Base class for filters. It provides basic parsing logic and utility functions for filters.
1981+
// Base class for filters. It provides parsing logic and utility functions for filters.
19591982
// All filters should have the same syntax:
19601983
// `filterName:value1|value2|value3` and multiple filters can be separated by `;`.
19611984
protected static abstract class BaseFilter {
@@ -1987,7 +2010,7 @@ public boolean parse() {
19872010
return hasFilter();
19882011
} catch (RuntimeException e) {
19892012
String usage = usageMessage();
1990-
String message = String.format(Locale.ROOT, "%s Input: `%s` Error: %s", usage, input, e.getMessage());
2013+
String message = String.format(Locale.ROOT, "%s Input: `%s`. Error: %s", usage, input, e.getMessage());
19912014
// throw an exception. This is a breaking change compared to pre 7.16.0
19922015
// Workaround: fix the syntax!
19932016
throw new IllegalArgumentException(message);
@@ -2200,7 +2223,7 @@ protected boolean hasCustomFilterMatch(String schemeKey, SecurityScheme scheme)
22002223
public void apply(String schemeKey, SecurityScheme scheme) {
22012224
boolean found = false;
22022225
found |= logIfMatch(KEY, schemeKey, hasKey(schemeKey));
2203-
found |= logIfMatch(TYPE, schemeKey, hasType(scheme.getType()));
2226+
found |= logIfMatch(TYPE, schemeKey, hasType(scheme.getType().toString()));
22042227
found |= hasCustomFilterMatch(schemeKey, scheme);
22052228

22062229
scheme.addExtension(X_INTERNAL, !found);

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ public void testFilterInvalidSyntaxDoesThrow() {
914914
new OpenAPINormalizer(openAPI, options).normalize();
915915
fail("Expected IllegalArgumentException");
916916
} catch (IllegalArgumentException e) {
917-
assertEquals(e.getMessage(), "FILTER rule [tag ; invalid] must be in the form of `operationId:name1|name2|name3` or `method:get|post|put` or `tag:tag1|tag2|tag3` or `path:/v1|/v2`. Error: filter with no value not supported :[tag]");
917+
assertEquals(e.getMessage(), "FILTER rule must be in the form of `operationId:name1|name2|name3` or `method:get|post|put` or `tag:tag1|tag2|tag3` or `path:/v1|/v2`. Input: `tag ; invalid`. Error: filter with no value not supported :[tag]");
918918
}
919919
}
920920

@@ -927,10 +927,36 @@ public void testFilterInvalidFilterDoesThrow() {
927927
new OpenAPINormalizer(openAPI, options).normalize();
928928
fail("Expected IllegalArgumentException");
929929
} catch (IllegalArgumentException e) {
930-
assertEquals(e.getMessage(), "FILTER rule [method:get ; unknown:test] must be in the form of `operationId:name1|name2|name3` or `method:get|post|put` or `tag:tag1|tag2|tag3` or `path:/v1|/v2`. Error: filter not supported :[unknown:test]");
930+
assertEquals(e.getMessage(), "FILTER rule must be in the form of `operationId:name1|name2|name3` or `method:get|post|put` or `tag:tag1|tag2|tag3` or `path:/v1|/v2`. Input: `method:get ; unknown:test`. Error: filter not supported :[unknown:test]");
931931
}
932932
}
933933

934+
@Test
935+
public void testSecuritySchemesFilter() {
936+
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/all_security_schemes.yaml");
937+
Map<String, String> options = Map.of("SECURITY_SCHEMES_FILTER", "key:api_key1 ; type:oauth2");
938+
939+
new OpenAPINormalizer(openAPI, options).normalize();
940+
941+
System.err.println("Security schemes after filter3: " + openAPI.getComponents().getSecuritySchemes().get("api_key1").toString());
942+
System.err.println("Security schemes after filter4: " + openAPI.getComponents().getSecuritySchemes().get("api_key1").getExtensions().toString());
943+
944+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("api_key1").getExtensions().get(X_INTERNAL),
945+
false);
946+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("api_key2").getExtensions().get(X_INTERNAL),
947+
true);
948+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("http1").getExtensions().get(X_INTERNAL), true);
949+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("http2").getExtensions().get(X_INTERNAL), true);
950+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("mutualTLS1").getExtensions().get(X_INTERNAL), true);
951+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("mutualTLS2").getExtensions().get(X_INTERNAL), true);
952+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("oauth2_1").getExtensions().get(X_INTERNAL),
953+
false);
954+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("oauth2_2").getExtensions().get(X_INTERNAL),
955+
false);
956+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("openIdConnect1").getExtensions().get(X_INTERNAL), true);
957+
assertEquals(openAPI.getComponents().getSecuritySchemes().get("openIdConnect2").getExtensions().get(X_INTERNAL), true);
958+
}
959+
934960

935961
@Test
936962
public void testComposedSchemaDoesNotThrow() {

0 commit comments

Comments
 (0)