From c5acc9ca7230e1f9c3bfae870d4e15ccbfcc899f Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Mon, 14 Oct 2024 21:07:00 -0700 Subject: [PATCH 01/22] - Fix issue #505 --- CHANGELOG.md | 11 ++ .../com/axway/apim/lib/CoreCLIOptions.java | 7 +- .../com/axway/apim/lib/CoreParameters.java | 9 + .../apim/lib/utils/rest/APIMHttpClient.java | 45 ++++- .../com/axway/lib/CoreCLIOptionsTest.java | 19 ++ .../axway/lib/EnvironmentPropertiesTest.java | 10 + .../lib/utils/rest/APIMHttpClientTest.java | 41 +++++ .../java/com/axway/apim/APIImportApp.java | 4 +- .../lib/params/APIUpgradeAccessParams.java | 174 ++++++++++-------- .../resources/env.anyOtherStage.properties | 3 +- 10 files changed, 231 insertions(+), 92 deletions(-) create mode 100644 modules/apim-adapter/src/test/java/com/axway/lib/utils/rest/APIMHttpClientTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af2b0857..ea946cf39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). + +# [1.14.7] In progress +## Fixed + + +### Added +-allow APIM cli to connect to API Manager protected by Cloudflare (See issue [#505](https://github.com/Axway-API-Management-Plus/apim-cli/issues/505)) + + - Added new paramater named customHeaders to handle additonal headers. + E.g ./apim.sh api get -n CalculatorService3 -o json -h localhost -u apiadmin -customHeaders abc:xyz + # [1.14.6] 2024-10-11 ## Fixed - Importing SOAP API with different endpoints (for import and for runtime calls) (See issue [#501](https://github.com/Axway-API-Management-Plus/apim-cli/issues/501)) diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreCLIOptions.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreCLIOptions.java index 18a56f4d1..55da673ac 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreCLIOptions.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreCLIOptions.java @@ -40,6 +40,7 @@ public Parameters getParams() throws AppException { params.setTimeout(getValue("timeout")); params.setDisableCompression(hasOption("disableCompression")); params.setOverrideSpecBasePath(hasOption("overrideSpecBasePath")); + params.setCustomHeaders(getValue("customHeaders")); return params; } @@ -152,7 +153,11 @@ public void addOptions() { option = new Option("overrideSpecBasePath", "Override API Specification ( open api, Swagger 2) using backendBasepath"); option.setRequired(false); - addOption(option); + cliOptions.addOption(option); + + option = new Option("customHeaders", true,"Custom http headers added while calling API manager in case it is protected with Gateway"); + option.setRequired(false); + cliOptions.addOption(option); } @Override diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreParameters.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreParameters.java index c28631b46..81c58ca4e 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreParameters.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/CoreParameters.java @@ -73,6 +73,7 @@ public static Mode valueOfDefault(String key) { private int timeout; private boolean disableCompression; private boolean overrideSpecBasePath; + private String customHeaders; public CoreParameters() { instance = this; @@ -456,6 +457,14 @@ public void setOverrideSpecBasePath(boolean overrideSpecBasePath) { this.overrideSpecBasePath = overrideSpecBasePath; } + public String getCustomHeaders() { + return customHeaders; + } + + public void setCustomHeaders(String customHeaders) { + this.customHeaders = customHeaders; + } + @Override public String toString() { return "[hostname=" + hostname + ", username=" + username + ", stage=" + stage + "]"; diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/rest/APIMHttpClient.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/rest/APIMHttpClient.java index 93f03cd27..9037b6470 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/rest/APIMHttpClient.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/rest/APIMHttpClient.java @@ -3,6 +3,7 @@ import com.axway.apim.lib.CoreParameters; import com.axway.apim.lib.error.AppException; import com.axway.apim.lib.error.ErrorCode; +import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -25,11 +26,15 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicHeader; import org.apache.http.ssl.SSLContextBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; /** * The interface to the API-Manager itself responsible to set up the underlying HTTPS-Communication. @@ -71,9 +76,9 @@ private void createConnection(URI uri) throws AppException { builder.loadTrustMaterial(null, new TrustAllStrategy()); SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier()); Registry r = RegistryBuilder.create() - .register(uri.getScheme(), sslConnectionSocketFactory) - .register("http", PlainConnectionSocketFactory.INSTANCE) - .build(); + .register(uri.getScheme(), sslConnectionSocketFactory) + .register("http", PlainConnectionSocketFactory.INSTANCE) + .build(); httpClientConnectionManager = new PoolingHttpClientConnectionManager(r); httpClientConnectionManager.setMaxTotal(5); @@ -88,14 +93,14 @@ private void createConnection(URI uri) throws AppException { int timeout = params.getTimeout(); LOG.debug("API Manager CLI http client timeout : {}", timeout); RequestConfig.Builder defaultRequestConfig = RequestConfig.custom() - .setConnectTimeout(timeout) - .setSocketTimeout(timeout) - .setConnectionRequestTimeout(timeout) - .setCookieSpec(CookieSpecs.STANDARD); + .setConnectTimeout(timeout) + .setSocketTimeout(timeout) + .setConnectionRequestTimeout(timeout) + .setCookieSpec(CookieSpecs.STANDARD); HttpClientBuilder clientBuilder = HttpClientBuilder.create() - .disableRedirectHandling() - .setConnectionManager(httpClientConnectionManager) - .useSystemProperties(); + .disableRedirectHandling() + .setConnectionManager(httpClientConnectionManager) + .useSystemProperties(); // Check if a proxy is configured if (params.getProxyHost() != null) { @@ -114,12 +119,32 @@ private void createConnection(URI uri) throws AppException { if (params.isDisableCompression()) clientBuilder.disableContentCompression(); clientBuilder.setDefaultRequestConfig(defaultRequestConfig.build()); + String customHeader = params.getCustomHeaders(); + if (customHeader != null) { + List
headers = splitStringToHttpHeaders(customHeader); + clientBuilder.setDefaultHeaders(headers); + } this.httpClient = clientBuilder.build(); } catch (Exception e) { throw new AppException("Can't create connection to API-Manager.", ErrorCode.API_MANAGER_COMMUNICATION); } } + public List
splitStringToHttpHeaders(String input) { + List
headers = new ArrayList<>(); + String[] headersArray = input.split(","); + for (String headerStr : headersArray) { + StringTokenizer tokenizer = new StringTokenizer(headerStr, ":"); + while (tokenizer.hasMoreTokens()) { + String key = tokenizer.nextToken(); + String value = tokenizer.nextToken(); + Header header = new BasicHeader(key, value); + headers.add(header); + } + } + return headers; + } + public HttpClient getHttpClient() { return httpClient; } diff --git a/modules/apim-adapter/src/test/java/com/axway/lib/CoreCLIOptionsTest.java b/modules/apim-adapter/src/test/java/com/axway/lib/CoreCLIOptionsTest.java index a2b2c2bdb..6c21bc538 100644 --- a/modules/apim-adapter/src/test/java/com/axway/lib/CoreCLIOptionsTest.java +++ b/modules/apim-adapter/src/test/java/com/axway/lib/CoreCLIOptionsTest.java @@ -126,4 +126,23 @@ public void testDisableCompressionNegative() throws AppException { Assert.assertEquals(params.isDisableCompression(), false); } + + @Test + public void testCustomHeaders() throws AppException { + String[] args = {"-customHeaders", "abc:xyz"}; + CLIOptions options = SampleCLIOptions.create(args); + CoreParameters params = (CoreParameters) options.getParams(); + System.out.println(params.getCustomHeaders()); + Assert.assertEquals(params.getCustomHeaders(), "abc:xyz"); + + } + + @Test + public void testCustomHeadersNegative() throws AppException { + String[] args = {""}; + CLIOptions options = SampleCLIOptions.create(args); + CoreParameters params = (CoreParameters) options.getParams(); + Assert.assertNull(params.getCustomHeaders()); + + } } diff --git a/modules/apim-adapter/src/test/java/com/axway/lib/EnvironmentPropertiesTest.java b/modules/apim-adapter/src/test/java/com/axway/lib/EnvironmentPropertiesTest.java index 062806166..d4d1a9b65 100644 --- a/modules/apim-adapter/src/test/java/com/axway/lib/EnvironmentPropertiesTest.java +++ b/modules/apim-adapter/src/test/java/com/axway/lib/EnvironmentPropertiesTest.java @@ -74,4 +74,14 @@ public void testEnvironmentWithOSEnvVariables() { Assert.assertEquals("http://${env.HOSTNAME}:${env.PORT.TRAFFIC}", EnvironmentProperties.resolveValueWithEnvVars("http://${env.HOSTNAME}:${env.PORT.TRAFFIC}")); Assert.assertNotNull(EnvironmentProperties.resolveValueWithEnvVars("${PATH}")); } + + @Test + public void testCustomHeader() { + String cliHome = System.getenv("AXWAY_APIM_CLI_HOME"); + if(cliHome != null) { + EnvironmentProperties properties = new EnvironmentProperties("anyOtherStage"); + Assert.assertEquals(properties.get("headers"), "cf-token:xyz123"); + } + } + } diff --git a/modules/apim-adapter/src/test/java/com/axway/lib/utils/rest/APIMHttpClientTest.java b/modules/apim-adapter/src/test/java/com/axway/lib/utils/rest/APIMHttpClientTest.java new file mode 100644 index 000000000..316bcde55 --- /dev/null +++ b/modules/apim-adapter/src/test/java/com/axway/lib/utils/rest/APIMHttpClientTest.java @@ -0,0 +1,41 @@ +package com.axway.lib.utils.rest; + +import com.axway.apim.WiremockWrapper; +import com.axway.apim.lib.StandardImportParams; +import com.axway.apim.lib.error.AppException; +import com.axway.apim.lib.utils.rest.APIMHttpClient; +import org.apache.http.Header; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.List; + +public class APIMHttpClientTest extends WiremockWrapper { + + @BeforeClass + public void initWiremock() { + super.initWiremock(); + } + + @AfterClass + public void close() { + super.close(); + } + + @Test + public void splitStringToHttpHeaders() throws AppException { + StandardImportParams coreParameters = new StandardImportParams(); + coreParameters.setHostname("localhost"); + coreParameters.setUsername("apiadmin"); + coreParameters.setPassword(" "); + String customHeader = "cf-access-token:xyz133"; + APIMHttpClient apimHttpClient = APIMHttpClient.getInstance(); + List
headers = apimHttpClient.splitStringToHttpHeaders(customHeader); + Assert.assertEquals(headers.size(), 1); + Assert.assertEquals(headers.get(0).getName(), "cf-access-token"); + Assert.assertEquals(headers.get(0).getValue(), "xyz133"); + + } +} diff --git a/modules/apis/src/main/java/com/axway/apim/APIImportApp.java b/modules/apis/src/main/java/com/axway/apim/APIImportApp.java index bf90f3c31..7450d63ca 100644 --- a/modules/apis/src/main/java/com/axway/apim/APIImportApp.java +++ b/modules/apis/src/main/java/com/axway/apim/APIImportApp.java @@ -67,7 +67,9 @@ public int importAPI(APIImportParams params) { List filters = new ArrayList<>(); // If we don't have an AdminAccount available, we ignore published APIs - For OrgAdmins // the unpublished or pending APIs become the actual API - if (!APIManagerAdapter.getInstance().hasAdminAccount()) { + boolean isAdminAccount = APIManagerAdapter.getInstance().hasAdminAccount(); + boolean orgAdminSelfService = APIManagerAdapter.getInstance().getConfigAdapter().getConfig(isAdminAccount).getOadminSelfServiceEnabled(); + if (!isAdminAccount && !orgAdminSelfService) { filters.add(new BasicNameValuePair("field", "state")); filters.add(new BasicNameValuePair("op", "ne")); filters.add(new BasicNameValuePair("value", "published")); diff --git a/modules/apis/src/main/java/com/axway/apim/api/export/lib/params/APIUpgradeAccessParams.java b/modules/apis/src/main/java/com/axway/apim/api/export/lib/params/APIUpgradeAccessParams.java index e6d60283b..68253504f 100644 --- a/modules/apis/src/main/java/com/axway/apim/api/export/lib/params/APIUpgradeAccessParams.java +++ b/modules/apis/src/main/java/com/axway/apim/api/export/lib/params/APIUpgradeAccessParams.java @@ -8,83 +8,99 @@ import com.axway.apim.lib.utils.Utils; public class APIUpgradeAccessParams extends APIExportParams implements Parameters, APIFilterParams { - - private String referenceAPIId; - private String referenceAPIName; - private String referenceAPIVersion; - private String referenceAPIOrganization; - - private Boolean referenceAPIDeprecate = false; - private Boolean referenceAPIRetire = false; - private Long referenceAPIRetirementDate; - - private API referenceAPI; - - public API getReferenceAPI() { - return referenceAPI; - } - public void setReferenceAPI(API referenceAPI) { - this.referenceAPI = referenceAPI; - } - public Boolean getReferenceAPIDeprecate() { - return referenceAPIDeprecate; - } - public void setReferenceAPIDeprecate(Boolean referenceAPIDeprecate) { - this.referenceAPIDeprecate = referenceAPIDeprecate; - } - public Boolean getReferenceAPIRetire() { - return referenceAPIRetire; - } - public void setReferenceAPIRetire(Boolean referenceAPIRetire) { - this.referenceAPIRetire = referenceAPIRetire; - } - public Long getReferenceAPIRetirementDate() { - return referenceAPIRetirementDate; - } - public void setReferenceAPIRetirementDate(String referenceAPIRetirementDate) throws AppException { - if(referenceAPIRetirementDate == null) return; - this.referenceAPIRetirementDate = Utils.getParsedDate(referenceAPIRetirementDate); - } - public String getReferenceAPIId() { - return referenceAPIId; - } - public void setReferenceAPIId(String referenceAPIId) { - this.referenceAPIId = referenceAPIId; - } - public String getReferenceAPIName() { - return referenceAPIName; - } - public void setReferenceAPIName(String referenceAPIName) { - this.referenceAPIName = referenceAPIName; - } - public String getReferenceAPIVersion() { - return referenceAPIVersion; - } - public void setReferenceAPIVersion(String referenceAPIVersion) { - this.referenceAPIVersion = referenceAPIVersion; - } - public String getReferenceAPIOrganization() { - return referenceAPIOrganization; - } - public void setReferenceAPIOrganization(String referenceAPIOrganization) { - this.referenceAPIOrganization = referenceAPIOrganization; - } - - public APIFilter getReferenceAPIFilter() { - return new APIFilter.Builder() - .hasApiId(getReferenceAPIId()) - .hasApiPath(getApiPath()) - .hasName(getReferenceAPIName()) - .hasVHost(getReferenceAPIVersion()) - .hasOrganization(getReferenceAPIOrganization()) - .hasState(API.STATE_PUBLISHED) - .build(); - } - @Override - public void validateRequiredParameters() throws AppException { - super.validateRequiredParameters(); - if(getReferenceAPIRetire()!=null && getReferenceAPIRetirementDate()==null) { - throw new AppException("If API should be retired, a retirement date is required.", ErrorCode.MISSING_PARAMETER); - } - } + + private String referenceAPIId; + private String referenceAPIName; + private String referenceAPIVersion; + private String referenceAPIOrganization; + + private Boolean referenceAPIDeprecate = false; + private Boolean referenceAPIRetire = false; + private Long referenceAPIRetirementDate; + + private API referenceAPI; + + public API getReferenceAPI() { + return referenceAPI; + } + + public void setReferenceAPI(API referenceAPI) { + this.referenceAPI = referenceAPI; + } + + public Boolean getReferenceAPIDeprecate() { + return referenceAPIDeprecate; + } + + public void setReferenceAPIDeprecate(Boolean referenceAPIDeprecate) { + this.referenceAPIDeprecate = referenceAPIDeprecate; + } + + public Boolean getReferenceAPIRetire() { + return referenceAPIRetire; + } + + public void setReferenceAPIRetire(Boolean referenceAPIRetire) { + this.referenceAPIRetire = referenceAPIRetire; + } + + public Long getReferenceAPIRetirementDate() { + return referenceAPIRetirementDate; + } + + public void setReferenceAPIRetirementDate(String referenceAPIRetirementDate) throws AppException { + if (referenceAPIRetirementDate == null) return; + this.referenceAPIRetirementDate = Utils.getParsedDate(referenceAPIRetirementDate); + } + + public String getReferenceAPIId() { + return referenceAPIId; + } + + public void setReferenceAPIId(String referenceAPIId) { + this.referenceAPIId = referenceAPIId; + } + + public String getReferenceAPIName() { + return referenceAPIName; + } + + public void setReferenceAPIName(String referenceAPIName) { + this.referenceAPIName = referenceAPIName; + } + + public String getReferenceAPIVersion() { + return referenceAPIVersion; + } + + public void setReferenceAPIVersion(String referenceAPIVersion) { + this.referenceAPIVersion = referenceAPIVersion; + } + + public String getReferenceAPIOrganization() { + return referenceAPIOrganization; + } + + public void setReferenceAPIOrganization(String referenceAPIOrganization) { + this.referenceAPIOrganization = referenceAPIOrganization; + } + + public APIFilter getReferenceAPIFilter() { + return new APIFilter.Builder() + .hasApiId(getReferenceAPIId()) + .hasApiPath(getApiPath()) + .hasName(getReferenceAPIName()) + .hasVHost(getReferenceAPIVersion()) + .hasOrganization(getReferenceAPIOrganization()) + .hasState(API.STATE_PUBLISHED) + .build(); + } + + @Override + public void validateRequiredParameters() throws AppException { + super.validateRequiredParameters(); + if (getReferenceAPIRetire() != null && getReferenceAPIRetirementDate() == null) { + throw new AppException("If API should be retired, a retirement date is required.", ErrorCode.MISSING_PARAMETER); + } + } } diff --git a/modules/apis/src/test/resources/env.anyOtherStage.properties b/modules/apis/src/test/resources/env.anyOtherStage.properties index a5a334516..26dee40e5 100644 --- a/modules/apis/src/test/resources/env.anyOtherStage.properties +++ b/modules/apis/src/test/resources/env.anyOtherStage.properties @@ -3,4 +3,5 @@ password=anyOtherPassword thisKeyExists=HellImHere -OS_MAIN_AND_STAGE_ENV_PROPERTY=valueFromAnyOtherStageEnv \ No newline at end of file +OS_MAIN_AND_STAGE_ENV_PROPERTY=valueFromAnyOtherStageEnv +headers=cf-token:xyz123 From 3187d6aad4ced7938529abbce771315c5b37eb55 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Wed, 16 Oct 2024 22:15:15 -0700 Subject: [PATCH 02/22] - code cleanup --- .../axway/apim/adapter/apis/APIFilter.java | 1 - .../jackson/QuotaRestrictionDeserializer.java | 1 - .../java/com/axway/apim/api/model/Image.java | 1 - .../axway/apim/api/model/SecurityProfile.java | 1 - .../filter/BaseAPISpecificationFilter.java | 1 - .../java/com/axway/apim/lib/APIMCLICache.java | 1 - .../axway/apim/lib/APIMCLICacheManager.java | 1 - .../axway/apim/lib/EnvironmentProperties.java | 1 - .../com/axway/apim/lib/utils/URLParser.java | 9 ++--- .../export/lib/cli/CLIAPIFilterOptions.java | 1 - .../apiimport/rollback/RollbackAPIProxy.java | 1 - .../rollback/RollbackBackendAPI.java | 1 - .../apim/test/changestate/ActualAPI.java | 38 ------------------- .../test/changestate/ChangeStateTest.java | 2 +- .../jackson/AppExportSerializerModifier.java | 5 +-- .../appexport/model/ExportApplication.java | 1 - .../OrganizationImportManager.java | 1 - .../lib/cli/CLIOrgFilterOptions.java | 11 +++--- .../impl/ConsolePrinterCustomProperties.java | 1 - .../axway/apim/users/UserImportManager.java | 1 - .../users/lib/cli/CLIUserFilterOptions.java | 23 ++++++----- 21 files changed, 23 insertions(+), 80 deletions(-) delete mode 100644 modules/apis/src/test/java/com/axway/apim/test/changestate/ActualAPI.java diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIFilter.java b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIFilter.java index dabc79e0b..bd46111bd 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIFilter.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIFilter.java @@ -642,7 +642,6 @@ public Builder(APIType type) { * @param loadBackendAPI is search backendEndAPI if set to true */ public Builder(APIType type, boolean loadBackendAPI) { - super(); initType(type); this.apiType = type; this.loadBackendAPI = loadBackendAPI; diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/jackson/QuotaRestrictionDeserializer.java b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/jackson/QuotaRestrictionDeserializer.java index 8132e6f2c..74a19e8eb 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/jackson/QuotaRestrictionDeserializer.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/jackson/QuotaRestrictionDeserializer.java @@ -44,7 +44,6 @@ public QuotaRestrictionDeserializer(DeserializeMode deserializeMode) { } public QuotaRestrictionDeserializer(DeserializeMode deserializeMode, boolean addRestrictedAPI) { - super(); this.deserializeMode = deserializeMode; this.addRestrictedAPI = addRestrictedAPI; try { diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/Image.java b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/Image.java index 8daa80e10..e81674979 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/Image.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/Image.java @@ -38,7 +38,6 @@ public Image() { } public Image(String filename) { - super(); this.filename = filename; } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/SecurityProfile.java b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/SecurityProfile.java index d4db81de3..999315daa 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/SecurityProfile.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/SecurityProfile.java @@ -14,7 +14,6 @@ public class SecurityProfile { private List devices; public SecurityProfile() { - super(); this.devices = new ArrayList<>(); } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/api/specification/filter/BaseAPISpecificationFilter.java b/modules/apim-adapter/src/main/java/com/axway/apim/api/specification/filter/BaseAPISpecificationFilter.java index 09c14b287..cb7eba35d 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/api/specification/filter/BaseAPISpecificationFilter.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/api/specification/filter/BaseAPISpecificationFilter.java @@ -16,7 +16,6 @@ protected static class FilterConfig { APISpecificationFilter filterConfigFilter; public FilterConfig(APISpecificationFilter filterConfigFilter) { - super(); this.filterConfigFilter = filterConfigFilter; } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICache.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICache.java index 27a0af384..a76edd99b 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICache.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICache.java @@ -17,7 +17,6 @@ public class APIMCLICache implements Cache { private final String prefix; public APIMCLICache(Cache cache, String prefix) { - super(); this.cache = cache; this.prefix = prefix; } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICacheManager.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICacheManager.java index 7d0a876f9..539bb8da0 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICacheManager.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/APIMCLICacheManager.java @@ -32,7 +32,6 @@ public class APIMCLICacheManager implements CacheManager { private List enabledCaches; public APIMCLICacheManager(CacheManager cacheManager) { - super(); this.cacheManager = cacheManager; } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/EnvironmentProperties.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/EnvironmentProperties.java index ac34495cf..0ad9bdbba 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/EnvironmentProperties.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/EnvironmentProperties.java @@ -37,7 +37,6 @@ public EnvironmentProperties(String stage) { } public EnvironmentProperties(String stage, String swaggerPromoteHome) { - super(); this.stage = stage; this.swaggerPromoteHome = swaggerPromoteHome; if (swaggerPromoteHome == null) { diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/URLParser.java b/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/URLParser.java index f88ad4fdf..272e74028 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/URLParser.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/lib/utils/URLParser.java @@ -5,19 +5,18 @@ public class URLParser { String username; - + String password; - + String uri; - + String urlToAPIDefinition; public URLParser(String urlToAPIDefinition) throws AppException { - super(); this.urlToAPIDefinition = urlToAPIDefinition; parseUrl(); } - + private void parseUrl() throws AppException { if(!urlToAPIDefinition.contains("@")) { this.uri = urlToAPIDefinition; diff --git a/modules/apis/src/main/java/com/axway/apim/api/export/lib/cli/CLIAPIFilterOptions.java b/modules/apis/src/main/java/com/axway/apim/api/export/lib/cli/CLIAPIFilterOptions.java index f7d746cbd..4d1684493 100644 --- a/modules/apis/src/main/java/com/axway/apim/api/export/lib/cli/CLIAPIFilterOptions.java +++ b/modules/apis/src/main/java/com/axway/apim/api/export/lib/cli/CLIAPIFilterOptions.java @@ -20,7 +20,6 @@ public class CLIAPIFilterOptions extends CLIOptions { private final CLIOptions cliOptions; public CLIAPIFilterOptions(CLIOptions cliOptions) { - super(); this.cliOptions = cliOptions; } diff --git a/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackAPIProxy.java b/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackAPIProxy.java index 22d5b7883..2c473b075 100644 --- a/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackAPIProxy.java +++ b/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackAPIProxy.java @@ -21,7 +21,6 @@ public class RollbackAPIProxy extends AbstractRollbackAction implements Rollback API rollbackAPI; public RollbackAPIProxy(API rollbackAPI) { - super(); this.rollbackAPI = rollbackAPI; executeOrder = 10; this.name = "Frontend-API"; diff --git a/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackBackendAPI.java b/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackBackendAPI.java index 4f75848ef..a520ce620 100644 --- a/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackBackendAPI.java +++ b/modules/apis/src/main/java/com/axway/apim/apiimport/rollback/RollbackBackendAPI.java @@ -20,7 +20,6 @@ public class RollbackBackendAPI extends AbstractRollbackAction implements Rollba API rollbackAPI; public RollbackBackendAPI(API rollbackAPI) { - super(); this.rollbackAPI = rollbackAPI; this.executeOrder = 20; this.name = "Backend-API"; diff --git a/modules/apis/src/test/java/com/axway/apim/test/changestate/ActualAPI.java b/modules/apis/src/test/java/com/axway/apim/test/changestate/ActualAPI.java deleted file mode 100644 index c616ff385..000000000 --- a/modules/apis/src/test/java/com/axway/apim/test/changestate/ActualAPI.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.axway.apim.test.changestate; - -import com.axway.apim.api.API; -import com.axway.apim.apiimport.DesiredAPI; -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Concrete class that is used to reflect the actual API as it's stored in the API-Manager. - * On the other hand, the APIImportDefintion reflects the desired state of the API. - *

- * Both classes extend the AbstractAPIDefinition which contains all the common API-Properties that - * are compared property by property in APIChangeState. - * - * @see API - * @see DesiredAPI - * @author cwiechmann@axway.com - */ -public class ActualAPI extends API { - - /** - * The actual state must be stored as given by the API-Manager, as this state must be - * send back during API-Proxy update! - */ - @JsonIgnore - private String actualState; - - public ActualAPI() { - super(); - } - - public String getActualState() { - return actualState; - } - - public void setActualState(String actualState) { - this.actualState = actualState; - } -} diff --git a/modules/apis/src/test/java/com/axway/apim/test/changestate/ChangeStateTest.java b/modules/apis/src/test/java/com/axway/apim/test/changestate/ChangeStateTest.java index a049f9040..af9d47992 100644 --- a/modules/apis/src/test/java/com/axway/apim/test/changestate/ChangeStateTest.java +++ b/modules/apis/src/test/java/com/axway/apim/test/changestate/ChangeStateTest.java @@ -100,7 +100,7 @@ public void isDesiredStateDeleted() throws Exception { } private static API getTestAPI() { - API testAPI = new ActualAPI(); + API testAPI = new API(); testAPI.setOrganization(new Organization.Builder().hasName("123").hasId("123").build()); testAPI.setState(API.STATE_PUBLISHED); return testAPI; diff --git a/modules/apps/src/main/java/com/axway/apim/appexport/impl/jackson/AppExportSerializerModifier.java b/modules/apps/src/main/java/com/axway/apim/appexport/impl/jackson/AppExportSerializerModifier.java index 7c8210469..e9203fcba 100644 --- a/modules/apps/src/main/java/com/axway/apim/appexport/impl/jackson/AppExportSerializerModifier.java +++ b/modules/apps/src/main/java/com/axway/apim/appexport/impl/jackson/AppExportSerializerModifier.java @@ -10,11 +10,10 @@ import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; public class AppExportSerializerModifier extends BeanSerializerModifier { - + File localFolder; public AppExportSerializerModifier(File localFolder) { - super(); this.localFolder = localFolder; } @@ -28,7 +27,7 @@ public JsonSerializer modifySerializer(SerializationConfig config, BeanDescri } else if (beanDesc.getBeanClass() == APIQuota.class) { return new AppQuotaSerializer((JsonSerializer) serializer); } - + return super.modifySerializer(config, beanDesc, serializer); } diff --git a/modules/apps/src/main/java/com/axway/apim/appexport/model/ExportApplication.java b/modules/apps/src/main/java/com/axway/apim/appexport/model/ExportApplication.java index 41855dde3..181772765 100644 --- a/modules/apps/src/main/java/com/axway/apim/appexport/model/ExportApplication.java +++ b/modules/apps/src/main/java/com/axway/apim/appexport/model/ExportApplication.java @@ -21,7 +21,6 @@ public class ExportApplication { ClientApplication clientApp; public ExportApplication(ClientApplication clientApp) { - super(); this.clientApp = clientApp; } diff --git a/modules/organizations/src/main/java/com/axway/apim/organization/OrganizationImportManager.java b/modules/organizations/src/main/java/com/axway/apim/organization/OrganizationImportManager.java index 355b2a85f..3422b2d94 100644 --- a/modules/organizations/src/main/java/com/axway/apim/organization/OrganizationImportManager.java +++ b/modules/organizations/src/main/java/com/axway/apim/organization/OrganizationImportManager.java @@ -16,7 +16,6 @@ public class OrganizationImportManager { private final APIManagerOrganizationAdapter orgAdapter; public OrganizationImportManager() throws AppException { - super(); this.orgAdapter = APIManagerAdapter.getInstance().getOrgAdapter(); } diff --git a/modules/organizations/src/main/java/com/axway/apim/organization/lib/cli/CLIOrgFilterOptions.java b/modules/organizations/src/main/java/com/axway/apim/organization/lib/cli/CLIOrgFilterOptions.java index 299fb34b5..88f12d916 100644 --- a/modules/organizations/src/main/java/com/axway/apim/organization/lib/cli/CLIOrgFilterOptions.java +++ b/modules/organizations/src/main/java/com/axway/apim/organization/lib/cli/CLIOrgFilterOptions.java @@ -9,11 +9,10 @@ import com.axway.apim.organization.lib.OrgFilterParams; public class CLIOrgFilterOptions extends CLIOptions { - + private final CLIOptions cliOptions; public CLIOrgFilterOptions(CLIOptions cliOptions) { - super(); this.cliOptions = cliOptions; } @@ -23,7 +22,7 @@ public Parameters getParams() throws AppException { params.setName(getValue("name")); params.setId(getValue("id")); params.setDev(getValue("dev")); - + return (Parameters) params; } @@ -37,7 +36,7 @@ public void addOption(Option option) { cliOptions.addOption(option); } - + @Override public String getValue(String key) { return cliOptions.getValue(key); @@ -65,12 +64,12 @@ public void addOptions() { option.setRequired(false); option.setArgName("*My organization*"); cliOptions.addOption(option); - + option = new Option("id", true, "Filter the export to an organization with that specific ID."); option.setRequired(false); option.setArgName("UUID-ID-OF-THE-ORG"); cliOptions.addOption(option); - + option = new Option("dev", true, "Filter organizations based on the development flag: true | false"); option.setRequired(false); option.setArgName("true|false"); diff --git a/modules/settings/src/main/java/com/axway/apim/setup/impl/ConsolePrinterCustomProperties.java b/modules/settings/src/main/java/com/axway/apim/setup/impl/ConsolePrinterCustomProperties.java index c5dd605f0..db79d375a 100644 --- a/modules/settings/src/main/java/com/axway/apim/setup/impl/ConsolePrinterCustomProperties.java +++ b/modules/settings/src/main/java/com/axway/apim/setup/impl/ConsolePrinterCustomProperties.java @@ -80,7 +80,6 @@ private static class CustomPropertyWithName { private final CustomProperty customProperty; public CustomPropertyWithName(CustomProperty customProperty) { - super(); this.customProperty = customProperty; } diff --git a/modules/users/src/main/java/com/axway/apim/users/UserImportManager.java b/modules/users/src/main/java/com/axway/apim/users/UserImportManager.java index 6ccffaa54..48fc7d43b 100644 --- a/modules/users/src/main/java/com/axway/apim/users/UserImportManager.java +++ b/modules/users/src/main/java/com/axway/apim/users/UserImportManager.java @@ -16,7 +16,6 @@ public class UserImportManager { private final APIManagerUserAdapter userAdapter; public UserImportManager() throws AppException { - super(); this.userAdapter = APIManagerAdapter.getInstance().getUserAdapter(); } diff --git a/modules/users/src/main/java/com/axway/apim/users/lib/cli/CLIUserFilterOptions.java b/modules/users/src/main/java/com/axway/apim/users/lib/cli/CLIUserFilterOptions.java index cb6683dd6..f5362ceb4 100644 --- a/modules/users/src/main/java/com/axway/apim/users/lib/cli/CLIUserFilterOptions.java +++ b/modules/users/src/main/java/com/axway/apim/users/lib/cli/CLIUserFilterOptions.java @@ -14,7 +14,6 @@ public class CLIUserFilterOptions extends CLIOptions { private final CLIOptions cliOptions; public CLIUserFilterOptions(CLIOptions cliOptions) { - super(); this.cliOptions = cliOptions; } @@ -32,7 +31,7 @@ public Parameters getParams() throws AppException { params.setEnabled(Boolean.parseBoolean(getValue(ENABLED))); } params.setId(getValue("id")); - + return (Parameters) params; } @@ -45,7 +44,7 @@ public void parse() throws AppException{ public void addOption(Option option) { cliOptions.addOption(option); } - + @Override public String getValue(String key) { return cliOptions.getValue(key); @@ -72,47 +71,47 @@ public void addOptions() { option.setRequired(false); option.setArgName("*mark24*"); addOption(option); - + option = new Option("n", "name", true, "Filter users with the specified name. You may use wildcards at the end or beginning."); option.setRequired(false); option.setArgName("*Mark*"); addOption(option); - + option = new Option("email", true, "Filter users with the specified Email-Address. You may use wildcards at the end or beginning."); option.setRequired(false); option.setArgName("*@axway.com*"); addOption(option); - + option = new Option("type", true, "Filter users with specific type. External users are managed in external system such as LDAP"); option.setRequired(false); option.setArgName("internal|external"); addOption(option); - + option = new Option("org", true, "Filter users belonging to specified organization. You may use wildcards at the end or beginning."); option.setRequired(false); option.setArgName("*Partner*"); addOption(option); - + option = new Option("role", true, "Filter users with the given role. "); option.setRequired(false); option.setArgName("user|oadmin|admin"); addOption(option); - + option = new Option("state", true, "Filter users with the given state. "); option.setRequired(false); option.setArgName("approved|pending"); addOption(option); - + option = new Option(ENABLED, true, "Filter users based on the enablement flag. By default enabled users are include by default."); option.setRequired(false); option.setArgName("true|false"); addOption(option); - + option = new Option("id", true, "Filter users with that specific ID."); option.setRequired(false); option.setArgName("UUID-ID-OF-THE-USER"); addOption(option); - + cliOptions.addOptions(); } From 98d0b912668f92a97972f386c24c1d05aaafc047 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Wed, 16 Oct 2024 22:32:19 -0700 Subject: [PATCH 03/22] - increase timeout for integration test --- .../apim/appimport/it/basic/ImportCompleteApplicationTestIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/apps/src/test/java/com/axway/apim/appimport/it/basic/ImportCompleteApplicationTestIT.java b/modules/apps/src/test/java/com/axway/apim/appimport/it/basic/ImportCompleteApplicationTestIT.java index be5385596..4c298e7ef 100644 --- a/modules/apps/src/test/java/com/axway/apim/appimport/it/basic/ImportCompleteApplicationTestIT.java +++ b/modules/apps/src/test/java/com/axway/apim/appimport/it/basic/ImportCompleteApplicationTestIT.java @@ -103,6 +103,7 @@ public void importApplicationBasicTest(@Optional @CitrusResource TestContext con .expression("$.[?(@.scope=='${scopeName1}')].isDefault", "${scopeIsDefault1}") .expression("$.[?(@.scope=='${scopeName2}')].isDefault", "${scopeIsDefault2}"))); + $(sleep().seconds(5)); $(echo("####### Re-Import same application - Should be a No-Change #######")); $(testContext -> { String[] args = {"app", "import", "-c", updatedConfigFile, "-h", testContext.replaceDynamicContentInString("${apiManagerHost}"), "-u", testContext.replaceDynamicContentInString("${apiManagerUser}"), "-p", testContext.replaceDynamicContentInString("${apiManagerPass}")}; From 477cdd78437abac2dd72f838d812844821f7cec9 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Fri, 18 Oct 2024 08:53:38 -0700 Subject: [PATCH 04/22] - performance fixes --- .../apis/APIManagerAPIAccessAdapter.java | 46 +++++++++++-- .../adapter/apis/APIManagerAPIAdapter.java | 19 ++---- .../apis/APIManagerAPIAccessAdapterTest.java | 8 +++ .../com/axway/apim/api/export/ExportAPI.java | 17 ++--- .../api/export/impl/ConsoleAPIExporter.java | 2 +- .../apiimport/APIImportConfigAdapter.java | 57 ++++++++--------- .../apiimport/actions/ManageClientApps.java | 17 ++--- .../apiimport/APIImportConfigAdapterTest.java | 64 +++++++++++++++++++ pom.xml | 8 +-- 9 files changed, 163 insertions(+), 75 deletions(-) diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapter.java b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapter.java index d45516818..9d2f1e692 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapter.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapter.java @@ -39,6 +39,7 @@ public class APIManagerAPIAccessAdapter { + public static final String APIS = "/apis"; public enum Type { organizations("Organization"), applications("Application"); @@ -79,7 +80,7 @@ private void readAPIAccessFromAPIManager(Type type, String id) throws AppExcepti return; } try { - URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + id + "/apis").build(); + URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + id + APIS).build(); RestAPICall getRequest = new GETRequest(uri); LOG.debug("Load API-Access with type: {} from API-Manager with ID: {}", type, id); try (CloseableHttpResponse httpResponse = (CloseableHttpResponse) getRequest.execute()) { @@ -153,6 +154,13 @@ private void removeFromCache(String id, Type type) { } } + private void removeApplicationFromCache(String id) { + Cache usedCache = caches.get(Type.applications); + if (usedCache != null && usedCache.containsKey(id)) + usedCache.remove(id); + + } + public void saveAPIAccess(List apiAccess, AbstractEntity entity, Type type) throws AppException { List existingAPIAccess = getAPIAccess(entity, type, true); List toBeRemovedAccesses = getMissingAPIAccesses(existingAPIAccess, apiAccess); @@ -194,6 +202,36 @@ public void populateApiId(APIAccess apiAccess) throws AppException { } } + public APIAccess createAPIAccessForApplication(APIAccess apiAccess, String applicationId) throws AppException { + try { + URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/applications/" + applicationId + APIS).build(); + mapper.setSerializationInclusion(Include.NON_NULL); + FilterProvider filter = new SimpleFilterProvider().setDefaultFilter( + SimpleBeanPropertyFilter.serializeAllExcept("apiName", "apiVersion")); + mapper.setFilterProvider(filter); + HttpEntity entity = new StringEntity(mapper.writeValueAsString(apiAccess), ContentType.APPLICATION_JSON); + RestAPICall request = new POSTRequest(entity, uri); + try (CloseableHttpResponse httpResponse = (CloseableHttpResponse) request.execute()) { + int statusCode = httpResponse.getStatusLine().getStatusCode(); + String response = EntityUtils.toString(httpResponse.getEntity()); + + if (statusCode != 201) { + if (statusCode == 409 && response.contains("resource already exists")) { + LOG.info("Unexpected response while creating/updating API Access: {} Response-Code: {} Response Body: {} Ignoring this error.", apiAccess, statusCode, response); + return apiAccess; + }else { + LOG.error("Error granting access to application id : {} for API-Proxy : {} using URI: {} Received Status-Code: {} Response: {}", applicationId, apiAccess.getApiId(), uri, statusCode, response); + throw new AppException("Can't grant access to API.", ErrorCode.ERR_GRANTING_ACCESS_TO_API); + } + } + removeApplicationFromCache(applicationId); + return mapper.readValue(response, APIAccess.class); + } + } catch (Exception e) { + throw new AppException("Can't grant access to API.", ErrorCode.ERR_GRANTING_ACCESS_TO_API, e); + } + } + public void createAPIAccess(APIAccess apiAccess, AbstractEntity parentEntity, Type type) throws AppException { List existingAPIAccess = getAPIAccess(parentEntity, type, true); if (existingAPIAccess != null && existingAPIAccess.contains(apiAccess)) { @@ -201,7 +239,7 @@ public void createAPIAccess(APIAccess apiAccess, AbstractEntity parentEntity, Ty return; } try { - URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + parentEntity.getId() + "/apis").build(); + URI uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(cmd.getApiBasepath() + "/" + type + "/" + parentEntity.getId() + APIS).build(); mapper.setSerializationInclusion(Include.NON_NULL); FilterProvider filter = new SimpleFilterProvider().setDefaultFilter( SimpleBeanPropertyFilter.serializeAllExcept("apiName", "apiVersion")); @@ -252,12 +290,12 @@ public void deleteAPIAccess(APIAccess apiAccess, AbstractEntity parentEntity, Ty if (statusCode < 200 || statusCode > 299) { String errorResponse = EntityUtils.toString(httpResponse.getEntity()); LOG.error("Can't delete API access requests for application. Response-Code: {}. Got response: {}", statusCode, errorResponse); - throw new AppException("Can't delete API access requests for application. Response-Code: " + statusCode, ErrorCode.API_MANAGER_COMMUNICATION); + throw new AppException("Can't delete API access requests for application. Response-Code: " + statusCode,ErrorCode.REVOKE_ACCESS_APPLICATION_ERR); } removeFromCache(parentEntity.getId(), type); } } catch (Exception e) { - throw new AppException("Can't delete API access requests for application.", ErrorCode.CANT_CREATE_API_PROXY, e); + throw new AppException("Can't delete API access requests for application.", ErrorCode.REVOKE_ACCESS_APPLICATION_ERR, e); } } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAdapter.java b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAdapter.java index 05cd7b57b..a64f10ce0 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAdapter.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIAdapter.java @@ -98,7 +98,7 @@ public List getAPIs(APIFilter filter, boolean logProgress) throws AppExcept API api = apis.get(i); translateMethodIds(api, filter.getTranslateMethodMode()); addQuotaConfiguration(api, filter.isIncludeQuotas()); - addClientOrganizations(api, filter.isIncludeClientOrganizations()); + addClientOrganizations(api); addClientApplications(api, filter); addExistingClientAppQuotas(api, filter.isIncludeQuotas()); addOriginalAPIDefinitionFromAPIM(api, filter); @@ -439,18 +439,11 @@ private void addExistingClientAppQuotas(API api, boolean addQuota) throws AppExc } } - public void addClientOrganizations(API api, boolean addClientOrganizations) throws AppException { - if (!addClientOrganizations || !APIManagerAdapter.getInstance().hasAdminAccount()) return; - List grantedOrgs; - List allOrgs = APIManagerAdapter.getInstance().getOrgAdapter().getAllOrgs(); - grantedOrgs = new ArrayList<>(); - for (Organization org : allOrgs) { - List orgAPIAccess = APIManagerAdapter.getInstance().getAccessAdapter().getAPIAccess(org, APIManagerAPIAccessAdapter.Type.organizations); - for (APIAccess access : orgAPIAccess) { - if (access.getApiId().equals(api.getId())) { - grantedOrgs.add(org); - } - } + public void addClientOrganizations(API api) throws AppException { + List grantedOrgs = new ArrayList<>(); + List apiOrganizationSubscriptions = APIManagerAdapter.getInstance().getAccessAdapter().getApiAccess(api.getId()); + for (ApiOrganizationSubscription apiOrganizationSubscription : apiOrganizationSubscriptions) { + grantedOrgs.add(new Organization(apiOrganizationSubscription.getOrganizationName())); } api.setClientOrganizations(grantedOrgs); } diff --git a/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapterTest.java b/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapterTest.java index ba040e9f3..b29d0717c 100644 --- a/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapterTest.java +++ b/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAccessAdapterTest.java @@ -217,5 +217,13 @@ public void getApiAccess() throws AppException { Assert.assertEquals(4, apiOrganizationSubscriptions.size()); } + @Test + public void createAPIAccessForApplication() throws AppException { + String applicationId = "40dd53a4-0b13-4485-82e8-63c687404c2f"; + APIAccess apiAccess = new APIAccess(); + apiAccess.setApiId("40dd53a4-0b13-4485-82e8-63c687404c2g"); + APIAccess response = apiManagerAPIAccessAdapter.createAPIAccessForApplication(apiAccess, applicationId); + Assert.assertNotNull(response); + } } diff --git a/modules/apis/src/main/java/com/axway/apim/api/export/ExportAPI.java b/modules/apis/src/main/java/com/axway/apim/api/export/ExportAPI.java index 1dd3bd0e7..4c55c60ed 100644 --- a/modules/apis/src/main/java/com/axway/apim/api/export/ExportAPI.java +++ b/modules/apis/src/main/java/com/axway/apim/api/export/ExportAPI.java @@ -253,22 +253,13 @@ public List getCaCerts() { } - public APIQuota getApplicationQuota() throws AppException { - return translateMethodIds(actualAPIProxy.getApplicationQuota()); + public APIQuota getApplicationQuota() { + return actualAPIProxy.getApplicationQuota(); } - public APIQuota getSystemQuota() throws AppException { - return translateMethodIds(actualAPIProxy.getSystemQuota()); - } - - private APIQuota translateMethodIds(APIQuota apiQuota) throws AppException { - if (apiQuota == null || apiQuota.getRestrictions() == null) return apiQuota; - for (QuotaRestriction restriction : apiQuota.getRestrictions()) { - if ("*".equals(restriction.getMethod())) continue; - restriction.setMethod(APIManagerAdapter.getInstance().getMethodAdapter().getMethodForId(actualAPIProxy.getId(), restriction.getMethod()).getName()); - } - return apiQuota; + public APIQuota getSystemQuota() { + return actualAPIProxy.getSystemQuota(); } @JsonIgnore diff --git a/modules/apis/src/main/java/com/axway/apim/api/export/impl/ConsoleAPIExporter.java b/modules/apis/src/main/java/com/axway/apim/api/export/impl/ConsoleAPIExporter.java index 2df13b285..527d9a509 100644 --- a/modules/apis/src/main/java/com/axway/apim/api/export/impl/ConsoleAPIExporter.java +++ b/modules/apis/src/main/java/com/axway/apim/api/export/impl/ConsoleAPIExporter.java @@ -127,7 +127,7 @@ private void printDetails(List apis) { try { APIManagerAPIAdapter apiAdapter = APIManagerAdapter.getInstance().getApiAdapter(); apiAdapter.addClientApplications(api, new APIFilter.Builder().includeClientApplications(true).build()); - apiAdapter.addClientOrganizations(api, true); + apiAdapter.addClientOrganizations(api); apiAdapter.addQuotaConfiguration(api, true); } catch (AppException e) { LOG.error("Error loading API details.", e); diff --git a/modules/apis/src/main/java/com/axway/apim/apiimport/APIImportConfigAdapter.java b/modules/apis/src/main/java/com/axway/apim/apiimport/APIImportConfigAdapter.java index 05a947c6f..10866b208 100644 --- a/modules/apis/src/main/java/com/axway/apim/apiimport/APIImportConfigAdapter.java +++ b/modules/apis/src/main/java/com/axway/apim/apiimport/APIImportConfigAdapter.java @@ -148,7 +148,7 @@ public API getDesiredAPI() throws AppException { validateHasQueryStringKey(apiConfig); completeCaCerts(apiConfig); addQuotaConfiguration(apiConfig); - handleAllOrganizations(apiConfig); + handleOrganizations(apiConfig); completeClientApplications(apiConfig); handleVhost(apiConfig); validateMethodDescription(apiConfig.getApiMethods()); @@ -181,7 +181,7 @@ private void validateOrganization(API apiConfig) throws AppException { private void addAPISpecification(API apiConfig) throws IOException { APISpecification apiSpecification; if (((DesiredAPI) apiConfig).getDesiredAPISpecification() != null) { - // API-Specification object that might contain filters, the type of an API, etc. + // API-Specification object that might contain filters, the type of API, etc. apiSpecification = APISpecificationFactory.getAPISpecification(((DesiredAPI) apiConfig).getDesiredAPISpecification(), this.apiConfigFile.getCanonicalFile().getParent(), apiConfig.getName()); } else if (StringUtils.isNotEmpty(this.pathToAPIDefinition)) { apiSpecification = APISpecificationFactory.getAPISpecification(this.pathToAPIDefinition, this.apiConfigFile.getCanonicalFile().getParent(), apiConfig.getName()); @@ -196,7 +196,7 @@ private void addAPISpecification(API apiConfig) throws IOException { apiConfig.setApiDefinition(apiSpecification); } - private void handleAllOrganizations(API apiConfig) throws AppException { + public void handleOrganizations(API apiConfig) throws AppException { if (apiConfig.getClientOrganizations() == null) return; if (apiConfig.getState().equals(API.STATE_UNPUBLISHED)) { apiConfig.setClientOrganizations(null); // Making sure, orgs are not considered as a changed property @@ -204,37 +204,35 @@ private void handleAllOrganizations(API apiConfig) throws AppException { } APIManagerOrganizationAdapter organizationAdapter = APIManagerAdapter.getInstance().getOrgAdapter(); if (apiConfig.getClientOrganizations().contains(new Organization.Builder().hasName("ALL").build())) { - List allOrgs = organizationAdapter.getAllOrgs(); - apiConfig.getClientOrganizations().clear(); - apiConfig.getClientOrganizations().addAll(allOrgs); + List organizations = organizationAdapter.getAllOrgs(); + organizations.remove(apiConfig.getOrganization()); + apiConfig.setClientOrganizations(organizations); apiConfig.setRequestForAllOrgs(true); } else { - // As the API-Manager internally handles the owning organization in the same way, - // we have to add the Owning-Org as a desired org - if (!apiConfig.getClientOrganizations().contains(apiConfig.getOrganization())) { - apiConfig.getClientOrganizations().add(apiConfig.getOrganization()); - } - // And validate each configured organization really exists in the API-Manager - Iterator it = apiConfig.getClientOrganizations().iterator(); - String invalidClientOrgs = null; - List foundOrgs = new ArrayList<>(); - while (it.hasNext()) { - Organization desiredOrg = it.next(); - Organization org = organizationAdapter.getOrgForName(desiredOrg.getName()); - if (org == null) { - LOG.warn("Unknown organization with name: {} configured. Ignoring this organization.", desiredOrg.getName()); - invalidClientOrgs = invalidClientOrgs == null ? desiredOrg.getName() : invalidClientOrgs + ", " + desiredOrg.getName(); - APIPropertiesExport.getInstance().setProperty(ErrorCode.INVALID_CLIENT_ORGANIZATIONS.name(), invalidClientOrgs); - it.remove(); - continue; - } - it.remove(); - foundOrgs.add(org); + List filteredOrganizations = removeInvalidOrganizations(apiConfig.getClientOrganizations()); + filteredOrganizations.remove(apiConfig.getOrganization()); + apiConfig.setClientOrganizations(filteredOrganizations); + } + } + + public List removeInvalidOrganizations(List inputOrganizations) throws AppException { + List validOrganizations = new ArrayList<>(); + APIManagerOrganizationAdapter organizationAdapter = APIManagerAdapter.getInstance().getOrgAdapter(); + String invalidClientOrgs = null; + for (Organization inputOrganization : inputOrganizations) { + Organization organization = organizationAdapter.getOrgForName(inputOrganization.getName()); + if (organization == null) { + LOG.warn("Unknown organization with name: {} configured. Ignoring this organization.", inputOrganization.getName()); + invalidClientOrgs = invalidClientOrgs == null ? inputOrganization.getName() : invalidClientOrgs + ", " + inputOrganization.getName(); + APIPropertiesExport.getInstance().setProperty(ErrorCode.INVALID_CLIENT_ORGANIZATIONS.name(), invalidClientOrgs); + } else { + validOrganizations.add(organization); } - apiConfig.getClientOrganizations().addAll(foundOrgs); } + return validOrganizations; } + private void addQuotaConfiguration(API apiConfig) { if (apiConfig.getState().equals(API.STATE_UNPUBLISHED)) return; initQuota(apiConfig.getSystemQuota()); @@ -371,7 +369,7 @@ private void addDefaultCorsProfile(API apiConfig) { /** * Purpose of this method is to load the actual existing applications from API-Manager * based on the provided criteria (App-Name, API-Key, OAuth-ClientId or Ext-ClientId). - * Or, if the APP doesn't exists remove it from the list and log a warning message. + * Or, if the APP doesn't exist remove it from the list and log a warning message. * Additionally, for each application it's checked, that the organization has access * to this API, otherwise it will be removed from the list as well and a warning message is logged. * @@ -437,7 +435,6 @@ private static ClientApplication getAppForCredential(String credential, String t ClientApplication app = APIManagerAdapter.getInstance().getAppIdForCredential(credential, type); if (app == null) { LOG.warn("Unknown application with ({}): {} configured. Ignoring this application.", type, credential); - return null; } return app; } diff --git a/modules/apis/src/main/java/com/axway/apim/apiimport/actions/ManageClientApps.java b/modules/apis/src/main/java/com/axway/apim/apiimport/actions/ManageClientApps.java index ebb8d7cf4..61c612bd3 100644 --- a/modules/apis/src/main/java/com/axway/apim/apiimport/actions/ManageClientApps.java +++ b/modules/apis/src/main/java/com/axway/apim/apiimport/actions/ManageClientApps.java @@ -49,7 +49,7 @@ public void execute(boolean reCreation) throws AppException { LOG.info("Configured client applications are ignored, as flag ignoreClientApps has been set."); return; } - if (desiredState.getApplications() != null) { // Happens, when config-file doesn't contains client apps + if (desiredState.getApplications() != null) { // Happens, when config-file doesn't contain client apps // Remove configured apps, for Non-Granted-Orgs! removeNonGrantedClientApps(desiredState.getApplications()); } @@ -115,15 +115,11 @@ private void createAppSubscription(List missingDesiredApps, S if (missingDesiredApps.isEmpty()) return; LOG.info("Creating API-Access for the following apps: {}", missingDesiredApps); for (ClientApplication app : missingDesiredApps) { - try { - LOG.info("Creating API-Access for application {}", app.getName()); - APIAccess apiAccess = new APIAccess(); - apiAccess.setApiId(apiId); - accessAdapter.createAPIAccess(apiAccess, app, Type.applications); - } catch (AppException e) { - throw new AppException("Failure creating API-Access for application: '" + app.getName() + "'. " + e.getMessage(), - ErrorCode.API_MANAGER_COMMUNICATION, e); - } + LOG.info("Creating API-Access for application {}", app.getName()); + APIAccess apiAccess = new APIAccess(); + apiAccess.setApiId(apiId); + APIAccess response = accessAdapter.createAPIAccessForApplication(apiAccess, app.getId()); + LOG.info("Created API ({}) Access for application {} ", response.getApiId(), app.getName()); } } @@ -142,6 +138,7 @@ private void removeAppSubscription(List removingActualApps) t } } } + private List getMissingApps(List apps, List otherApps) { List missingApps = new ArrayList<>(); if (otherApps == null) otherApps = new ArrayList<>(); diff --git a/modules/apis/src/test/java/com/axway/apim/apiimport/APIImportConfigAdapterTest.java b/modules/apis/src/test/java/com/axway/apim/apiimport/APIImportConfigAdapterTest.java index 8b1cae7da..afea2c7e8 100644 --- a/modules/apis/src/test/java/com/axway/apim/apiimport/APIImportConfigAdapterTest.java +++ b/modules/apis/src/test/java/com/axway/apim/apiimport/APIImportConfigAdapterTest.java @@ -4,6 +4,7 @@ import com.axway.apim.WiremockWrapper; import com.axway.apim.api.API; import com.axway.apim.api.model.CaCert; +import com.axway.apim.api.model.Organization; import com.axway.apim.api.model.OutboundProfile; import com.axway.apim.apiimport.lib.params.APIImportParams; import com.axway.apim.lib.CoreParameters; @@ -20,6 +21,7 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -334,4 +336,66 @@ public void testOutboundBasicAuthEmptyPassword() throws AppException { Assert.assertEquals("", apiConfig.getAuthenticationProfiles().get(0).getParameters().get("password")); } + @Test + public void handleOrganizationsDoNothing() throws AppException { + APIImportParams params = new APIImportParams(); + params.setHostname("localhost"); + params.setUsername("test"); + params.setPassword(Utils.getEncryptedPassword()); + String testConfig = this.getClass().getResource("/com/axway/apim/test/files/basic/outbound_basic_auth_empty_password.json").getFile(); + params.setConfig(testConfig); + APIImportConfigAdapter adapter = new APIImportConfigAdapter(params); + API api = new API(); + adapter.handleOrganizations(api); + Assert.assertNull(api.getClientOrganizations()); + } + + @Test + public void handleOrganizationsWithUnpublishedApi() throws AppException { + APIImportParams params = new APIImportParams(); + params.setHostname("localhost"); + params.setUsername("test"); + params.setPassword(Utils.getEncryptedPassword()); + String testConfig = this.getClass().getResource("/com/axway/apim/test/files/basic/outbound_basic_auth_empty_password.json").getFile(); + params.setConfig(testConfig); + APIImportConfigAdapter adapter = new APIImportConfigAdapter(params); + API api = new API(); + api.setState(API.STATE_UNPUBLISHED); + api.setClientOrganizations(new ArrayList<>()); + adapter.handleOrganizations(api); + Assert.assertNull(api.getClientOrganizations()); + } + + @Test + public void handleOrganizationsAll() throws AppException { + APIImportParams params = new APIImportParams(); + params.setHostname("localhost"); + params.setUsername("test"); + params.setPassword(Utils.getEncryptedPassword()); + String testConfig = this.getClass().getResource("/com/axway/apim/test/files/basic/outbound_basic_auth_empty_password.json").getFile(); + params.setConfig(testConfig); + APIImportConfigAdapter adapter = new APIImportConfigAdapter(params); + API api = new API(); + api.setState(API.STATE_PUBLISHED); + api.setClientOrganizations(Arrays.asList(new Organization("ALL"))); + adapter.handleOrganizations(api); + Assert.assertEquals(api.getClientOrganizations().size(), 1); + } + + @Test + public void handleOrganizationsSingle() throws AppException { + APIImportParams params = new APIImportParams(); + params.setHostname("localhost"); + params.setUsername("test"); + params.setPassword(Utils.getEncryptedPassword()); + String testConfig = this.getClass().getResource("/com/axway/apim/test/files/basic/outbound_basic_auth_empty_password.json").getFile(); + params.setConfig(testConfig); + APIImportConfigAdapter adapter = new APIImportConfigAdapter(params); + API api = new API(); + api.setState(API.STATE_PUBLISHED); + api.setClientOrganizations(Arrays.asList(new Organization("orga"))); + adapter.handleOrganizations(api); + Assert.assertEquals(api.getClientOrganizations().size(), 1); + } + } diff --git a/pom.xml b/pom.xml index dc08b2d71..b28476a22 100644 --- a/pom.xml +++ b/pom.xml @@ -45,8 +45,8 @@ UTF-8 - 1.8 - 1.8 + 11 + 11 github true @@ -281,8 +281,8 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 11 + 11 From a88561b55c8b9cbd565ddeee0d7d55011ce50496 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Fri, 18 Oct 2024 09:33:07 -0700 Subject: [PATCH 05/22] - fix junit --- .../com/axway/apim/adapter/apis/APIManagerAPIAdapterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAdapterTest.java b/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAdapterTest.java index 7f7d454e3..49bc02024 100644 --- a/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAdapterTest.java +++ b/modules/apim-adapter/src/test/java/com/axway/apim/adapter/apis/APIManagerAPIAdapterTest.java @@ -595,7 +595,7 @@ public void loadAPIIncludingClientOrgs() throws IOException { API api = apiManagerAPIAdapter.getAPI(filter, true); Assert.assertNotNull(api.getClientOrganizations(), "Should have a some client organizations"); - Assert.assertEquals(api.getClientOrganizations().size(), 1, "Expected client organization"); + Assert.assertEquals(api.getClientOrganizations().size(), 4, "Expected client organization"); } @Test From 30756f6df1c5cb7e6cbbd95a26908bb37490f4b0 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Mon, 21 Oct 2024 15:07:38 -0700 Subject: [PATCH 06/22] - Handle api method quota update in case of spec is updated as well. --- .../apis/APIManagerAPIMethodAdapter.java | 2 +- modules/apim-cli/assembly/scripts/apim.sh | 4 + .../apiimport/actions/APIQuotaManager.java | 22 +- .../actions/APIQuotaManagerTest.java | 265 +++++++++++- ...eAndUpdateQuotaWithNewMethodAndSpecIT.java | 86 ++++ .../step1/api-config.json | 35 ++ .../upsert_quota_and_spec/step1/api.json | 325 +++++++++++++++ .../step2/api-config.json | 44 ++ .../upsert_quota_and_spec/step2/api.json | 380 ++++++++++++++++++ 9 files changed, 1145 insertions(+), 18 deletions(-) create mode 100644 modules/apis/src/test/java/com/axway/apim/test/quota/CreateAndUpdateQuotaWithNewMethodAndSpecIT.java create mode 100644 modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api-config.json create mode 100644 modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api.json create mode 100644 modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api-config.json create mode 100644 modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api.json diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java index 4c9b300b9..c330289a2 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java @@ -58,7 +58,7 @@ public List getAllMethodsForAPI(String apiId) throws AppException { readMethodsFromAPIManager(apiId); List apiMethods; try { - apiMethods = mapper.readValue(this.apiManagerResponse.get(apiId), new TypeReference>() { + apiMethods = mapper.readValue(this.apiManagerResponse.get(apiId), new TypeReference<>() { }); } catch (IOException e) { throw new AppException(ERROR_CANT_LOAD_API_METHODS_FOR_API + apiId + "' from API-Manager.", ErrorCode.API_MANAGER_COMMUNICATION, e); diff --git a/modules/apim-cli/assembly/scripts/apim.sh b/modules/apim-cli/assembly/scripts/apim.sh index 09973f796..1c6d0109f 100644 --- a/modules/apim-cli/assembly/scripts/apim.sh +++ b/modules/apim-cli/assembly/scripts/apim.sh @@ -32,6 +32,10 @@ done cd "$currentDir" +### Enable Debugging of http headers and payload +### "$_java" -Xms64m -Xmx256m -Dlog4j.configurationFile=../lib/log4j2.xml -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG -classpath "$CP" com.axway.apim.cli.APIManagerCLI "${@}" + + "$_java" -Xms64m -Xmx256m -Dlog4j.configurationFile=../lib/log4j2.xml -classpath "$CP" com.axway.apim.cli.APIManagerCLI "${@}" rc=$? exit $rc diff --git a/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java b/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java index 0e8ee2b42..a6b65e0d4 100644 --- a/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java +++ b/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java @@ -96,7 +96,7 @@ public List mergeRestriction(List existingRe desiredRestriction.setApiId(null); // And compare each desired restriction, if it is already included in the existing restrictions for (QuotaRestriction existingRestriction : existingRestrictions) { - // It's considered as the same restriction when type, method, period & per are equal + // It's considered as the same restriction when quota type, method, period & per are equal if (desiredRestriction.isSameRestriction(existingRestriction, true)) { // If it is the same restriction, we need to update the restriction configuration if (existingRestriction.getType() == QuotaRestrictionType.throttle) { @@ -144,15 +144,21 @@ public void populateMethodId(API createdAPI, List mergedRestri // Additionally, we have to change the methodId // Load the method for actualAPI to get the name of the method to which the existing quota is applied to if (actualState != null) { - APIMethod actualMethod = methodAdapter.getMethodForName(actualState.getId(), restriction.getMethod()); - if (actualMethod != null) { - // Now load the new method based on the name for the createdAPI - APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), actualMethod.getName()); - // Finally modify the restriction + try { + APIMethod actualMethod = methodAdapter.getMethodForName(actualState.getId(), restriction.getMethod()); + if (actualMethod != null) { + // Now load the new method based on the name for the createdAPI + APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), actualMethod.getName()); + // Finally modify the restriction + restriction.setMethod(newMethod.getId()); + } + } catch (AppException e) { + LOG.warn("{}", e.getMessage()); + // Now load the new method based on the name for the createdAPI as existing api does not have the method. + APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), restriction.getMethod()); restriction.setMethod(newMethod.getId()); - } else { - LOG.warn("API Method Name : {} not found in specification", restriction.getMethod()); } + } else { // For new api creation APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), restriction.getMethod()); diff --git a/modules/apis/src/test/java/com/axway/apim/apiimport/actions/APIQuotaManagerTest.java b/modules/apis/src/test/java/com/axway/apim/apiimport/actions/APIQuotaManagerTest.java index 67e3c96e5..3b9747935 100644 --- a/modules/apis/src/test/java/com/axway/apim/apiimport/actions/APIQuotaManagerTest.java +++ b/modules/apis/src/test/java/com/axway/apim/apiimport/actions/APIQuotaManagerTest.java @@ -1,19 +1,39 @@ package com.axway.apim.apiimport.actions; +import com.axway.apim.WiremockWrapper; +import com.axway.apim.api.API; +import com.axway.apim.api.model.APIQuota; import com.axway.apim.api.model.QuotaRestriction; +import com.axway.apim.lib.CoreParameters; +import com.axway.apim.lib.utils.Utils; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.io.IOException; import java.util.List; -public class APIQuotaManagerTest { +public class APIQuotaManagerTest extends WiremockWrapper { + + @BeforeClass + public void initWiremock() { + super.initWiremock(); + } + + @AfterClass + public void close() { + super.close(); + } + + ObjectMapper objectMapper = new ObjectMapper(); + @Test public void mergeRestriction() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); String actualQuota = "[\n" + " {\n" + " \"api\": \"*\",\n" + @@ -69,7 +89,7 @@ public void mergeRestriction() throws IOException { " }\n" + " }\n" + " ]"; - TypeReference> quotaRestrictionTypeRef = new TypeReference>() { + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { }; List actualQuotaRestriction = objectMapper.readValue(actualQuota, quotaRestrictionTypeRef); List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); @@ -81,7 +101,6 @@ public void mergeRestriction() throws IOException { @Test public void mergeRestrictionActual() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); String actualQuota = "[\n" + " {\n" + " \"api\": \"4f52e8a2-cba1-4645-8088-2ed98f5ea57e\",\n" + @@ -137,7 +156,7 @@ public void mergeRestrictionActual() throws IOException { " }\n" + " }\n" + " ]"; - TypeReference> quotaRestrictionTypeRef = new TypeReference>() { + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { }; List actualQuotaRestriction = objectMapper.readValue(actualQuota, quotaRestrictionTypeRef); List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); @@ -148,7 +167,6 @@ public void mergeRestrictionActual() throws IOException { @Test public void mergeRestrictionDesired() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); String actualQuota = "[\n" + " {\n" + " \"method\": \"PATCH /{txid}\",\n" + @@ -199,7 +217,7 @@ public void mergeRestrictionDesired() throws IOException { " }\n" + " }\n" + " ]"; - TypeReference> quotaRestrictionTypeRef = new TypeReference>() { + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { }; List actualQuotaRestriction = objectMapper.readValue(actualQuota, quotaRestrictionTypeRef); List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); @@ -211,7 +229,6 @@ public void mergeRestrictionDesired() throws IOException { @Test public void mergeRestrictionDesiredWithNoActual() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); String actualQuota = "[]"; String desiredQuota = "[\n" + @@ -243,7 +260,7 @@ public void mergeRestrictionDesiredWithNoActual() throws IOException { " }\n" + " }\n" + " ]"; - TypeReference> quotaRestrictionTypeRef = new TypeReference>() { + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { }; List actualQuotaRestriction = objectMapper.readValue(actualQuota, quotaRestrictionTypeRef); List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); @@ -251,4 +268,234 @@ public void mergeRestrictionDesiredWithNoActual() throws IOException { List result = apiQuotaManager.mergeRestriction(actualQuotaRestriction, desiredQuotaRestriction); Assert.assertEquals(3, result.size()); } + + + @Test + public void populateMethodIdForNewApi() throws JsonProcessingException { + + CoreParameters coreParameters = new CoreParameters(); + coreParameters.setHostname("localhost"); + coreParameters.setUsername("test"); + coreParameters.setPassword(Utils.getEncryptedPassword()); + + String desiredQuota = "[\n" + + " {\n" + + " \"method\": \"addPet\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"656\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"deleteUser\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"750\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"getUserByName\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"887\"\n" + + " }\n" + + " }\n" + + " ]"; + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { + }; + List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); + API createdAPI = new API(); + APIQuota apiQuota = new APIQuota(); + apiQuota.setRestrictions(desiredQuotaRestriction); + createdAPI.setSystemQuota(apiQuota); + createdAPI.setId("e4ded8c8-0a40-4b50-bc13-552fb7209150"); + APIQuotaManager apiQuotaManager = new APIQuotaManager(null, null); + apiQuotaManager.populateMethodId(createdAPI, desiredQuotaRestriction); + + Assert.assertEquals(createdAPI.getSystemQuota().getRestrictions().get(0).getMethod(), "dfd61eee-cf2d-4d97-bbb6-f602fd2063bd"); + + + } + + @Test + public void populateMethodIdForExistingApi() throws JsonProcessingException { + + CoreParameters coreParameters = new CoreParameters(); + coreParameters.setHostname("localhost"); + coreParameters.setUsername("test"); + coreParameters.setPassword(Utils.getEncryptedPassword()); + + String actualQuota = "[\n" + + " {\n" + + " \"method\": \"addPet\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"656\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"deleteUser\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"750\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"getUserByName\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"887\"\n" + + " }\n" + + " }\n" + + " ]"; + + String desiredQuota = "[\n" + + " {\n" + + " \"method\": \"addPet\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"656\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"deleteUser\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"750\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"getUserByName\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"887\"\n" + + " }\n" + + " }\n" + + " ]"; + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { + }; + List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); + API createdAPI = new API(); + APIQuota apiQuota = new APIQuota(); + apiQuota.setRestrictions(desiredQuotaRestriction); + createdAPI.setSystemQuota(apiQuota); + createdAPI.setId("e4ded8c8-0a40-4b50-bc13-552fb7209150"); + + + List actualQuotaRestriction = objectMapper.readValue(actualQuota, quotaRestrictionTypeRef); + API actualAPI = new API(); + APIQuota apiQuotaActualApi = new APIQuota(); + + apiQuotaActualApi.setRestrictions(actualQuotaRestriction); + actualAPI.setSystemQuota(apiQuotaActualApi); + actualAPI.setId("e4ded8c8-0a40-4b50-bc13-552fb7209150"); + + APIQuotaManager apiQuotaManager = new APIQuotaManager(createdAPI, actualAPI); + apiQuotaManager.populateMethodId(createdAPI, desiredQuotaRestriction); + + Assert.assertEquals(createdAPI.getSystemQuota().getRestrictions().get(0).getMethod(), "dfd61eee-cf2d-4d97-bbb6-f602fd2063bd"); + Assert.assertEquals(actualAPI.getSystemQuota().getRestrictions().get(0).getMethod(), "addPet"); + } + + + @Test + public void populateMethodIdForExistingApiWithQuotaChange() throws JsonProcessingException { + + CoreParameters coreParameters = new CoreParameters(); + coreParameters.setHostname("localhost"); + coreParameters.setUsername("test"); + coreParameters.setPassword(Utils.getEncryptedPassword()); + + String actualQuota = "[\n" + + " {\n" + + " \"method\": \"deleteUser\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"750\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"getUserByName\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"887\"\n" + + " }\n" + + " }\n" + + " ]"; + + String desiredQuota = "[\n" + + " {\n" + + " \"method\": \"addPet\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"656\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"deleteUser\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"750\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"method\": \"getUserByName\",\n" + + " \"type\": \"throttle\",\n" + + " \"config\": {\n" + + " \"period\": \"second\",\n" + + " \"per\": \"1\",\n" + + " \"messages\": \"887\"\n" + + " }\n" + + " }\n" + + " ]"; + TypeReference> quotaRestrictionTypeRef = new TypeReference<>() { + }; + List desiredQuotaRestriction = objectMapper.readValue(desiredQuota, quotaRestrictionTypeRef); + API createdAPI = new API(); + APIQuota apiQuota = new APIQuota(); + apiQuota.setRestrictions(desiredQuotaRestriction); + createdAPI.setSystemQuota(apiQuota); + createdAPI.setId("e4ded8c8-0a40-4b50-bc13-552fb7209150"); + + + List actualQuotaRestriction = objectMapper.readValue(actualQuota, quotaRestrictionTypeRef); + API actualAPI = new API(); + APIQuota apiQuotaActualApi = new APIQuota(); + + apiQuotaActualApi.setRestrictions(actualQuotaRestriction); + actualAPI.setSystemQuota(apiQuotaActualApi); + actualAPI.setId("e4ded8c8-0a40-4b50-bc13-552fb7209150"); + + APIQuotaManager apiQuotaManager = new APIQuotaManager(createdAPI, actualAPI); + apiQuotaManager.populateMethodId(createdAPI, desiredQuotaRestriction); + + Assert.assertEquals(createdAPI.getSystemQuota().getRestrictions().get(0).getMethod(), "dfd61eee-cf2d-4d97-bbb6-f602fd2063bd"); + Assert.assertEquals(actualAPI.getSystemQuota().getRestrictions().get(0).getMethod(), "deleteUser"); + } } diff --git a/modules/apis/src/test/java/com/axway/apim/test/quota/CreateAndUpdateQuotaWithNewMethodAndSpecIT.java b/modules/apis/src/test/java/com/axway/apim/test/quota/CreateAndUpdateQuotaWithNewMethodAndSpecIT.java new file mode 100644 index 000000000..c1a249323 --- /dev/null +++ b/modules/apis/src/test/java/com/axway/apim/test/quota/CreateAndUpdateQuotaWithNewMethodAndSpecIT.java @@ -0,0 +1,86 @@ +package com.axway.apim.test.quota; + +import com.axway.apim.EndpointConfig; +import com.axway.apim.test.ImportTestAction; +import org.citrusframework.annotations.CitrusTest; +import org.citrusframework.http.client.HttpClient; +import org.citrusframework.message.MessageType; +import org.citrusframework.testng.spring.TestNGCitrusSpringSupport; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.ContextConfiguration; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.IOException; + +import static org.citrusframework.DefaultTestActionBuilder.action; +import static org.citrusframework.actions.EchoAction.Builder.echo; +import static org.citrusframework.actions.SleepAction.Builder.sleep; +import static org.citrusframework.http.actions.HttpActionBuilder.http; +import static org.citrusframework.validation.DelegatingPayloadVariableExtractor.Builder.fromBody; + +@ContextConfiguration(classes = {EndpointConfig.class}) + +public class CreateAndUpdateQuotaWithNewMethodAndSpecIT extends TestNGCitrusSpringSupport { + + @Autowired + HttpClient apiManager; + + + @CitrusTest + @Test + public void run() throws IOException, InterruptedException { + + $(echo("#######Get initial system quota #######")); + $(http().client(apiManager).send().get("/quotas/00000000-0000-0000-0000-000000000000")); + $(http().client(apiManager).receive().response(HttpStatus.OK).message().type(MessageType.JSON).extract(fromBody() + .expression("$.restrictions.length()", "size"))); + + $(echo("Number of system quota : ${size}")); + + ImportTestAction swaggerImport = new ImportTestAction(); + description("Import an API containing a quota definition"); + variable("useApiAdmin", "true"); + variable("apiName", "Teste api - Quotas"); + + variable(ImportTestAction.API_DEFINITION, "/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api.json"); + variable(ImportTestAction.API_CONFIG, "/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api-config.json"); + variable("expectedReturnCode", "0"); + $(action(swaggerImport)); + + $(echo("####### Check System-Quotas have been setup as configured #######")); + $(echo("####### ############ Sleep 5 seconds ##################### #######")); + $(sleep().seconds(5)); + $(http().client(apiManager).send().get("/quotas/00000000-0000-0000-0000-000000000000")); + $(http().client(apiManager).receive().response(HttpStatus.OK).message().type(MessageType.JSON).extract(fromBody() + .expression("$.restrictions.length()", "size2"))); + $(echo("Number of system quota After import : ${size2}")); + $(testContext -> { + Assert.assertEquals(Integer.parseInt(testContext.getVariable("size2")), Integer.parseInt(testContext.getVariable("size")) + 2); + }); + + + $(echo("####### Executing a Quota-No-Change import #######")); + variable(ImportTestAction.API_DEFINITION, "/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api.json"); + variable(ImportTestAction.API_CONFIG, "/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api-config.json"); + variable("expectedReturnCode", "0"); + $(action(swaggerImport)); + + $(echo("####### Check System-Quotas have been setup as configured #######")); + $(echo("####### ############ Sleep 2 seconds ##################### #######")); + $(sleep().seconds(5)); + $(http().client(apiManager).send().get("/quotas/00000000-0000-0000-0000-000000000000")); + $(http().client(apiManager).receive().response(HttpStatus.OK).message().type(MessageType.JSON).extract(fromBody() + .expression("$.restrictions.length()", "size3"))); + + $(echo("Number of system quota After import2 : ${size3}")); + + + $(testContext -> { + Assert.assertEquals(Integer.parseInt(testContext.getVariable("size3")), Integer.parseInt(testContext.getVariable("size")) + 3); + }); + + } + +} diff --git a/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api-config.json b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api-config.json new file mode 100644 index 000000000..4488b4326 --- /dev/null +++ b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api-config.json @@ -0,0 +1,35 @@ +{ + "name": "Teste api - Quotas", + "path": "/healthcheck/teste/api/versao/1-14-7", + "state": "published", + "version": "1.0.0", + "organization":"API Development ${orgNumber}", + "backendBasepath" : "http://127.0.0.1:8080/healthcheck", + "tags": { + "has-swagger": [ + "false" + ] + }, + "systemQuota": { + "restrictions": [ + { + "method": "addPet", + "type": "throttle", + "config": { + "period": "second", + "per": "1", + "messages": "656" + } + }, + { + "method": "updatePet", + "type": "throttle", + "config": { + "period": "second", + "per": "1", + "messages": "750" + } + } + ] + } +} diff --git a/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api.json b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api.json new file mode 100644 index 000000000..80ae13499 --- /dev/null +++ b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step1/api.json @@ -0,0 +1,325 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version": "1.0.0", + "title": "Swagger Petstore", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host": "petstore.swagger.io", + "basePath": "/healthcheck/teste/api", + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders" + }, + { + "name": "user", + "description": "Operations about user", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "schemes": [ + "https", + "http" + ], + "paths": { + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "", + "operationId": "updatePet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + } + }, + "securityDefinitions": { + "petstore_auth": { + "type": "oauth2", + "authorizationUrl": "https://petstore.swagger.io/oauth/dialog", + "flow": "implicit", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + }, + "definitions": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean", + "default": false + } + }, + "xml": { + "name": "Order" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + }, + "xml": { + "name": "User" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "Pet": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/definitions/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "xml": { + "name": "photoUrl", + "wrapped": true + }, + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "xml": { + "name": "tag", + "wrapped": true + }, + "items": { + "$ref": "#/definitions/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "Pet" + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + } +} \ No newline at end of file diff --git a/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api-config.json b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api-config.json new file mode 100644 index 000000000..fdda68a88 --- /dev/null +++ b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api-config.json @@ -0,0 +1,44 @@ +{ + "name": "Teste api - Quotas", + "path": "/healthcheck/teste/api/versao/1-14-7", + "state": "published", + "version": "1.0.0", + "organization":"API Development ${orgNumber}", + "backendBasepath" : "http://127.0.0.1:8080/healthcheck", + "tags": { + "has-swagger": [ + "false" + ] + }, + "systemQuota": { + "restrictions": [ + { + "method": "addPet", + "type": "throttle", + "config": { + "period": "second", + "per": "1", + "messages": "656" + } + }, + { + "method": "updatePet", + "type": "throttle", + "config": { + "period": "second", + "per": "1", + "messages": "750" + } + }, + { + "method": "findPetsByStatus", + "type": "throttle", + "config": { + "period": "second", + "per": "1", + "messages": "750" + } + } + ] + } +} diff --git a/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api.json b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api.json new file mode 100644 index 000000000..c3c5a5dd5 --- /dev/null +++ b/modules/apis/src/test/resources/com/axway/apim/test/files/quota/upsert_quota_and_spec/step2/api.json @@ -0,0 +1,380 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version": "1.0.0", + "title": "Swagger Petstore", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host": "petstore.swagger.io", + "basePath": "/healthcheck/teste/api", + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders" + }, + { + "name": "user", + "description": "Operations about user", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "schemes": [ + "https", + "http" + ], + "paths": { + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "", + "operationId": "updatePet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": true, + "type": "array", + "items": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "default": "available" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + } + }, + "securityDefinitions": { + "petstore_auth": { + "type": "oauth2", + "authorizationUrl": "https://petstore.swagger.io/oauth/dialog", + "flow": "implicit", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + }, + "definitions": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean", + "default": false + } + }, + "xml": { + "name": "Order" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + }, + "xml": { + "name": "User" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "Pet": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/definitions/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "xml": { + "name": "photoUrl", + "wrapped": true + }, + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "xml": { + "name": "tag", + "wrapped": true + }, + "items": { + "$ref": "#/definitions/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "Pet" + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + } +} \ No newline at end of file From 0d872bb973f270cead79a35409eaaa460b24bec9 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Mon, 21 Oct 2024 21:12:42 -0700 Subject: [PATCH 07/22] - remove duplicates --- .../adapter/apis/APIManagerAPIMethodAdapter.java | 11 +++++++---- .../apim/apiimport/actions/APIQuotaManager.java | 13 ++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java index c330289a2..a5e232668 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/adapter/apis/APIManagerAPIMethodAdapter.java @@ -69,7 +69,7 @@ public List getAllMethodsForAPI(String apiId) throws AppException { public APIMethod getMethodForName(String apiId, String methodName) throws AppException { List apiMethods = getAllMethodsForAPI(apiId); if (apiMethods.isEmpty()) { - LOG.warn("No operations found for API with id: {}", apiId); + logMessage(apiId); return null; } for (APIMethod method : apiMethods) { @@ -78,16 +78,19 @@ public APIMethod getMethodForName(String apiId, String methodName) throws AppExc return method; } } - LOG.debug("{} - {}",apiId, methodName); throw new AppException("No operation found with name: '" + methodName + "'", ErrorCode.API_OPERATION_NOT_FOUND); } + private void logMessage(String apiId) { + LOG.warn("No operations found for API with id: {}", apiId); + } + public APIMethod getMethodForId(String apiId, String methodId) throws AppException { - if(methodId.equals("*")) + if (methodId.equals("*")) return null; List apiMethods = getAllMethodsForAPI(apiId); if (apiMethods.isEmpty()) { - LOG.warn("No operations found for API with id: {}", apiId); + logMessage(apiId); return null; } for (APIMethod method : apiMethods) { diff --git a/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java b/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java index a6b65e0d4..954f2c367 100644 --- a/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java +++ b/modules/apis/src/main/java/com/axway/apim/apiimport/actions/APIQuotaManager.java @@ -155,18 +155,21 @@ public void populateMethodId(API createdAPI, List mergedRestri } catch (AppException e) { LOG.warn("{}", e.getMessage()); // Now load the new method based on the name for the createdAPI as existing api does not have the method. - APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), restriction.getMethod()); - restriction.setMethod(newMethod.getId()); + updateMethodId(createdAPI, restriction); } - } else { // For new api creation - APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), restriction.getMethod()); - restriction.setMethod(newMethod.getId()); + updateMethodId(createdAPI, restriction); } } } + public void updateMethodId(API createdAPI, QuotaRestriction restriction) throws AppException { + APIManagerAPIMethodAdapter methodAdapter = APIManagerAdapter.getInstance().getMethodAdapter(); + APIMethod newMethod = methodAdapter.getMethodForName(createdAPI.getId(), restriction.getMethod()); + restriction.setMethod(newMethod.getId()); + } + private List getRestrictions(APIQuota quota) { if (quota == null) return Collections.emptyList(); return quota.getRestrictions(); From abb1f3634cc61b3fcad8c8b1dc2bf3d82c155436 Mon Sep 17 00:00:00 2001 From: rathnapandi Date: Tue, 22 Oct 2024 08:28:07 -0700 Subject: [PATCH 08/22] - fix sonar issues --- .../com/axway/apim/api/model/APIQuota.java | 6 +- .../axway/apim/api/model/CustomProperty.java | 64 +++++++++---------- .../axway/apim/lib/error/AppException.java | 13 ++-- .../main/java/com/axway/apim/TestUtils.java | 2 +- 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/APIQuota.java b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/APIQuota.java index ddef14913..f1dcca0f6 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/APIQuota.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/APIQuota.java @@ -17,7 +17,7 @@ public class APIQuota { String description; - Boolean system; + boolean system; List restrictions; @@ -61,11 +61,11 @@ public void setId(String id) { this.id = id; } - public Boolean getSystem() { + public boolean getSystem() { return system; } - public void setSystem(Boolean system) { + public void setSystem(boolean system) { this.system = system; } diff --git a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/CustomProperty.java b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/CustomProperty.java index 1ae6f9d52..e9345566a 100644 --- a/modules/apim-adapter/src/main/java/com/axway/apim/api/model/CustomProperty.java +++ b/modules/apim-adapter/src/main/java/com/axway/apim/api/model/CustomProperty.java @@ -3,33 +3,33 @@ import java.util.List; public class CustomProperty { - + private String label; - + private String type; - - private Boolean disabled; - - private Boolean required; - + + private boolean disabled; + + private boolean required; + private String help; - + private List