Use List and Map in OpenApi security 42/106842/20
authorŠimon Ukuš <simon.ukus@pantheon.tech>
Wed, 12 Jul 2023 10:16:14 +0000 (12:16 +0200)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Wed, 23 Aug 2023 12:53:11 +0000 (12:53 +0000)
Swagger specification says "security is an array of hashmaps".

This change replaces the use of ArrayNode for java.util.List
and ObjectNode for java.util.Map.

JIRA: NETCONF-1075
Change-Id: Ic88d0de29d4c4abb2bc37db34033a0ae03434901
Signed-off-by: Šimon Ukuš <simon.ukus@pantheon.tech>
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/BaseYangOpenApiGenerator.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/OpenApiObject.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/Operation.java
restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java
restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/mountpoints/MountPointOpenApiTest.java

index f0857bab4eb6a40b130697f709d70d7e20f9d6b5..c27ffa432bfb70b74f503feab9ba8fa9efae8092 100644 (file)
@@ -17,8 +17,6 @@ import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.b
 import static org.opendaylight.restconf.openapi.util.RestDocgenUtil.resolveFullNameFromNode;
 import static org.opendaylight.restconf.openapi.util.RestDocgenUtil.resolvePathArgumentsName;
 
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Range;
 import java.io.IOException;
@@ -72,8 +70,7 @@ public abstract class BaseYangOpenApiGenerator {
     public static final String MODULE_NAME_SUFFIX = "_module";
     public static final String BASIC_AUTH_NAME = "basicAuth";
     public static final Http OPEN_API_BASIC_AUTH = new Http("basic", null, null);
-    public static final ArrayNode SECURITY = JsonNodeFactory.instance.arrayNode()
-        .add(JsonNodeFactory.instance.objectNode().set(BASIC_AUTH_NAME, JsonNodeFactory.instance.arrayNode()));
+    public static final List<Map<String, List<String>>> SECURITY = List.of(Map.of(BASIC_AUTH_NAME, List.of()));
 
     private final DOMSchemaService schemaService;
 
index 1041cde0b8e772b9563d8b5f8068e92f3809dd8b..c7de610330cbb0e126a3ac91dbfca8ea2e20aee2 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.restconf.openapi.model;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonInclude.Include;
-import com.fasterxml.jackson.databind.node.ArrayNode;
 import java.util.List;
 import java.util.Map;
 
@@ -20,5 +19,5 @@ public record OpenApiObject(
         List<Server> servers,
         Map<String, Path> paths,
         Components components,
-        ArrayNode security) {
+        List<Map<String, List<String>>> security) {
 }
index c161828050cd1747c9fc16c4481e764dc3320388..8db94a653d2059b78b1773b864213890d2fb5761 100644 (file)
@@ -11,11 +11,22 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import java.util.List;
+import java.util.Map;
 
 @JsonInclude(JsonInclude.Include.NON_NULL)
-public record Operation(boolean deprecated, List<String> tags, List<Parameter> parameters, ArrayNode security,
-        ArrayNode servers, ObjectNode callbacks, ObjectNode externalDocs, ObjectNode requestBody,
-        ObjectNode responses, String description, String operationId, String summary) {
+public record Operation(
+        boolean deprecated,
+        List<String> tags,
+        List<Parameter> parameters,
+        List<Map<String, List<String>>> security,
+        ArrayNode servers,
+        ObjectNode callbacks,
+        ObjectNode externalDocs,
+        ObjectNode requestBody,
+        ObjectNode responses,
+        String description,
+        String operationId,
+        String summary) {
 
     private Operation(final Builder builder) {
         this(builder.deprecated, builder.tags, builder.parameters, builder.security, builder.servers, builder.callbacks,
@@ -28,7 +39,7 @@ public record Operation(boolean deprecated, List<String> tags, List<Parameter> p
         private boolean deprecated;
         private List<String> tags;
         private List<Parameter> parameters;
-        private ArrayNode security;
+        private List<Map<String, List<String>>> security;
         private ArrayNode servers;
         private ObjectNode callbacks;
         private ObjectNode externalDocs;
@@ -53,7 +64,7 @@ public record Operation(boolean deprecated, List<String> tags, List<Parameter> p
             return this;
         }
 
-        public Builder security(final ArrayNode security) {
+        public Builder security(final List<Map<String, List<String>>> security) {
             this.security = security;
             return this;
         }
index ab77045a37992a8b955ae2428157eee94b0c285b..d7557c2be48e0d9dd698be9fb31bf137fe808588 100644 (file)
@@ -19,6 +19,7 @@ import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.BA
 
 import com.fasterxml.jackson.databind.JsonNode;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -363,9 +364,22 @@ public final class OpenApiGeneratorRFC8040Test {
     public void testAuthenticationFeature() {
         final var doc = generator.getApiDeclaration(TOASTER_2, REVISION_DATE, uriInfo);
 
-        assertEquals("[{\"basicAuth\":[]}]", doc.security().toString());
+        assertEquals("[{basicAuth=[]}]", doc.security().toString());
         assertEquals("Http[type=http, scheme=basic, description=null, bearerFormat=null]",
             doc.components().securitySchemes().get(BASIC_AUTH_NAME).toString());
+
+        // take list of all defined security scheme objects => all names of registered SecuritySchemeObjects
+        final var securitySchemesObjectNames = doc.components().securitySchemes().keySet();
+        assertTrue("No Security Schemes Object is defined", securitySchemesObjectNames.size() > 0);
+
+        // collect all referenced security scheme objects
+        final var referencedSecurityObjects = new HashSet<String>();
+        doc.security().forEach(map -> referencedSecurityObjects.addAll(map.keySet()));
+
+        // verify, that each reference references name of registered Security Scheme Object
+        for (final var secObjRef : referencedSecurityObjects) {
+            assertTrue(securitySchemesObjectNames.contains(secObjRef));
+        }
     }
 
     /**
index d19e2c9250bb3e4892e17f3fc1a0aec08c5d55d1..54eea0f52d2d89f8dc35ad94df737ea91d97920b 100644 (file)
@@ -280,7 +280,7 @@ public final class MountPointOpenApiTest {
         openApi.onMountPointCreated(INSTANCE_ID);
         final var mountPointApi = openApi.getMountPointApi(mockInfo, 1L, null);
 
-        assertEquals("[{\"basicAuth\":[]}]", mountPointApi.security().toString());
+        assertEquals("[{basicAuth=[]}]", mountPointApi.security().toString());
         assertEquals("Http[type=http, scheme=basic, description=null, bearerFormat=null]",
             mountPointApi.components().securitySchemes().get(BASIC_AUTH_NAME).toString());
     }