This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 43dd6efbd0b CAMEL-21164: camel-rest - Code first should use actual 
values for property placeholders in dumped API spec (#15460)
43dd6efbd0b is described below

commit 43dd6efbd0bd03a9ec6e8642a936a42ac5f2ebc3
Author: avi5kdonrh <[email protected]>
AuthorDate: Sat Sep 7 11:38:57 2024 +0530

    CAMEL-21164: camel-rest - Code first should use actual values for property 
placeholders in dumped API spec (#15460)
    
    Changes: camel-openapi-java:
    
              org.apache.camel.openapi RestOpenApiReader
              
org.apache.camel.openapi.SpringRestOpenApiReaderModelApiSecurityPlaceholderTest
              
org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.xml
---
 .../apache/camel/openapi/RestOpenApiReader.java    |  63 ++++-----
 ...enApiReaderModelApiSecurityPlaceholderTest.java | 145 +++++++++++++++++++++
 ...penApiReaderModelApiSecurityPlaceholderTest.xml |  93 +++++++++++++
 3 files changed, 272 insertions(+), 29 deletions(-)

diff --git 
a/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
 
b/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
index c5672440745..d50cb171c60 100644
--- 
a/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
+++ 
b/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
@@ -272,7 +272,7 @@ public class RestOpenApiReader {
                         ? new String[] { getValue(camelContext, 
rest.getPath()) }
                 : new String[0];
 
-        parseOas30(openApi, rest, pathAsTags);
+        parseOas30(camelContext, openApi, rest, pathAsTags);
 
         // gather all types in use
         Set<String> types = new LinkedHashSet<>();
@@ -341,7 +341,7 @@ public class RestOpenApiReader {
         });
     }
 
-    private void parseOas30(OpenAPI openApi, RestDefinition rest, String[] 
pathAsTags) {
+    private void parseOas30(CamelContext camelContext, OpenAPI openApi, 
RestDefinition rest, String[] pathAsTags) {
         String summary = rest.getDescriptionText();
 
         for (String tag : pathAsTags) {
@@ -358,36 +358,37 @@ public class RestOpenApiReader {
             for (RestSecurityDefinition def : sd.getSecurityDefinitions()) {
                 if (def instanceof BasicAuthDefinition) {
                     SecurityScheme auth = new 
SecurityScheme().type(SecurityScheme.Type.HTTP)
-                            .scheme("basic").description(def.getDescription());
-                    openApi.getComponents().addSecuritySchemes(def.getKey(), 
auth);
+                            
.scheme("basic").description(CamelContextHelper.parseText(camelContext, 
def.getDescription()));
+                    
openApi.getComponents().addSecuritySchemes(CamelContextHelper.parseText(camelContext,
 def.getKey()), auth);
                 } else if (def instanceof BearerTokenDefinition) {
                     SecurityScheme auth = new 
SecurityScheme().type(SecurityScheme.Type.HTTP)
-                            .scheme("bearer").description(def.getDescription())
-                            .bearerFormat(((BearerTokenDefinition) 
def).getFormat());
-                    openApi.getComponents().addSecuritySchemes(def.getKey(), 
auth);
+                            
.scheme("bearer").description(CamelContextHelper.parseText(camelContext, 
def.getDescription()))
+                            .bearerFormat(
+                                    
(CamelContextHelper.parseText(camelContext, ((BearerTokenDefinition) 
def).getFormat())));
+                    
openApi.getComponents().addSecuritySchemes(CamelContextHelper.parseText(camelContext,
 def.getKey()), auth);
                 } else if (def instanceof ApiKeyDefinition) {
                     ApiKeyDefinition rs = (ApiKeyDefinition) def;
                     SecurityScheme auth = new 
SecurityScheme().type(SecurityScheme.Type.APIKEY)
-                            
.name(rs.getName()).description(def.getDescription());
-
-                    if (rs.getInHeader() != null && 
Boolean.parseBoolean(rs.getInHeader())) {
+                            .name(CamelContextHelper.parseText(camelContext, 
rs.getName()))
+                            
.description(CamelContextHelper.parseText(camelContext, def.getDescription()));
+                    if 
(Boolean.TRUE.equals(CamelContextHelper.parseBoolean(camelContext, 
rs.getInHeader()))) {
                         auth.setIn(SecurityScheme.In.HEADER);
-                    } else if (rs.getInQuery() != null && 
Boolean.parseBoolean(rs.getInQuery())) {
+                    } else if 
(Boolean.TRUE.equals(CamelContextHelper.parseBoolean(camelContext, 
rs.getInQuery()))) {
                         auth.setIn(SecurityScheme.In.QUERY);
-                    } else if (rs.getInCookie() != null && 
Boolean.parseBoolean(rs.getInCookie())) {
+                    } else if 
(Boolean.TRUE.equals(CamelContextHelper.parseBoolean(camelContext, 
rs.getInCookie()))) {
                         auth.setIn(SecurityScheme.In.COOKIE);
                     } else {
                         throw new IllegalStateException("No API Key location 
specified.");
                     }
-                    openApi.getComponents().addSecuritySchemes(def.getKey(), 
auth);
+                    
openApi.getComponents().addSecuritySchemes(CamelContextHelper.parseText(camelContext,
 def.getKey()), auth);
                 } else if (def instanceof OAuth2Definition) {
                     OAuth2Definition rs = (OAuth2Definition) def;
 
                     SecurityScheme auth = new 
SecurityScheme().type(SecurityScheme.Type.OAUTH2)
-                            .description(def.getDescription());
-                    String flow = rs.getFlow();
+                            
.description(CamelContextHelper.parseText(camelContext, def.getDescription()));
+                    String flow = CamelContextHelper.parseText(camelContext, 
rs.getFlow());
                     if (flow == null) {
-                        flow = inferOauthFlow(rs);
+                        flow = inferOauthFlow(camelContext, rs);
                     }
                     OAuthFlows oauthFlows = new OAuthFlows();
                     auth.setFlows(oauthFlows);
@@ -410,25 +411,27 @@ public class RestOpenApiReader {
                         default:
                             throw new IllegalStateException("Invalid OAuth 
flow '" + flow + "' specified");
                     }
-                    oauthFlow.setAuthorizationUrl(rs.getAuthorizationUrl());
-                    oauthFlow.setTokenUrl(rs.getTokenUrl());
-                    oauthFlow.setRefreshUrl(rs.getRefreshUrl());
+                    
oauthFlow.setAuthorizationUrl(CamelContextHelper.parseText(camelContext, 
rs.getAuthorizationUrl()));
+                    
oauthFlow.setTokenUrl(CamelContextHelper.parseText(camelContext, 
rs.getTokenUrl()));
+                    
oauthFlow.setRefreshUrl(CamelContextHelper.parseText(camelContext, 
rs.getRefreshUrl()));
                     if (!rs.getScopes().isEmpty()) {
                         oauthFlow.setScopes(new Scopes());
                         for (RestPropertyDefinition scope : rs.getScopes()) {
-                            oauthFlow.getScopes().addString(scope.getKey(), 
scope.getValue());
+                            
oauthFlow.getScopes().addString(CamelContextHelper.parseText(camelContext, 
scope.getKey()),
+                                    CamelContextHelper.parseText(camelContext, 
scope.getValue()));
                         }
                     }
-                    openApi.getComponents().addSecuritySchemes(def.getKey(), 
auth);
+                    
openApi.getComponents().addSecuritySchemes(CamelContextHelper.parseText(camelContext,
 def.getKey()), auth);
                 } else if (def instanceof MutualTLSDefinition) {
                     SecurityScheme auth = new 
SecurityScheme().type(SecurityScheme.Type.MUTUALTLS)
-                            .description(def.getDescription());
-                    openApi.getComponents().addSecuritySchemes(def.getKey(), 
auth);
+                            
.description(CamelContextHelper.parseText(camelContext, def.getDescription()));
+                    
openApi.getComponents().addSecuritySchemes(CamelContextHelper.parseText(camelContext,
 def.getKey()), auth);
                 } else if (def instanceof OpenIdConnectDefinition) {
                     SecurityScheme auth = new 
SecurityScheme().type(SecurityScheme.Type.OPENIDCONNECT)
-                            .description(def.getDescription());
-                    auth.setOpenIdConnectUrl(((OpenIdConnectDefinition) 
def).getUrl());
-                    openApi.getComponents().addSecuritySchemes(def.getKey(), 
auth);
+                            
.description(CamelContextHelper.parseText(camelContext, def.getDescription()));
+                    auth.setOpenIdConnectUrl(
+                            CamelContextHelper.parseText(camelContext, 
((OpenIdConnectDefinition) def).getUrl()));
+                    
openApi.getComponents().addSecuritySchemes(CamelContextHelper.parseText(camelContext,
 def.getKey()), auth);
                 }
             }
         }
@@ -1115,11 +1118,13 @@ public class RestOpenApiReader {
 
     }
 
-    private String inferOauthFlow(OAuth2Definition rs) {
+    private String inferOauthFlow(CamelContext camelContext, OAuth2Definition 
rs) {
         String flow;
-        if (rs.getAuthorizationUrl() != null && rs.getTokenUrl() != null) {
+        if (CamelContextHelper.parseText(camelContext, 
rs.getAuthorizationUrl()) != null
+                && CamelContextHelper.parseText(camelContext, 
rs.getTokenUrl()) != null) {
             flow = "authorizationCode";
-        } else if (rs.getTokenUrl() == null && rs.getAuthorizationUrl() != 
null) {
+        } else if (CamelContextHelper.parseText(camelContext, 
rs.getTokenUrl()) == null
+                && CamelContextHelper.parseText(camelContext, 
rs.getAuthorizationUrl()) != null) {
             flow = "implicit";
         } else {
             throw new IllegalStateException("Error inferring OAuth flow");
diff --git 
a/components/camel-openapi-java/src/test/java/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.java
 
b/components/camel-openapi-java/src/test/java/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.java
new file mode 100644
index 00000000000..c2a12f0938a
--- /dev/null
+++ 
b/components/camel-openapi-java/src/test/java/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.openapi;
+
+import java.util.Map;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class SpringRestOpenApiReaderModelApiSecurityPlaceholderTest extends 
CamelSpringTestSupport {
+
+    private Logger log = LoggerFactory.getLogger(getClass());
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        Map<String, Object> properties = Map.ofEntries(
+                Map.entry("oauth.key", "petstore_auth"),
+                Map.entry("oauth.description", "OAuth test"),
+                Map.entry("oauth.authorization.url", 
"http://petstore.swagger.io/oauth/dialog";),
+                Map.entry("oauth.flow", "implicit"),
+                Map.entry("oauth.token.url", 
"http://petstore.swagger.io/oauth/token";),
+                Map.entry("oauth.refresh.url", 
"http://petstore.swagger.io/oauth/refresh";),
+                Map.entry("oauth.scopes", "read:pets,write:pets"),
+                Map.entry("oauth.scope.read", "read"),
+                Map.entry("oauth.scope.readers", "pets"),
+                Map.entry("oauth.scope.write", "write"),
+                Map.entry("oauth.scope.writers", "pets"),
+                Map.entry("apiKey.key", "api_key"),
+                Map.entry("apiKey.description", "API Key Test"),
+                Map.entry("apiKey.header.name", "myHeader"),
+                Map.entry("apiKey.inHeader", "true"),
+                Map.entry("apiKey.inCookie", "false"),
+                Map.entry("apiKey.inQuery", "false"),
+                Map.entry("bearer.key", "bearer"),
+                Map.entry("bearer.description", "Bearer Auth Test"),
+                Map.entry("bearer.format", "org.apache.camel.openapi.User"),
+                Map.entry("mtls.key", "mTLS"),
+                Map.entry("mtls.description", "mTLS Auth Test"),
+                Map.entry("oidc.key", "oidc"),
+                Map.entry("oidc.description", "OpenID Connect OAuth Test"),
+                Map.entry("oidc.url", 
"http://petstore.swagger.io/oauth/.well-known/openid-configuration";),
+                Map.entry("basicAuth.key", "basic"),
+                Map.entry("basicAuth.description", "Basic Auth Test"));
+        System.getProperties().putAll(properties);
+        return new ClassPathXmlApplicationContext(
+                
"org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.xml");
+    }
+
+    @Test
+    public void testReaderReadV3() throws Exception {
+        BeanConfig config = new BeanConfig();
+        config.setHost("localhost:8080");
+        config.setSchemes(new String[] { "http" });
+        config.setBasePath("/api");
+        config.setTitle("Camel User store");
+        config.setLicense("Apache 2.0");
+        
config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html";);
+        config.setVersion(BeanConfig.OPENAPI_VERSION_31.getVersion()); // 
Setting the version to 3.1 to test mTLS
+        Info info = new Info();
+        info.setDescription("OpenAPI 3.1 code first placeholder resolver test 
for security definitions");
+        info.setVersion("1.0");
+        info.setTitle("OpenAPI Security Definitions Placeholder Resolver Test 
1.0");
+        config.setInfo(info);
+        RestOpenApiReader reader = new RestOpenApiReader();
+
+        OpenAPI openApi = reader.read(context, context.getRestDefinitions(), 
config, context.getName(),
+                new DefaultClassResolver());
+        assertNotNull(openApi);
+
+        String json = RestOpenApiSupport.getJsonFromOpenAPIAsString(openApi, 
config);
+        log.info(json);
+
+        assertTrue(json.contains("\"securitySchemes\" : {"));
+        assertTrue(json.contains("\"type\" : \"oauth2\""));
+        assertTrue(json.contains("\"authorizationUrl\" : 
\"http://petstore.swagger.io/oauth/dialog\"";));
+        assertTrue(json.contains("\"tokenUrl\" : 
\"http://petstore.swagger.io/oauth/token\"";));
+        assertTrue(json.contains("\"refreshUrl\" : 
\"http://petstore.swagger.io/oauth/refresh\"";));
+        assertTrue(json.contains("\"flows\" : {"));
+        assertTrue(json.contains("\"implicit\" : {"));
+        assertTrue(json.contains("\"scopes\" : {"));
+        assertTrue(json.contains("\"read\" : \"pets\""));
+        assertTrue(json.contains("\"write\" : \"pets\""));
+        assertTrue(json.contains("\"type\" : \"apiKey\","));
+        assertTrue(json.contains("\"in\" : \"header\""));
+        assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\"";));
+        assertTrue(json.contains("\"security\" : [ {"));
+        assertTrue(json.contains("\"petstore_auth\" : [ \"write:pets\", 
\"read:pets\" ]"));
+        assertTrue(json.contains("\"api_key\" : [ ]"));
+        assertTrue(json.contains("\"basic\" : [ ]"));
+        assertTrue(json.contains("\"bearer\" : [ ]"));
+        assertTrue(json.contains("\"oidc\" : [ ]"));
+        assertTrue(json.contains("\"mTLS\" : [ ]"));
+        assertTrue(json.contains("\"description\" : \"The user returned\""));
+        assertTrue(json.contains("\"$ref\" : \"#/components/schemas/User\""));
+        assertTrue(json.contains("\"format\" : 
\"org.apache.camel.openapi.User\""));
+        assertTrue(json.contains("\"type\" : \"string\""));
+        assertTrue(json.contains("\"format\" : \"date\""));
+        assertTrue(json.contains("\"description\" : \"OAuth test\""));
+        assertTrue(json.contains("\"description\" : \"API Key Test\""));
+        assertTrue(json.contains("\"description\" : \"Basic Auth Test\""));
+        assertTrue(json.contains("\"description\" : \"Bearer Auth Test\""));
+        assertTrue(json.contains("\"description\" : \"OpenID Connect OAuth 
Test\""));
+        assertTrue(json.contains("\"description\" : \"mTLS Auth Test\""));
+        assertTrue(json.contains("\"type\" : \"apiKey\""));
+        assertTrue(json.contains("\"type\" : \"http\""));
+        assertTrue(json.contains("\"type\" : \"mutualTLS\""));
+        assertTrue(json.contains("\"type\" : \"openIdConnect\""));
+        assertTrue(json.contains("\"name\" : \"myHeader\""));
+        assertTrue(json.contains("\"in\" : \"header\""));
+        assertTrue(json.contains("\"scheme\" : \"basic\""));
+        assertTrue(json.contains("\"scheme\" : \"bearer\""));
+        assertTrue(json.contains("\"bearerFormat\" : 
\"org.apache.camel.openapi.User\""));
+        assertTrue(
+                json.contains("\"openIdConnectUrl\" : 
\"http://petstore.swagger.io/oauth/.well-known/openid-configuration\"";));
+        assertFalse(json.contains("\"enum\""));
+        assertFalse(json.contains("\"{{\""));
+
+        context.stop();
+    }
+}
diff --git 
a/components/camel-openapi-java/src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.xml
 
b/components/camel-openapi-java/src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.xml
new file mode 100644
index 00000000000..cbdbcb264c5
--- /dev/null
+++ 
b/components/camel-openapi-java/src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityPlaceholderTest.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <!-- use a dummy rest consumer factory for the rest engine -->
+  <bean id="dummy-rest" 
class="org.apache.camel.openapi.DummyRestConsumerFactory"/>
+
+  <bean id="userService" class="java.lang.Object"/>
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring";>
+
+    <rest path="/user" tag="dude" description="User rest service" 
consumes="application/json" produces="application/json">
+      <securityDefinitions>
+        <oauth2 key="{{oauth.key}}" 
authorizationUrl="{{oauth.authorization.url}}" 
description="{{oauth.description}}"
+        tokenUrl="{{oauth.token.url}}" flow="{{oauth.flow}}" 
refreshUrl="{{oauth.refresh.url}}">
+          <scopes key="{{oauth.scope.read}}"
+                  value="{{oauth.scope.readers}}"/>
+          <scopes key="{{oauth.scope.write}}"
+                  value="{{oauth.scope.writers}}"/>
+        </oauth2>
+        <apiKey key="{{apiKey.key}}" name="{{apiKey.header.name}}" 
inHeader="{{apiKey.inHeader}}" description="{{apiKey.description}}"
+        inQuery="{{apiKey.inQuery}}" inCookie="{{apiKey.inCookie}}"/>
+        <basicAuth key="{{basicAuth.key}}" 
description="{{basicAuth.description}}"/>
+        <bearer key="{{bearer.key}}" format="{{bearer.format}}" 
description="{{bearer.description}}"/>
+        <mutualTLS key="{{mtls.key}}" description="{{mtls.description}}"/>
+        <openIdConnect key="{{oidc.key}}" url="{{oidc.url}}" 
description="{{oidc.description}}"/>
+      </securityDefinitions>
+
+      <get path="/{id}/{date}" description="Find user by id and date" 
outType="org.apache.camel.openapi.User">
+        <param name="id" type="path" description="The id of the user to get"/>
+        <param name="date" type="path" dataFormat="date" description="The 
date"/>
+        <responseMessage message="The user returned"/>
+        <security key="{{apiKey.key}}"/>
+        <to uri="bean:userService?method=getUser(${header.id})"/>
+      </get>
+
+      <put description="Updates or create a user" 
type="org.apache.camel.openapi.User">
+        <param name="body" type="body" description="The user to update or 
create"/>
+        <security key="{{oauth.key}}" 
scopes="write:{{oauth.scope.writers}},read:{{oauth.scope.readers}}"/>
+        <to uri="bean:userService?method=updateUser"/>
+      </put>
+
+      <get path="/findAll" description="Find all users" 
outType="org.apache.camel.openapi.User[]">
+        <responseMessage message="All the found users"/>
+        <security key="{{basicAuth.key}}"/>
+        <to uri="bean:userService?method=listUsers"/>
+      </get>
+
+      <post path="/sendInfo" description="Send user information" 
outType="java.lang.String">
+        <responseMessage message="User info sent"/>
+        <security key="{{oidc.key}}"/>
+        <to uri="bean:userService?method=listUsers"/>
+      </post>
+
+      <post path="/getInfo" description="get user information" 
type="org.apache.camel.openapi.User" outType="java.lang.String">
+        <responseMessage message="User info found"/>
+        <security key="{{bearer.key}}"/>
+        <to uri="bean:userService?method=listUsers"/>
+      </post>
+
+      <get path="/test" description="Test the service" 
outType="java.lang.String">
+        <responseMessage message="Tested the service successfully"/>
+        <security key="{{mtls.key}}"/>
+        <to uri="bean:userService?method=listUsers"/>
+      </get>
+
+    </rest>
+
+  </camelContext>
+
+</beans>

Reply via email to