From 62cd1b137941d1da7da0be3ed8ee5ca22dfd5b63 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 13 Aug 2024 17:48:18 +0530 Subject: [PATCH 01/74] Add initial implementation --- .../wso2/carbon/apimgt/api/APIConsumer.java | 12 +++ .../carbon/apimgt/api/ExceptionCodes.java | 1 + .../org/wso2/carbon/apimgt/api/model/API.java | 12 ++- .../apimgt/api/model/OrganizationInfo.java | 59 ++++++++++++++ .../wso2/carbon/apimgt/impl/APIConstants.java | 1 + .../carbon/apimgt/impl/APIConsumerImpl.java | 33 ++++++-- .../apimgt/persistence/APIConstants.java | 4 + .../persistence/RegistryPersistenceImpl.java | 4 +- .../apimgt/persistence/dto/PublisherAPI.java | 78 +++++++++++-------- .../apimgt/persistence/mapper/APIMapper.java | 4 +- .../utils/RegistryPersistenceUtil.java | 9 ++- .../rest/api/common/RestApiConstants.java | 1 + .../src/main/resources/publisher-api.yaml | 31 ++------ .../rest/api/publisher/v1/dto/APIDTO.java | 26 ++++++- .../v1/common/mappings/APIMappingUtil.java | 17 ++++ .../common/mappings/PublisherCommonUtils.java | 8 ++ .../src/main/resources/publisher-api.yaml | 7 ++ .../api/store/v1/impl/ApisApiServiceImpl.java | 12 ++- .../impl/OAuthOpaqueAuthenticatorImpl.java | 64 +++++++++++++++ .../auth/OAuthAuthenticationInterceptor.java | 9 +++ .../rest/api/util/utils/RestApiUtil.java | 15 ++++ .../src/main/resources/rxts/api.rxt | 3 + 22 files changed, 336 insertions(+), 74 deletions(-) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java index 72d1d703bd3f..f3edb073ec61 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java @@ -36,6 +36,7 @@ import org.wso2.carbon.apimgt.api.model.KeyManagerApplicationInfo; import org.wso2.carbon.apimgt.api.model.Monetization; import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.SubscribedAPI; @@ -879,4 +880,15 @@ boolean isKeyManagerByNameAllowedForUser(String keyManagerName, String organizat * @throws APIManagementException */ boolean removalKeys(Application application, String keyMappingId, String xWSO2Tenant) throws APIManagementException; + + /** + * @param searchQuery search query. ex : provider:admin + * @param organizationInfo Identifier of an organization + * @param start starting number + * @param end ending number + * @return + * @throws APIManagementException + */ + Map searchPaginatedAPIs(String searchQuery, OrganizationInfo organizationInfo, int start, int end, + String sortBy, String sortOrder) throws APIManagementException; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java index e235bd68d70a..2ceeb49cd507 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java @@ -100,6 +100,7 @@ public enum ExceptionCodes implements ErrorHandler { INVALID_CONTEXT(900346, "Invalid context provided", 400, "Invalid context provided for API: %s:%s"), INVALID_ENDPOINT_URL(900346, "Endpoint URL(s) is(are) not valid", 400, "Endpoint URL(s) is(are) not valid"), USER_ROLES_CANNOT_BE_NULL(900610, "Access control roles cannot be empty", 400, "Access control roles cannot be empty when visibility is restricted"), + ORGS_CANNOT_BE_NULL(900610, "Access control organizatoins cannot be empty", 400, "Access control organizations cannot be empty when visibility is restricted"), API_REVISION_NOT_FOUND(900347, "API Revision Not Found", 404, "Requested API Revision with id %s not found"), EXISTING_API_REVISION_DEPLOYMENT_FOUND(900348, "Can not delete API Revision ", 400, "Couldn't delete API revision since API revision is currently deployed to a gateway. " + "You need to undeploy the API Revision from the gateway before attempting deleting API Revision: %s "), diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java index 64da343d671f..c00d0de2afed 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java @@ -98,8 +98,10 @@ public class API implements Serializable { private String visibility; private String visibleRoles; private String visibleTenants; + private String visibleOrganizations; - private boolean endpointSecured = false; + + private boolean endpointSecured = false; private boolean endpointAuthDigest = false; private String endpointUTUsername; private String endpointUTPassword; @@ -1499,4 +1501,12 @@ public List getApiPolicies() { public void setApiPolicies(List apiPolicies) { this.apiPolicies = apiPolicies; } + + public String getVisibleOrganizations() { + return visibleOrganizations; + } + + public void setVisibleOrganizations(String visibleOrganizations) { + this.visibleOrganizations = visibleOrganizations; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java new file mode 100644 index 000000000000..a3b832296bee --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.wso2.carbon.apimgt.api.model; + +public class OrganizationInfo { + + + String superOrganization; + String name; + String id; + OrganizationInfo parentOrganization; + OrganizationInfo[] childOrganizations; + + public String getSuperOrganization() { + return superOrganization; + } + public void setSuperOrganization(String superOrganization) { + this.superOrganization = superOrganization; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public OrganizationInfo getParentOrganization() { + return parentOrganization; + } + public void setParentOrganization(OrganizationInfo parentOrganization) { + this.parentOrganization = parentOrganization; + } + public OrganizationInfo[] getChildOrganizations() { + return childOrganizations; + } + public void setChildOrganizations(OrganizationInfo[] childOrganizations) { + this.childOrganizations = childOrganizations; + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index d3ddce152252..ef5461ccbb3e 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -219,6 +219,7 @@ public final class APIConstants { public static final String VISIBILITY = "visibility"; public static final String API_RESTRICTED_VISIBILITY = "restricted"; + public static final String API_RESTRICTED_BY_ORG = "restricted_by_org"; public static final String API_PRIVATE_VISIBILITY = "private"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 7ba7f75129f4..ae44701e65d6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -74,6 +74,7 @@ import org.wso2.carbon.apimgt.api.model.Monetization; import org.wso2.carbon.apimgt.api.model.OAuthAppRequest; import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.SubscribedAPI; @@ -3824,16 +3825,36 @@ public void changeUserPassword(String currentPassword, String newPassword) throw @Override public Map searchPaginatedAPIs(String searchQuery, String organization, int start, int end, String sortBy, String sortOrder) throws APIManagementException { - - Map result = new HashMap(); - if (log.isDebugEnabled()) { - log.debug("Original search query received : " + searchQuery); - } + Organization org = new Organization(organization); String userName = (userNameWithoutChange != null) ? userNameWithoutChange : username; String[] roles = APIUtil.getListOfRoles(userName); Map properties = APIUtil.getUserProperties(userName); UserContext userCtx = new UserContext(userNameWithoutChange, org, properties, roles); + + return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); + } + + @Override + public Map searchPaginatedAPIs(String searchQuery, OrganizationInfo organizationInfo, int start, int end, + String sortBy, String sortOrder) throws APIManagementException { + Organization org = new Organization(organizationInfo.getSuperOrganization()); + String userName = (userNameWithoutChange != null) ? userNameWithoutChange : username; + String[] roles = APIUtil.getListOfRoles(userName); + Map properties = APIUtil.getUserProperties(userName); + UserContext userCtx = new UserContext(userNameWithoutChange, new Organization(organizationInfo.getName()), + properties, roles); + + return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); + } + + private Map searchPaginatedAPIs(String searchQuery, int start, int end, Organization org, + UserContext userCtx) throws APIManagementException { + Map result = new HashMap(); + if (log.isDebugEnabled()) { + log.debug("Original search query received : " + searchQuery); + } + try { DevPortalAPISearchResult searchAPIs = apiPersistenceInstance.searchAPIsForDevPortal(org, searchQuery, start, end, userCtx); @@ -3878,7 +3899,7 @@ public Map searchPaginatedAPIs(String searchQuery, String organi throw new APIManagementException("Error while searching the api ", e); } return result; - } + } @Override public ApiTypeWrapper getAPIorAPIProductByUUID(String uuid, String organization) throws APIManagementException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java index 48334184b9e9..c77465e62cff 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java @@ -52,6 +52,7 @@ public final class APIConstants { public static final String API_OVERVIEW_VISIBILITY = "overview_visibility"; public static final String API_OVERVIEW_VISIBLE_ROLES = "overview_visibleRoles"; public static final String API_OVERVIEW_VISIBLE_TENANTS = "overview_visibleTenants"; + public static final String API_OVERVIEW_VISIBLE_ORGANIZATIONS = "overview_visibleOrganizations"; public static final String API_OVERVIEW_ENVIRONMENTS = "overview_environments"; public static final String API_OVERVIEW_AUDIENCE = "overview_audience"; public static final String API_OVERVIEW_AUDIENCES = "overview_audiences"; @@ -206,6 +207,7 @@ public static class Monetization { public static final String NULL_USER_ROLE_LIST = "null"; public static final String API_RESTRICTED_VISIBILITY = "restricted"; public static final String API_PRIVATE_VISIBILITY = "private"; + public static final String API_RESTRICTED_BY_ORG = "restricted_by_org"; public static final String API_CONTROLLED_VISIBILITY = "controlled"; public static final String DOC_OWNER_VISIBILITY = "OWNER_ONLY"; public static final String API_GLOBAL_VISIBILITY = "public"; @@ -384,4 +386,6 @@ public enum APITransportType { public static final String API_OVERVIEW_GATEWAY_VENDOR = "overview_gatewayVendor"; public static final String ASYNC_API_TRANSPORT_PROTOCOLS = "overview_asyncTransportProtocols"; + + public static final String DEFAULT_VISIBLE_ORG = "all"; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index f3a83f589b87..4767a11f1c80 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -35,6 +35,7 @@ import org.wso2.carbon.apimgt.persistence.dto.*; import org.wso2.carbon.apimgt.persistence.dto.Documentation; import org.wso2.carbon.apimgt.persistence.dto.Mediation; +import org.wso2.carbon.apimgt.persistence.dto.Organization; import org.wso2.carbon.apimgt.persistence.dto.ResourceFile; import org.wso2.carbon.apimgt.persistence.dto.DocumentContent.ContentSourceType; import org.wso2.carbon.apimgt.persistence.exceptions.*; @@ -1077,8 +1078,9 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String log.debug("Requested query for devportal search: " + searchQuery); String modifiedQuery = RegistrySearchUtil.getDevPortalSearchQuery(searchQuery, ctx, isAllowDisplayAPIsWithMultipleStatus(), isAllowDisplayAPIsWithMultipleVersions()); + modifiedQuery = modifiedQuery + "&visibleOrganizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" + + ctx.getOrganization().getName() + "*)"; log.debug("Modified query for devportal search: " + modifiedQuery); - String userNameLocal; if (holder.isAnonymousMode()) { userNameLocal = APIConstants.WSO2_ANONYMOUS_USER; diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java index 03dfda3dc5cb..aebcad716376 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java @@ -44,7 +44,8 @@ public class PublisherAPI extends PublisherAPIInfo { private String businessOwnerEmail; private String visibility; private String visibleRoles; - private String visibleOrganizations; //visibleTenants + private String visibleSuperOrganizations; //visibleTenants + private String visibleOrganizations; //visible organizations private boolean endpointSecured; private String swaggerDefinition; private String asyncApiDefinition; @@ -624,39 +625,48 @@ public String getVendor() { public void setVendor(String vendor) { this.vendor = vendor; } - - @Override - public String toString() { - return "PublisherAPI [isDefaultVersion=" + isDefaultVersion + ", description=" + description + ", wsdlUrl=" - + wsdlUrl + ", wadlUrl=" + wadlUrl + ", technicalOwner=" + technicalOwner + ", technicalOwnerEmail=" - + technicalOwnerEmail + ", businessOwner=" + businessOwner + ", businessOwnerEmail=" - + businessOwnerEmail + ", visibility=" + visibility + ", visibleRoles=" + visibleRoles - + ", visibleOrganizations=" + visibleOrganizations + ", endpointSecured=" + endpointSecured - + ", endpointAuthDigest=" + endpointAuthDigest + ", endpointUTUsername=" + endpointUTUsername - + ", endpointUTPassword=" + endpointUTPassword + ", transports=" + transports + ", inSequence=" - + inSequence + ", outSequence=" + outSequence + ", faultSequence=" + faultSequence + ", responseCache=" - + responseCache + ", cacheTimeout=" + cacheTimeout + ", endpointConfig=" + endpointConfig - + ", subscriptionAvailability=" + subscriptionAvailability + ", subscriptionAvailableOrgs=" - + subscriptionAvailableOrgs + ", implementation=" + implementation + ", productionMaxTps=" - + productionMaxTps + ", sandboxMaxTps=" + sandboxMaxTps + ", authorizationHeader=" + authorizationHeader - + ", apiKeyHeader=" + apiKeyHeader - + ", apiSecurity=" + apiSecurity + ", enableSchemaValidation=" + enableSchemaValidation - + ", enableSubscriberVerification=" + enableSubscriberVerification + ", enableStore=" + enableStore - + ", testKey=" + testKey + ", contextTemplate=" + contextTemplate + ", availableTierNames=" - + availableTierNames + ", environments=" + environments - + ", corsConfiguration=" + corsConfiguration + ", websubSubscriptionConfiguration=" - + websubSubscriptionConfiguration + ", apiCategories=" - + apiCategories + ", isMonetizationEnabled=" + isMonetizationEnabled + ", monetizationProperties=" - + monetizationProperties + ", keyManagers=" + keyManagers + ", deploymentEnvironments=" - + deploymentEnvironments + ", tags=" + tags + ", accessControl=" + accessControl + ", gatewayVendor=" - + gatewayVendor + ", asyncTransportProtocols=" + asyncTransportProtocols + ", accessControlRoles=" - + accessControlRoles + ", additionalProperties=" + additionalProperties - + ", thumbnail=" + thumbnail + ", createdTime=" + createdTime + ", lastUpdated=" + lastUpdated - + ", versionTimestamp=" + versionTimestamp + ",apiExternalProductionEndpoint=" - + apiExternalProductionEndpoint + ",apiExternalSandboxEndpoint=" + apiExternalSandboxEndpoint - + ", originalDevportalURL" + redirectURL + ", apiOwner" + apiOwner + ", vendor" + vendor - + ", toString()=" + super.toString() + "]"; - } + + public String getVisibleSuperOrganizations() { + return visibleSuperOrganizations; + } + + public void setVisibleSuperOrganizations(String visibleSuperOrganizations) { + this.visibleSuperOrganizations = visibleSuperOrganizations; + } + + @Override + public String toString() { + return "PublisherAPI [isDefaultVersion=" + isDefaultVersion + ", description=" + description + ", wsdlUrl=" + + wsdlUrl + ", wadlUrl=" + wadlUrl + ", technicalOwner=" + technicalOwner + ", technicalOwnerEmail=" + + technicalOwnerEmail + ", businessOwner=" + businessOwner + ", businessOwnerEmail=" + + businessOwnerEmail + ", visibility=" + visibility + ", visibleRoles=" + visibleRoles + + ", visibleSuperOrganizations=" + visibleSuperOrganizations + ", visibleOrganizations=" + + visibleOrganizations + ", endpointSecured=" + endpointSecured + ", swaggerDefinition=" + + swaggerDefinition + ", asyncApiDefinition=" + asyncApiDefinition + ", endpointAuthDigest=" + + endpointAuthDigest + ", endpointUTUsername=" + endpointUTUsername + ", endpointUTPassword=" + + endpointUTPassword + ", transports=" + transports + ", inSequence=" + inSequence + ", outSequence=" + + outSequence + ", faultSequence=" + faultSequence + ", responseCache=" + responseCache + + ", cacheTimeout=" + cacheTimeout + ", endpointConfig=" + endpointConfig + + ", subscriptionAvailability=" + subscriptionAvailability + ", subscriptionAvailableOrgs=" + + subscriptionAvailableOrgs + ", implementation=" + implementation + ", productionMaxTps=" + + productionMaxTps + ", sandboxMaxTps=" + sandboxMaxTps + ", authorizationHeader=" + authorizationHeader + + ", apiKeyHeader=" + apiKeyHeader + ", apiSecurity=" + apiSecurity + ", enableSchemaValidation=" + + enableSchemaValidation + ", enableSubscriberVerification=" + enableSubscriberVerification + + ", enableStore=" + enableStore + ", testKey=" + testKey + ", contextTemplate=" + contextTemplate + + ", availableTierNames=" + availableTierNames + ", environments=" + environments + + ", corsConfiguration=" + corsConfiguration + ", websubSubscriptionConfiguration=" + + websubSubscriptionConfiguration + ", apiCategories=" + apiCategories + ", isMonetizationEnabled=" + + isMonetizationEnabled + ", monetizationProperties=" + monetizationProperties + ", keyManagers=" + + keyManagers + ", deploymentEnvironments=" + deploymentEnvironments + ", tags=" + tags + + ", accessControl=" + accessControl + ", accessControlRoles=" + accessControlRoles + + ", additionalProperties=" + additionalProperties + ", thumbnail=" + thumbnail + ", createdTime=" + + createdTime + ", lastUpdated=" + lastUpdated + ", soapToRestSequences=" + soapToRestSequences + + ", wsUriMapping=" + wsUriMapping + ", gatewayVendor=" + gatewayVendor + ", asyncTransportProtocols=" + + asyncTransportProtocols + ", versionTimestamp=" + versionTimestamp + ", audience=" + audience + + ", apiExternalProductionEndpoint=" + apiExternalProductionEndpoint + ", apiExternalSandboxEndpoint=" + + apiExternalSandboxEndpoint + ", redirectURL=" + redirectURL + ", apiOwner=" + apiOwner + ", vendor=" + + vendor + "]"; + } } /* diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapper.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapper.java index 1222c3c8e271..bd46e86c5b2d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapper.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapper.java @@ -53,7 +53,7 @@ public interface APIMapper { @Mapping(source = "id", target = "uuid") @Mapping(source = "thumbnail", target = "thumbnailUrl") @Mapping(source = "availableTierNames", target = "availableTiers") - @Mapping(source = "visibleOrganizations", target = "visibleTenants") + @Mapping(source = "visibleSuperOrganizations", target = "visibleTenants") @Mapping(source = "subscriptionAvailableOrgs", target = "subscriptionAvailableTenants") @Mapping(source = "gatewayVendor", target = "gatewayVendor") API toApi(PublisherAPI api); @@ -64,7 +64,7 @@ public interface APIMapper { @Mapping(source = "thumbnailUrl", target = "thumbnail") @Mapping(source = "availableTiers", target = "availableTierNames") @Mapping(source = "uuid", target = "id") - @Mapping(source = "visibleTenants", target = "visibleOrganizations") + @Mapping(source = "visibleTenants", target = "visibleSuperOrganizations") @Mapping(source = "subscriptionAvailableTenants", target = "subscriptionAvailableOrgs") @Mapping(source = "gatewayVendor", target = "gatewayVendor") PublisherAPI toPublisherApi(API api); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index bda9ce68da7b..d22b16155b1b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -178,7 +178,13 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_ENABLE_STORE, Boolean.toString(api.isEnableStore())); artifact.setAttribute(APIConstants.API_OVERVIEW_TESTKEY, api.getTestKey()); artifact.setAttribute(APIConstants.API_OVERVIEW_VERSION_COMPARABLE, api.getVersionTimestamp()); - + if (APIConstants.API_RESTRICTED_BY_ORG.equals(api.getVisibility())) { + artifact.setAttribute(APIConstants.API_OVERVIEW_VISIBLE_ORGANIZATIONS, api.getVisibleOrganizations()); + } else { + // Set a default value if org visibility is not set. This is done to generate search query for public apis + artifact.setAttribute(APIConstants.API_OVERVIEW_VISIBLE_ORGANIZATIONS, APIConstants.DEFAULT_VISIBLE_ORG); + } + //Validate if the API has an unsupported context before setting it in the artifact String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); if (APIConstants.SUPER_TENANT_DOMAIN.equals(tenantDomain)) { @@ -601,6 +607,7 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry) api.setVisibility(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBILITY)); api.setVisibleRoles(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBLE_ROLES)); api.setVisibleTenants(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBLE_TENANTS)); + api.setVisibleOrganizations(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBLE_ORGANIZATIONS)); api.setEndpointSecured(Boolean.parseBoolean(artifact.getAttribute( APIConstants.API_OVERVIEW_ENDPOINT_SECURED))); api.setEndpointAuthDigest(Boolean.parseBoolean(artifact.getAttribute( diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java index f36b87e33521..a523b63e711e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java @@ -39,6 +39,7 @@ public final class RestApiConstants { public static final String AUTHENTICATION_REQUIRED = "authentication_required"; public static final String HEADER_X_WSO2_TENANT = "x-wso2-tenant"; public static final String ORGANIZATION = "organization"; + public static final String ORGANIZATION_INFO = "organization_info"; public static final String SUB_ORGANIZATION = "sub_organization"; public static final String MASKED_TOKEN = "maskedToken"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index c82c7450c1c3..ca7602542f8d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -9226,12 +9226,6 @@ components: enum: - PUBLIC - SINGLE - audiences: - type: array - description: The audiences of the API for jwt validation. Accepted values are any String values - items: - type: string - example: [ "aud1","aud2","aud3" ] lifeCycleStatus: type: string example: CREATED @@ -9449,12 +9443,6 @@ components: enum: - PUBLIC - SINGLE - audiences: - type: array - description: The audiences of the API for jwt validation. Accepted values are any String values - items: - type: string - example: [ "aud1","aud2","aud3" ] transport: type: array description: | @@ -9525,6 +9513,7 @@ components: - PUBLIC - PRIVATE - RESTRICTED + - RESTRICTED_BY_ORG x-otherScopes: - apim:api_publish - apim:api_manage @@ -9542,6 +9531,12 @@ components: example: [] items: type: string + visibleOrganizations: + type: array + description: The organizations that are able to access the API in Developer Portal + example: [] + items: + type: string mediationPolicies: type: array example: @@ -10047,12 +10042,6 @@ components: gatewayVendor: type: string example: wso2 - audiences: - type: array - description: The audiences of the API product for jwt validation. Accepted values are any String values - items: - type: string - example: [ "aud1","aud2","aud3" ] monetizedInfo: type: boolean example: true @@ -10326,12 +10315,6 @@ components: workflowStatus: type: string example: APPROVED - audiences: - type: array - description: The audiences of the API for jwt validation. Accepted values are any String values - items: - type: string - example: [ "aud1","aud2","aud3" ] ProductAPI: title: ProductAPI required: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java index a4c9d314a950..bb7f4eae3552 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java @@ -154,7 +154,8 @@ public static AudienceEnum fromValue(String v) { public enum VisibilityEnum { PUBLIC("PUBLIC"), PRIVATE("PRIVATE"), - RESTRICTED("RESTRICTED"); + RESTRICTED("RESTRICTED"), + RESTRICTED_BY_ORG("RESTRICTED_BY_ORG"); private String value; VisibilityEnum (String v) { @@ -187,6 +188,7 @@ public static VisibilityEnum fromValue(String v) { @Scope(name = "apim:api_manage", description="", value ="") private List visibleRoles = new ArrayList(); private List visibleTenants = new ArrayList(); + private List visibleOrganizations = new ArrayList(); private List mediationPolicies = new ArrayList(); private APIOperationPoliciesDTO apiPolicies = null; @@ -884,6 +886,24 @@ public void setVisibleTenants(List visibleTenants) { this.visibleTenants = visibleTenants; } + /** + * The organizations that are able to access the API in Developer Portal + **/ + public APIDTO visibleOrganizations(List visibleOrganizations) { + this.visibleOrganizations = visibleOrganizations; + return this; + } + + + @ApiModelProperty(example = "[]", value = "The organizations that are able to access the API in Developer Portal") + @JsonProperty("visibleOrganizations") + public List getVisibleOrganizations() { + return visibleOrganizations; + } + public void setVisibleOrganizations(List visibleOrganizations) { + this.visibleOrganizations = visibleOrganizations; + } + /** **/ public APIDTO mediationPolicies(List mediationPolicies) { @@ -1426,6 +1446,7 @@ public boolean equals(java.lang.Object o) { Objects.equals(visibility, API.visibility) && Objects.equals(visibleRoles, API.visibleRoles) && Objects.equals(visibleTenants, API.visibleTenants) && + Objects.equals(visibleOrganizations, API.visibleOrganizations) && Objects.equals(mediationPolicies, API.mediationPolicies) && Objects.equals(apiPolicies, API.apiPolicies) && Objects.equals(subscriptionAvailability, API.subscriptionAvailability) && @@ -1458,7 +1479,7 @@ public boolean equals(java.lang.Object o) { @Override public int hashCode() { - return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, audiences, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, gatewayType, asyncTransportProtocols); + return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, audiences, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, visibleOrganizations, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, gatewayType, asyncTransportProtocols); } @Override @@ -1498,6 +1519,7 @@ public String toString() { sb.append(" visibility: ").append(toIndentedString(visibility)).append("\n"); sb.append(" visibleRoles: ").append(toIndentedString(visibleRoles)).append("\n"); sb.append(" visibleTenants: ").append(toIndentedString(visibleTenants)).append("\n"); + sb.append(" visibleOrganizations: ").append(toIndentedString(visibleOrganizations)).append("\n"); sb.append(" mediationPolicies: ").append(toIndentedString(mediationPolicies)).append("\n"); sb.append(" apiPolicies: ").append(toIndentedString(apiPolicies)).append("\n"); sb.append(" subscriptionAvailability: ").append(toIndentedString(subscriptionAvailability)).append("\n"); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java index ea653cfe901f..206bf4e1b053 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java @@ -316,6 +316,15 @@ public static API fromDTOtoAPI(APIDTO dto, String provider) throws APIManagement model.setVisibleTenants(visibleTenants); } } + + if (dto.getVisibleOrganizations() != null) { + String visibleOrgs = StringUtils.join(dto.getVisibleOrganizations(), ','); + model.setVisibleOrganizations(visibleOrgs); +// check if need to have a config +// if (APIUtil.isCrossTenantSubscriptionsEnabled()) { +// +// } + } List accessControlRoles = dto.getAccessControlRoles(); if (accessControlRoles == null || accessControlRoles.isEmpty()) { @@ -934,6 +943,8 @@ private static String mapVisibilityFromDTOtoAPI(APIDTO.VisibilityEnum visibility return APIConstants.API_PRIVATE_VISIBILITY; case RESTRICTED: return APIConstants.API_RESTRICTED_VISIBILITY; + case RESTRICTED_BY_ORG: + return APIConstants.API_RESTRICTED_BY_ORG; // case CONTROLLED: todo add to swagger // return APIConstants.API_CONTROLLED_VISIBILITY; default: @@ -1288,6 +1299,10 @@ public static APIDTO fromAPItoDTO(API model, boolean preserveCredentials, if (model.getVisibleTenants() != null) { dto.setVisibleRoles(Arrays.asList(model.getVisibleTenants().split(","))); } + + if (model.getVisibleOrganizations() != null) { + dto.setVisibleOrganizations(Arrays.asList(model.getVisibleOrganizations().split(","))); + } if (model.getAdditionalProperties() != null) { JSONObject additionalProperties = model.getAdditionalProperties(); @@ -1508,6 +1523,8 @@ private static APIDTO.VisibilityEnum mapVisibilityFromAPItoDTO(String visibility return APIDTO.VisibilityEnum.PRIVATE; case APIConstants.API_RESTRICTED_VISIBILITY: return APIDTO.VisibilityEnum.RESTRICTED; + case APIConstants.API_RESTRICTED_BY_ORG: + return APIDTO.VisibilityEnum.RESTRICTED_BY_ORG; // case APIConstants.API_CONTROLLED_VISIBILITY : todo add this to swagger // return APIDTO.VisibilityEnum.CONTROLLED; default: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index 1fba20fff132..f95ec25f9d97 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -1266,6 +1266,14 @@ public static API prepareToCreateAPIByDTO(APIDTO body, APIProvider apiProvider, throw new APIManagementException(errorMessage, ExceptionCodes.INVALID_USER_ROLES); } } + + if (body.getVisibility() == APIDTO.VisibilityEnum.RESTRICTED_BY_ORG + && body.getVisibleOrganizations().isEmpty()) { + throw new APIManagementException( + "Valid organizations should be added under 'visibleOrganizations' to restrict " + "the visibility", + ExceptionCodes.ORGS_CANNOT_BE_NULL); + } + //Get all existing versions of api been adding List apiVersions = apiProvider.getApiVersionsMatchingApiNameAndOrganization(body.getName(), diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index 36202f048800..cbd88d5ea90f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -9525,6 +9525,7 @@ components: - PUBLIC - PRIVATE - RESTRICTED + - RESTRICTED_BY_ORG x-otherScopes: - apim:api_publish - apim:api_manage @@ -9542,6 +9543,12 @@ components: example: [] items: type: string + visibleOrganizations: + type: array + description: The organizations that are able to access the API in Developer Portal + example: [] + items: + type: string mediationPolicies: type: array example: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index b11627e5b5b5..ce31ba4b4b35 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -41,6 +41,7 @@ import org.wso2.carbon.apimgt.api.model.Documentation; import org.wso2.carbon.apimgt.api.model.DocumentationContent; import org.wso2.carbon.apimgt.api.model.Environment; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.Tier; import org.wso2.carbon.apimgt.api.model.graphql.queryanalysis.GraphqlComplexityInfo; @@ -94,7 +95,10 @@ public Response apisGet(Integer limit, Integer offset, String xWSO2Tenant, Strin query = query == null ? "" : query; APIListDTO apiListDTO = new APIListDTO(); try { - String organization = RestApiUtil.getValidatedOrganization(messageContext); + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + orgInfo.setSuperOrganization(superOrganization); + String username = RestApiCommonUtil.getLoggedInUsername(); APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); @@ -104,14 +108,16 @@ public Response apisGet(Integer limit, Integer offset, String xWSO2Tenant, Strin .replace(APIConstants.CONTENT_SEARCH_TYPE_PREFIX + ":", APIConstants.NAME_TYPE_PREFIX + ":"); } - Map allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, organization, offset, + //Map allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, superOrganization, offset, + // limit, null, null); + Map allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, limit, null, null); Set sortedSet = (Set) allMatchedApisMap.get("apis"); // This is a SortedSet ArrayList allMatchedApis = new ArrayList<>(sortedSet); - apiListDTO = APIMappingUtil.fromAPIListToDTO(allMatchedApis, organization); + apiListDTO = APIMappingUtil.fromAPIListToDTO(allMatchedApis, superOrganization); //Add pagination section in the response Object totalLength = allMatchedApisMap.get("length"); Integer totalAvailableAPis = 0; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index 3b8a8d7ccd07..d1b9f687c101 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -17,11 +17,15 @@ package org.wso2.carbon.apimgt.rest.api.util.impl; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.cxf.message.Message; +import org.json.JSONException; +import org.json.JSONObject; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.APIManagerConfiguration; import org.wso2.carbon.apimgt.impl.RESTAPICacheConfiguration; import org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO; import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder; @@ -36,11 +40,14 @@ import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO; import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.UserRealm; +import org.wso2.carbon.user.core.UserStoreManager; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import org.wso2.carbon.apimgt.api.OAuthTokenInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.rest.api.util.authenticators.AbstractOAuthAuthenticator; import java.util.HashMap; @@ -148,6 +155,7 @@ public boolean authenticate(Message message) throws APIManagementException { carbonContext.setUsername(username); message.put(RestApiConstants.AUTH_TOKEN_INFO, tokenInfo); message.put(RestApiConstants.SUB_ORGANIZATION, tenantDomain); + message.put(RestApiConstants.ORGANIZATION_INFO, getOrganizationInfo(tenantDomain, username)); // TODO cache if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { APIUtil.loadTenantConfigBlockingMode(tenantDomain); } @@ -236,4 +244,60 @@ protected String getConfigurationElementValue(String property) { return ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService().getAPIManagerConfiguration() .getFirstProperty(property); } + + public OrganizationInfo getOrganizationInfo(String tenantDomain, String username) { + OrganizationInfo orgInfo = new OrganizationInfo(); + orgInfo.setSuperOrganization(tenantDomain); + + Boolean isSuperTenant = true; + int tenantId = MultitenantConstants.SUPER_TENANT_ID; + APIManagerConfiguration config = ServiceReferenceHolder.getInstance(). + getAPIManagerConfigurationService().getAPIManagerConfiguration(); + String claim = config.getFirstProperty(APIConstants.API_STORE_GROUP_EXTRACTOR_CLAIM_URI); + if (StringUtils.isBlank(claim)) { + claim = "http://wso2.org/claims/organization"; + } + String organization = null; + String[] groupIdArray = null; + try { + if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { + isSuperTenant = true; + } + + RealmService realmService = ServiceReferenceHolder.getInstance().getRealmService(); + + //if the user is not in the super tenant domain then find the domain name and tenant id. + if (!isSuperTenant) { + tenantDomain = MultitenantUtils.getTenantDomain(username); + tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager() + .getTenantId(tenantDomain); + } + + UserRealm realm = (UserRealm) realmService.getTenantUserRealm(tenantId); + UserStoreManager manager = realm.getUserStoreManager(); + organization = + manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), claim, null); + if (organization != null) { + if (organization.contains(",")) { + groupIdArray = organization.split(","); + for (int i = 0; i < groupIdArray.length; i++) { + groupIdArray[i] = groupIdArray[i].toString().trim(); + } + } else { + organization = organization.trim(); + groupIdArray = new String[] {organization}; + orgInfo.setName(organization); // check for multiple orgs + } + } else { + // If claim is null then returning a empty string + groupIdArray = new String[] {}; + } + } catch (JSONException e) { + log.error("Exception occured while trying to get group Identifier from login response", e); + } catch (org.wso2.carbon.user.api.UserStoreException e) { + log.error("Error while checking user existence for " + username, e); + } + + return orgInfo; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/interceptors/auth/OAuthAuthenticationInterceptor.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/interceptors/auth/OAuthAuthenticationInterceptor.java index df2c63886b41..f25cc2f5691e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/interceptors/auth/OAuthAuthenticationInterceptor.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/interceptors/auth/OAuthAuthenticationInterceptor.java @@ -23,9 +23,14 @@ import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; +import org.json.JSONException; +import org.json.JSONObject; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.OAuthTokenInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.common.RestApiConstants; @@ -37,6 +42,10 @@ import org.wso2.carbon.apimgt.rest.api.util.impl.OAuthOpaqueAuthenticatorImpl; import org.wso2.carbon.apimgt.rest.api.util.utils.JWTAuthenticationUtils; import org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil; +import org.wso2.carbon.user.core.UserRealm; +import org.wso2.carbon.user.core.UserStoreManager; +import org.wso2.carbon.user.core.service.RealmService; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import java.util.HashMap; import java.util.Map; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java index 2ce4659f34f2..7f6140ed4b55 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java @@ -37,6 +37,7 @@ import org.wso2.carbon.apimgt.api.model.DuplicateAPIException; import org.wso2.carbon.apimgt.api.model.OAuthAppRequest; import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.Tier; import org.wso2.carbon.apimgt.impl.AMDefaultKeyManagerImpl; @@ -1236,6 +1237,20 @@ public static String getValidatedOrganization(MessageContext ctx) throws APIMana } return organization; } + + /** + * Method to extract the User organization + * @param ctx MessageContext + * @return organization + */ + + public static OrganizationInfo getOrganizationInfo(MessageContext ctx) throws APIManagementException { + OrganizationInfo organizationInfo = new OrganizationInfo(); + if (ctx.get(RestApiConstants.ORGANIZATION_INFO) != null) { + organizationInfo = (OrganizationInfo) ctx.get(RestApiConstants.ORGANIZATION_INFO); + } + return organizationInfo; + } /** diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt index 4a16128d321f..bab04cb44bea 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt @@ -117,6 +117,9 @@ Visible Tenants + + visibleOrganizations + Is Latest From 6930c4e45514e8ae74bb94c492eb262a366811f8 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Fri, 16 Aug 2024 11:08:17 +0530 Subject: [PATCH 02/74] Add api org visibility to registry property --- .../apimgt/persistence/APIConstants.java | 2 +- .../persistence/RegistryPersistenceImpl.java | 114 ++++++++++++++++-- .../utils/RegistryPersistenceUtil.java | 8 +- .../src/main/resources/rxts/api.rxt | 3 - 4 files changed, 109 insertions(+), 18 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java index c77465e62cff..970e18de5491 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java @@ -52,7 +52,6 @@ public final class APIConstants { public static final String API_OVERVIEW_VISIBILITY = "overview_visibility"; public static final String API_OVERVIEW_VISIBLE_ROLES = "overview_visibleRoles"; public static final String API_OVERVIEW_VISIBLE_TENANTS = "overview_visibleTenants"; - public static final String API_OVERVIEW_VISIBLE_ORGANIZATIONS = "overview_visibleOrganizations"; public static final String API_OVERVIEW_ENVIRONMENTS = "overview_environments"; public static final String API_OVERVIEW_AUDIENCE = "overview_audience"; public static final String API_OVERVIEW_AUDIENCES = "overview_audiences"; @@ -204,6 +203,7 @@ public static class Monetization { public static final String DISPLAY_PUBLISHER_ROLES = "display_publisher_roles"; public static final String ACCESS_CONTROL = "publisher_access_control"; public static final String NO_ACCESS_CONTROL = "all"; + public static final String VISIBLE_ORGANIZATIONS = "visible_organizations"; public static final String NULL_USER_ROLE_LIST = "null"; public static final String API_RESTRICTED_VISIBILITY = "restricted"; public static final String API_PRIVATE_VISIBILITY = "private"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 4767a11f1c80..58effd82ddd7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -172,10 +172,15 @@ public PublisherAPI addAPI(Organization org, PublisherAPI publisherAPI) throws A if (visibleRolesList != null) { visibleRoles = visibleRolesList.split(","); } + + String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; + if (APIConstants.API_RESTRICTED_BY_ORG.equals(api.getVisibility())){ + visibleOrgs = api.getVisibleOrganizations(); + } String publisherAccessControlRoles = api.getAccessControlRoles(); updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, api.getAccessControl(), - api.getAdditionalProperties()); + api.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, artifactPath, registry); @@ -547,8 +552,12 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw String[] visibleRoles = new String[0]; String publisherAccessControlRoles = api.getAccessControlRoles(); + String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; + if (APIConstants.API_RESTRICTED_BY_ORG.equals(api.getVisibility())){ + visibleOrgs = api.getVisibleOrganizations(); + } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, api.getAccessControl(), - api.getAdditionalProperties()); + api.getAdditionalProperties(), visibleOrgs); //propagate api status change and access control roles change to document artifact String newStatus = updateApiArtifact.getAttribute(APIConstants.API_OVERVIEW_STATUS); @@ -1078,8 +1087,8 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String log.debug("Requested query for devportal search: " + searchQuery); String modifiedQuery = RegistrySearchUtil.getDevPortalSearchQuery(searchQuery, ctx, isAllowDisplayAPIsWithMultipleStatus(), isAllowDisplayAPIsWithMultipleVersions()); - modifiedQuery = modifiedQuery + "&visibleOrganizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" - + ctx.getOrganization().getName() + "*)"; + //modifiedQuery = modifiedQuery + "&" + APIConstants.VISIBLE_ORGANIZATIONS + "=(" + // + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" + ctx.getOrganization().getName() + "*)"; log.debug("Modified query for devportal search: " + modifiedQuery); String userNameLocal; if (holder.isAnonymousMode()) { @@ -1093,7 +1102,12 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String result = searchPaginatedDevPortalAPIsByDoc(userRegistry, tenantIDLocal, searchQuery.split(":")[1], userNameLocal, start, offset); } else { + searchSolr( + modifiedQuery + "&" + APIConstants.VISIBLE_ORGANIZATIONS + "=(" + + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" + ctx.getOrganization().getName() + "*)", + tenantIDLocal, userRegistry, start, offset); result = searchPaginatedDevPortalAPIs(userRegistry, tenantIDLocal, modifiedQuery, start, offset); + } } catch (APIManagementException e) { throw new APIPersistenceException("Error while searching APIs ", e); @@ -1104,6 +1118,83 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String } return result; } + + private void searchSolr(String query, int tenantId, Registry reg, int start, int offset) { + Map attributes = processQuery(query); + + try { + PaginationContext.init(start, offset, "ASC", APIConstants.API_OVERVIEW_NAME, getMaxPaginationLimit()); + UserRegistry systemUserRegistry = ServiceReferenceHolder.getInstance().getRegistryService() + .getRegistry(CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId); + ContentBasedSearchService contentBasedSearchService = new ContentBasedSearchService(); + SearchResultsBean resultsBean = contentBasedSearchService.searchByAttribute(attributes, systemUserRegistry); + log.debug(resultsBean); + } catch (IndexerException | RegistryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public Map processQuery(String query) { + // Map to hold the final output + Map outputMap = new HashMap<>(); + + // Split the query by '&' + String[] parameters = query.split("&"); + + // Process each parameter + for (String parameter : parameters) { + // Split each parameter by '=' to get key and value + String[] keyValue = parameter.split("="); + + // Extract the key and value + String key = keyValue[0]; + String value = keyValue.length > 1 ? keyValue[1] : ""; + + // Map keys to the corresponding output format + switch (key) { + case "store_view_roles": + outputMap.put("propertyName", key); + outputMap.put("rightPropertyValue", value); + break; + case "visible_organizations": + outputMap.put("propertyName", key); + outputMap.put("rightPropertyValue", value); + break; +// case "name": +// outputMap.put("overview_name", value); +// break; +// case "enableStore": +// outputMap.put("overview_enableStore", value); +// break; + case "group": + outputMap.put("group", value); + break; + case "group.field": + outputMap.put("group.field", "overview_" + value); + break; + case "group.ngroups": + outputMap.put("group.ngroups", value); + break; + case "group.sort": + outputMap.put("group.sort", "overview_" + value); + break; +// case "status": +// outputMap.put("overview_status", value.toLowerCase()); +// break; + default: + // Add any other cases if needed + outputMap.put("overview_" + key, value); + break; + } + } + + // Add additional mappings if needed + outputMap.put("mediaType", "application/vnd.wso2-api+xml"); + outputMap.put("rightOp", "eq"); + + return outputMap; + } private DevPortalAPISearchResult searchPaginatedDevPortalAPIs(Registry userRegistry, int tenantIDLocal, String searchQuery, int start, int offset) throws APIManagementException { @@ -2981,7 +3072,7 @@ private void saveAPIStatus(Registry registry, String artifactId, String apiStatu * @throws RegistryException Registry Exception. */ private void updateRegistryResources(Registry registry, String artifactPath, String publisherAccessControlRoles, - String publisherAccessControl, Map additionalProperties) + String publisherAccessControl, Map additionalProperties, String visibleOrganizations) throws RegistryException { publisherAccessControlRoles = (publisherAccessControlRoles == null || publisherAccessControlRoles.trim() .isEmpty()) ? APIConstants.NULL_USER_ROLE_LIST : publisherAccessControlRoles; @@ -3014,6 +3105,7 @@ private void updateRegistryResources(Registry registry, String artifactPath, Str // the roles that were specified can be maintained. apiResource.setProperty(APIConstants.DISPLAY_PUBLISHER_ROLES, publisherAccessControlRoles); apiResource.setProperty(APIConstants.ACCESS_CONTROL, publisherAccessControl); + apiResource.setProperty(APIConstants.VISIBLE_ORGANIZATIONS, visibleOrganizations); apiResource.removeProperty(APIConstants.CUSTOM_API_INDEXER_PROPERTY); if (additionalProperties != null && additionalProperties.size() != 0) { for (Map.Entry entry : additionalProperties.entrySet()) { @@ -3269,8 +3361,12 @@ public PublisherAPIProduct addAPIProduct(Organization org, PublisherAPIProduct p } String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); + String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; + if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ + //visibleOrgs = apiProduct.getVisibleOrganizations(); TODO fix for products + } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), - apiProduct.getAdditionalProperties()); + apiProduct.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(apiProduct.getId().getProviderName(), apiProduct.getVisibility(), visibleRoles, artifactPath, registry); @@ -3495,8 +3591,12 @@ public PublisherAPIProduct updateAPIProduct(Organization org, PublisherAPIProduc applyTags(apiProduct.getTags(), registry, artifactPath); String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); + String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; + if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ + //visibleOrgs = apiProduct.getVisibleOrganizations(); TODO fix for products + } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), - apiProduct.getAdditionalProperties()); + apiProduct.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(apiProduct.getId().getProviderName(), apiProduct.getVisibility(), visibleRoles, artifactPath, registry); registry.commitTransaction(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index d22b16155b1b..755bc551a618 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -178,12 +178,6 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_ENABLE_STORE, Boolean.toString(api.isEnableStore())); artifact.setAttribute(APIConstants.API_OVERVIEW_TESTKEY, api.getTestKey()); artifact.setAttribute(APIConstants.API_OVERVIEW_VERSION_COMPARABLE, api.getVersionTimestamp()); - if (APIConstants.API_RESTRICTED_BY_ORG.equals(api.getVisibility())) { - artifact.setAttribute(APIConstants.API_OVERVIEW_VISIBLE_ORGANIZATIONS, api.getVisibleOrganizations()); - } else { - // Set a default value if org visibility is not set. This is done to generate search query for public apis - artifact.setAttribute(APIConstants.API_OVERVIEW_VISIBLE_ORGANIZATIONS, APIConstants.DEFAULT_VISIBLE_ORG); - } //Validate if the API has an unsupported context before setting it in the artifact String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); @@ -607,7 +601,6 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry) api.setVisibility(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBILITY)); api.setVisibleRoles(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBLE_ROLES)); api.setVisibleTenants(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBLE_TENANTS)); - api.setVisibleOrganizations(artifact.getAttribute(APIConstants.API_OVERVIEW_VISIBLE_ORGANIZATIONS)); api.setEndpointSecured(Boolean.parseBoolean(artifact.getAttribute( APIConstants.API_OVERVIEW_ENDPOINT_SECURED))); api.setEndpointAuthDigest(Boolean.parseBoolean(artifact.getAttribute( @@ -806,6 +799,7 @@ private static API setResourceProperties(API api, Resource apiResource, String a } } api.setAccessControl(apiResource.getProperty(APIConstants.ACCESS_CONTROL)); + api.setVisibleOrganizations(apiResource.getProperty(APIConstants.VISIBLE_ORGANIZATIONS)); String accessControlRoles = null; diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt index bab04cb44bea..4a16128d321f 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/rxts/api.rxt @@ -117,9 +117,6 @@ Visible Tenants - - visibleOrganizations - Is Latest From 197b95c3d6ed75a95b1f800669b2c53233549446 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Sat, 17 Aug 2024 08:52:30 +0530 Subject: [PATCH 03/74] Add application sharing with the organization --- .../wso2/carbon/apimgt/api/APIConsumer.java | 3 +- .../carbon/apimgt/api/model/Application.java | 10 + .../apimgt/org.wso2.carbon.apimgt.impl/code | 648 ++++++++++++++++++ .../wso2/carbon/apimgt/impl/APIConstants.java | 1 + .../carbon/apimgt/impl/APIConsumerImpl.java | 11 +- .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 46 +- .../impl/dao/constants/SQLConstants.java | 7 +- .../dao/constants/SQLConstantsH2MySQL.java | 68 +- .../rest/api/store/v1/dto/ApplicationDTO.java | 55 +- .../v1/impl/ApplicationsApiServiceImpl.java | 34 +- .../src/main/resources/devportal-api.yaml | 5 + .../src/main/resources/sql/h2.sql | 1 + .../src/main/resources/sql/mysql.sql | 1 + 13 files changed, 861 insertions(+), 29 deletions(-) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.impl/code diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java index f3edb073ec61..06d9a3e4ac2c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java @@ -462,12 +462,13 @@ OAuthApplicationInfo updateAuthClient(String userId, Application application, * @param offset * @param groupingId the groupId to which the applications must belong. * @param organization Identifier of an organization + * @param sharedOrganization * @return Applications * @throws APIManagementException if failed to applications for given subscriber */ Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, int offset, - String search, String sortColumn, String sortOrder, String organization) + String search, String sortColumn, String sortOrder, String organization, String sharedOrganization) throws APIManagementException; /** diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java index 556746ea27c9..e40003eeb9fe 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java @@ -58,6 +58,8 @@ public Map> getKeyManagerWiseOAuthApp( private String keyType; private int subscriptionCount; private String keyManager; + private String sharedOrganization; + public String getCreatedTime() { return createdTime; } @@ -320,4 +322,12 @@ public void setOrganization(String organization) { this.organization = organization; } + + public String getSharedOrganization() { + return sharedOrganization; + } + + public void setSharedOrganization(String sharedOrganization) { + this.sharedOrganization = sharedOrganization; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/code b/components/apimgt/org.wso2.carbon.apimgt.impl/code new file mode 100644 index 000000000000..07d29e164d3f --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/code @@ -0,0 +1,648 @@ +diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java +index f3edb073ec6..06d9a3e4ac2 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java +@@ -462,12 +462,13 @@ public interface APIConsumer extends APIManager { + * @param offset + * @param groupingId the groupId to which the applications must belong. + * @param organization Identifier of an organization ++ * @param sharedOrganization + * @return Applications + * @throws APIManagementException if failed to applications for given subscriber + */ + + Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, int offset, +- String search, String sortColumn, String sortOrder, String organization) ++ String search, String sortColumn, String sortOrder, String organization, String sharedOrganization) + throws APIManagementException; + + /** +diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java +index 556746ea27c..e40003eeb9f 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java +@@ -58,6 +58,8 @@ public class Application { + private String keyType; + private int subscriptionCount; + private String keyManager; ++ private String sharedOrganization; ++ + public String getCreatedTime() { + return createdTime; + } +@@ -320,4 +322,12 @@ public class Application { + + this.organization = organization; + } ++ ++ public String getSharedOrganization() { ++ return sharedOrganization; ++ } ++ ++ public void setSharedOrganization(String sharedOrganization) { ++ this.sharedOrganization = sharedOrganization; ++ } + } +diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +index ef5461ccbb3..31724f5aef0 100755 +--- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +@@ -823,6 +823,7 @@ public final class APIConstants { + "internal_application_mgt_delete", "internal_application_mgt_update", "internal_application_mgt_view", + "internal_user_mgt_list"}; + public static final String KEY_MANAGER_CLIENT_APPLICATION_PREFIX = "wso2_apim_km_"; ++ public static final String DEFAULT_APP_SHARING_KEYWORD = "private"; + + public static final String TOKEN_URL = "TokenURL"; + public static final String REVOKE_URL = "RevokeURL"; +diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +index ae44701e65d..bf3ab8f624d 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +@@ -1664,6 +1664,9 @@ public class APIConsumerImpl extends AbstractAPIManager implements APIConsumer { + if (StringUtils.isBlank(application.getCallbackUrl())) { + application.setCallbackUrl(null); + } ++ if (StringUtils.isEmpty(application.getSharedOrganization())) { ++ application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); ++ } + int applicationId = apiMgtDAO.addApplication(application, userId, organization); + Application createdApplication = apiMgtDAO.getApplicationById(applicationId); + +@@ -1894,6 +1897,9 @@ public class APIConsumerImpl extends AbstractAPIManager implements APIConsumer { + application.setApplicationAttributes(null); + } + validateApplicationPolicy(application, existingApp.getOrganization()); ++ if (StringUtils.isEmpty(application.getSharedOrganization())) { ++ application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); ++ } + apiMgtDAO.updateApplication(application); + Application updatedApplication = apiMgtDAO.getApplicationById(application.getId()); + if (log.isDebugEnabled()) { +@@ -2786,19 +2792,20 @@ APIConstants.AuditLogConstants.DELETED, this.username); + * @param sortColumn The sort column. + * @param sortOrder The sort order. + * @param organization Identifier of an Organization ++ * @param sharedOrganization + * @return Application[] The Applications. + * @throws APIManagementException + */ + @Override + public Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, int offset +- , String search, String sortColumn, String sortOrder, String organization) ++ , String search, String sortColumn, String sortOrder, String organization, String sharedOrganization) + throws APIManagementException { + + if (APIUtil.isOnPremResolver()) { + organization = tenantDomain; + } + return apiMgtDAO.getApplicationsWithPagination(subscriber, groupingId, start, offset, +- search, sortColumn, sortOrder, organization); ++ search, sortColumn, sortOrder, organization, sharedOrganization); + } + + /** +diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +index 06decdd0970..40a4771b5b4 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +@@ -3497,6 +3497,7 @@ public class ApiMgtDAO { + ps.setString(11, application.getUUID()); + ps.setString(12, String.valueOf(application.getTokenType())); + ps.setString(13, organization); ++ ps.setString(14, application.getSharedOrganization()); + ps.executeUpdate(); + + rs = ps.getGeneratedKeys(); +@@ -3537,7 +3538,8 @@ public class ApiMgtDAO { + ps.setString(5, null); + ps.setTimestamp(6, new Timestamp(System.currentTimeMillis())); + ps.setString(7, application.getTokenType()); +- ps.setInt(8, application.getId()); ++ ps.setString(8, application.getSharedOrganization()); ++ ps.setInt(9, application.getId()); + + ps.executeUpdate(); + +@@ -4118,7 +4120,8 @@ public class ApiMgtDAO { + * @throws APIManagementException + */ + public Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, +- int offset, String search, String sortColumn, String sortOrder, String organization) ++ int offset, String search, String sortColumn, String sortOrder, String organization, ++ String sharedOrganization) + throws APIManagementException { + + Connection connection = null; +@@ -4126,7 +4129,7 @@ public class ApiMgtDAO { + ResultSet rs = null; + Application[] applications = null; + String sqlQuery = null; +- ++ boolean isOrgSharingEnabled = true; //TODO need to come from config or from user info + if (groupingId != null && !"null".equals(groupingId) && !groupingId.isEmpty()) { + if (multiGroupAppSharingEnabled) { + if (forceCaseInsensitiveComparisons) { +@@ -4147,9 +4150,19 @@ public class ApiMgtDAO { + } + } else { + if (forceCaseInsensitiveComparisons) { +- sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE"); ++ if (isOrgSharingEnabled) { ++ sqlQuery = SQLConstantManagerFactory ++ .getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE_WITH_ORGSHARING"); ++ } else { ++ sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE"); ++ } + } else { +- sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE"); ++ if (isOrgSharingEnabled) { ++ sqlQuery = SQLConstantManagerFactory ++ .getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE_WITH_ORGSHARING"); ++ } else { ++ sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE"); ++ } + } + } + +@@ -4196,12 +4209,22 @@ public class ApiMgtDAO { + prepStmt.setInt(6, offset); + } + } else { +- prepStmt = connection.prepareStatement(sqlQuery); +- prepStmt.setString(1, subscriber.getName()); +- prepStmt.setString(2, organization); +- prepStmt.setString(3, "%" + search + "%"); +- prepStmt.setInt(4, start); +- prepStmt.setInt(5, offset); ++ if (isOrgSharingEnabled) { ++ prepStmt = connection.prepareStatement(sqlQuery); ++ prepStmt.setString(1, subscriber.getName()); ++ prepStmt.setString(2, sharedOrganization); ++ prepStmt.setString(3, organization); ++ prepStmt.setString(4, "%" + search + "%"); ++ prepStmt.setInt(5, start); ++ prepStmt.setInt(6, offset); ++ } else { ++ prepStmt = connection.prepareStatement(sqlQuery); ++ prepStmt.setString(1, subscriber.getName()); ++ prepStmt.setString(2, organization); ++ prepStmt.setString(3, "%" + search + "%"); ++ prepStmt.setInt(4, start); ++ prepStmt.setInt(5, offset); ++ } + } + if (log.isDebugEnabled()) { + log.debug("Query: " + sqlQuery); +@@ -4238,6 +4261,7 @@ public class ApiMgtDAO { + // Get custom attributes of application + Map applicationAttributes = getApplicationAttributes(connection, applicationId); + application.setApplicationAttributes(applicationAttributes); ++ application.setSharedOrganization(rs.getString("SHARED_ORGANIZATION")); + + applicationsList.add(application); + } +diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +index e52d62eaa65..0f4fcc9d6ee 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +@@ -1009,8 +1009,8 @@ public class SQLConstants { + public static final String APP_APPLICATION_SQL = + " INSERT INTO AM_APPLICATION (NAME, SUBSCRIBER_ID, APPLICATION_TIER, " + + " CALLBACK_URL, DESCRIPTION, APPLICATION_STATUS, GROUP_ID, CREATED_BY, CREATED_TIME, UPDATED_TIME, " + +- "UUID, TOKEN_TYPE, ORGANIZATION)" + +- " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"; ++ "UUID, TOKEN_TYPE, ORGANIZATION, SHARED_ORGANIZATION)" + ++ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + public static final String UPDATE_APPLICATION_SQL = + " UPDATE " + +@@ -1022,7 +1022,8 @@ public class SQLConstants { + " DESCRIPTION = ?, " + + " UPDATED_BY = ?, " + + " UPDATED_TIME = ?, " + +- " TOKEN_TYPE = ? " + ++ " TOKEN_TYPE = ?, " + ++ " SHARED_ORGANIZATION = ? " + + " WHERE" + + " APPLICATION_ID = ?"; + +diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java +index 03aead5993a..5c09b58ec01 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java +@@ -181,7 +181,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ + " GROUP_ID, " + + " UUID, " + + " APP.CREATED_BY AS CREATED_BY, " + +- " APP.TOKEN_TYPE AS TOKEN_TYPE " + ++ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + ++ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + + " FROM" + + " AM_APPLICATION APP, " + + " AM_SUBSCRIBER SUB " + +@@ -212,7 +213,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ + " GROUP_ID, " + + " UUID, " + + " APP.CREATED_BY AS CREATED_BY, " + +- " APP.TOKEN_TYPE AS TOKEN_TYPE " + ++ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + ++ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + + " FROM" + + " AM_APPLICATION APP, " + + " AM_SUBSCRIBER SUB " + +@@ -227,6 +229,68 @@ public class SQLConstantsH2MySQL extends SQLConstants{ + " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + + " ORDER BY $1 $2 limit ? , ?"; + ++ public static final String GET_APPLICATIONS_PREFIX_CASESENSITVE_WITH_ORGSHARING = ++ "select distinct x.*,bl.ENABLED from (" + ++ "SELECT " + ++ " APPLICATION_ID, " + ++ " NAME," + ++ " APPLICATION_TIER," + ++ " APP.SUBSCRIBER_ID, " + ++ " APP.CREATED_TIME AS APP_CREATED_TIME, " + ++ " APP.UPDATED_TIME AS APP_UPDATED_TIME, " + ++ " CALLBACK_URL, " + ++ " DESCRIPTION, " + ++ " APPLICATION_STATUS, " + ++ " USER_ID, " + ++ " GROUP_ID, " + ++ " UUID, " + ++ " APP.CREATED_BY AS CREATED_BY, " + ++ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + ++ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + ++ " FROM" + ++ " AM_APPLICATION APP, " + ++ " AM_SUBSCRIBER SUB " + ++ " WHERE " + ++ " SUB.SUBSCRIBER_ID = APP.SUBSCRIBER_ID " + ++ " AND (LOWER(SUB.USER_ID) = LOWER(?) OR APP.SHARED_ORGANIZATION = ? )" + ++ " AND " + ++ " APP.ORGANIZATION = ? " + ++ " And "+ ++ " LOWER (NAME) like LOWER (?)"+ ++ " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + ++ " ORDER BY $1 $2 limit ? , ?"; ++ ++ public static final String GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE_WITH_ORGSHARING = ++ "select distinct x.*,bl.ENABLED from (" + ++ "SELECT " + ++ " APPLICATION_ID, " + ++ " NAME," + ++ " APPLICATION_TIER," + ++ " APP.SUBSCRIBER_ID, " + ++ " APP.CREATED_TIME AS APP_CREATED_TIME, " + ++ " APP.UPDATED_TIME AS APP_UPDATED_TIME, " + ++ " CALLBACK_URL, " + ++ " DESCRIPTION, " + ++ " APPLICATION_STATUS, " + ++ " USER_ID, " + ++ " GROUP_ID, " + ++ " UUID, " + ++ " APP.CREATED_BY AS CREATED_BY, " + ++ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + ++ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + ++ " FROM" + ++ " AM_APPLICATION APP, " + ++ " AM_SUBSCRIBER SUB " + ++ " WHERE " + ++ " SUB.SUBSCRIBER_ID = APP.SUBSCRIBER_ID " + ++ " AND (LOWER(SUB.USER_ID) = LOWER(?) OR APP.SHARED_ORGANIZATION = ? )" + ++ " AND " + ++ " APP.ORGANIZATION = ? " + ++ " And "+ ++ " LOWER (NAME) like LOWER (?)"+ ++ " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + ++ " ORDER BY $1 $2 limit ? , ?"; ++ + + public static final String GET_APPLICATIONS_BY_TENANT_ID = + " SELECT " + +diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +index ca7602542f8..cbd88d5ea90 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml ++++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +@@ -8167,7 +8167,7 @@ paths: + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" +- -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 ++ -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 + "https://127.0.0.1:9443/api/am/publisher/v4/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/operation-policies"' + + +@@ -8411,7 +8411,7 @@ paths: + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" +- -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 ++ -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 + "https://127.0.0.1:9443/api/am/publisher/v4/operation-policies"' + + /operation-policies/export: +@@ -9226,6 +9226,12 @@ components: + enum: + - PUBLIC + - SINGLE ++ audiences: ++ type: array ++ description: The audiences of the API for jwt validation. Accepted values are any String values ++ items: ++ type: string ++ example: [ "aud1","aud2","aud3" ] + lifeCycleStatus: + type: string + example: CREATED +@@ -9443,6 +9449,12 @@ components: + enum: + - PUBLIC + - SINGLE ++ audiences: ++ type: array ++ description: The audiences of the API for jwt validation. Accepted values are any String values ++ items: ++ type: string ++ example: [ "aud1","aud2","aud3" ] + transport: + type: array + description: | +@@ -10042,6 +10054,12 @@ components: + gatewayVendor: + type: string + example: wso2 ++ audiences: ++ type: array ++ description: The audiences of the API product for jwt validation. Accepted values are any String values ++ items: ++ type: string ++ example: [ "aud1","aud2","aud3" ] + monetizedInfo: + type: boolean + example: true +@@ -10315,6 +10333,12 @@ components: + workflowStatus: + type: string + example: APPROVED ++ audiences: ++ type: array ++ description: The audiences of the API for jwt validation. Accepted values are any String values ++ items: ++ type: string ++ example: [ "aud1","aud2","aud3" ] + ProductAPI: + title: ProductAPI + required: +diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java +index 225f12efa07..ec38b804982 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java +@@ -73,6 +73,38 @@ return null; + private String createdTime = null; + private String updatedTime = null; + ++ @XmlType(name="VisibilityEnum") ++ @XmlEnum(String.class) ++ public enum VisibilityEnum { ++ PRIVATE("PRIVATE"), ++ SHARED_WITH_ORG("SHARED_WITH_ORG"); ++ private String value; ++ ++ VisibilityEnum (String v) { ++ value = v; ++ } ++ ++ public String value() { ++ return value; ++ } ++ ++ @Override ++ public String toString() { ++ return String.valueOf(value); ++ } ++ ++ @JsonCreator ++ public static VisibilityEnum fromValue(String v) { ++ for (VisibilityEnum b : VisibilityEnum.values()) { ++ if (String.valueOf(b.value).equals(v)) { ++ return b; ++ } ++ } ++return null; ++ } ++ } ++ private VisibilityEnum visibility = null; ++ + /** + **/ + public ApplicationDTO applicationId(String applicationId) { +@@ -334,6 +366,23 @@ return null; + this.updatedTime = updatedTime; + } + ++ /** ++ **/ ++ public ApplicationDTO visibility(VisibilityEnum visibility) { ++ this.visibility = visibility; ++ return this; ++ } ++ ++ ++ @ApiModelProperty(value = "") ++ @JsonProperty("visibility") ++ public VisibilityEnum getVisibility() { ++ return visibility; ++ } ++ public void setVisibility(VisibilityEnum visibility) { ++ this.visibility = visibility; ++ } ++ + + @Override + public boolean equals(java.lang.Object o) { +@@ -358,12 +407,13 @@ return null; + Objects.equals(owner, application.owner) && + Objects.equals(hashEnabled, application.hashEnabled) && + Objects.equals(createdTime, application.createdTime) && +- Objects.equals(updatedTime, application.updatedTime); ++ Objects.equals(updatedTime, application.updatedTime) && ++ Objects.equals(visibility, application.visibility); + } + + @Override + public int hashCode() { +- return Objects.hash(applicationId, name, throttlingPolicy, description, tokenType, status, groups, subscriptionCount, keys, attributes, subscriptionScopes, owner, hashEnabled, createdTime, updatedTime); ++ return Objects.hash(applicationId, name, throttlingPolicy, description, tokenType, status, groups, subscriptionCount, keys, attributes, subscriptionScopes, owner, hashEnabled, createdTime, updatedTime, visibility); + } + + @Override +@@ -386,6 +436,7 @@ return null; + sb.append(" hashEnabled: ").append(toIndentedString(hashEnabled)).append("\n"); + sb.append(" createdTime: ").append(toIndentedString(createdTime)).append("\n"); + sb.append(" updatedTime: ").append(toIndentedString(updatedTime)).append("\n"); ++ sb.append(" visibility: ").append(toIndentedString(visibility)).append("\n"); + sb.append("}"); + return sb.toString(); + } +diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +index 616753f2b2d..619f74850c8 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java ++++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +@@ -44,6 +44,7 @@ import org.wso2.carbon.apimgt.api.model.AccessTokenInfo; + import org.wso2.carbon.apimgt.api.model.Application; + import org.wso2.carbon.apimgt.api.model.ApplicationConstants; + import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; ++import org.wso2.carbon.apimgt.api.model.OrganizationInfo; + import org.wso2.carbon.apimgt.api.model.Scope; + import org.wso2.carbon.apimgt.api.model.Subscriber; + import org.wso2.carbon.apimgt.impl.APIConstants; +@@ -62,6 +63,7 @@ import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyDTO; + import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyGenerateRequestDTO; + import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyRevokeRequestDTO; + import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO; ++import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO.VisibilityEnum; + import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationInfoDTO; + import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationKeyDTO; + import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationKeyGenerateRequestDTO; +@@ -137,12 +139,14 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + groupId = RestApiUtil.getLoggedInUserGroupId(); + try { + String organization = RestApiUtil.getValidatedOrganization(messageContext); ++ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); + Subscriber subscriber = new Subscriber(username); + Application[] applications; ++ String sharedOrganization = orgInfo.getName(); + applications = apiConsumer + .getApplicationsWithPagination(new Subscriber(username), groupId, offset, limit, query, sortBy, +- sortOrder, organization); ++ sortOrder, organization, sharedOrganization); + if (applications != null) { + JSONArray applicationAttributesFromConfig = apiConsumer.getAppAttributesFromConfig(username); + for (Application application : applications) { +@@ -243,15 +247,16 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + } + + String organization = RestApiUtil.getValidatedOrganization(messageContext); ++ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + + if (APIUtil.isApplicationExist(ownerId, applicationDTO.getName(), applicationGroupId, organization) && update != null + && update) { + int appId = APIUtil.getApplicationId(applicationDTO.getName(), ownerId); + Application oldApplication = apiConsumer.getApplicationById(appId); + application = preProcessAndUpdateApplication(ownerId, applicationDTO, oldApplication, +- oldApplication.getUUID()); ++ oldApplication.getUUID(), orgInfo.getName()); + } else { +- application = preProcessAndAddApplication(ownerId, applicationDTO, organization); ++ application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getName()); + update = Boolean.FALSE; + } + +@@ -323,7 +328,8 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + body.setTokenType(ApplicationDTO.TokenTypeEnum.JWT); + + String organization = RestApiUtil.getValidatedOrganization(messageContext); +- Application createdApplication = preProcessAndAddApplication(username, body, organization); ++ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); ++ Application createdApplication = preProcessAndAddApplication(username, body, organization, orgInfo.getName()); + ApplicationDTO createdApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(createdApplication); + + //to be set as the Location header +@@ -356,8 +362,8 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + * @param organization Identifier of an organization + * @return Created application + */ +- private Application preProcessAndAddApplication(String username, ApplicationDTO applicationDto, String organization) +- throws APIManagementException { ++ private Application preProcessAndAddApplication(String username, ApplicationDTO applicationDto, String organization, ++ String sharedOrganization) throws APIManagementException { + APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); + + //validate the tier specified for the application +@@ -375,6 +381,12 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + + //subscriber field of the body is not honored. It is taken from the context + Application application = ApplicationMappingUtil.fromDTOtoApplication(applicationDto, username); ++ ++ application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); // default ++ if ((applicationDto.getVisibility() != null) ++ && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { ++ application.setSharedOrganization(sharedOrganization); ++ } + + int applicationId = apiConsumer.addApplication(application, username, organization); + +@@ -468,8 +480,9 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + "A duplicate application already exists by the name - " + body.getName()); + } + } ++ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + Application updatedApplication = preProcessAndUpdateApplication(username, body, oldApplication, +- applicationId); ++ applicationId, orgInfo.getName()); + ApplicationDTO updatedApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(updatedApplication); + return Response.ok().entity(updatedApplicationDTO).build(); + +@@ -531,7 +544,7 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + * @return Updated application + */ + private Application preProcessAndUpdateApplication(String username, ApplicationDTO applicationDto, +- Application oldApplication, String applicationId) throws APIManagementException { ++ Application oldApplication, String applicationId, String sharedOrganization) throws APIManagementException { + APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); + Object applicationAttributesFromUser = applicationDto.getAttributes(); + Map applicationAttributes = new ObjectMapper() +@@ -547,6 +560,11 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { + //we do not honor the application id which is sent via the request body + application.setUUID(oldApplication != null ? oldApplication.getUUID() : null); + ++ application.setSharedOrganization(oldApplication.getSharedOrganization()); // default ++ if ((applicationDto.getVisibility() != null) ++ && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { ++ application.setSharedOrganization(sharedOrganization); ++ } + apiConsumer.updateApplication(application); + + //retrieves the updated application and send as the response +diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml +index b99d43642ed..296ce294b71 100644 +--- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml ++++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml +@@ -4363,6 +4363,11 @@ components: + type: string + readOnly: true + example: 1651555310208 ++ visibility: ++ type: string ++ enum: ++ - PRIVATE ++ - SHARED_WITH_ORG + ApplicationInfo: + title: Application info object with basic application details + type: object +diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +index 16a72011705..4687988fc52 100644 +--- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql ++++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +@@ -1542,6 +1542,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( + UUID VARCHAR(256), + TOKEN_TYPE VARCHAR(10), + ORGANIZATION VARCHAR(100), ++ SHARED_ORGANIZATION VARCHAR(100), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, + PRIMARY KEY(APPLICATION_ID), + UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), +diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql +index a4bace7ddf7..71cbc6bd626 100644 +--- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql ++++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql +@@ -1490,6 +1490,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( + UUID VARCHAR(256), + TOKEN_TYPE VARCHAR(10), + ORGANIZATION VARCHAR(100), ++ SHARED_ORGANIZATION VARCHAR(100), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, + PRIMARY KEY(APPLICATION_ID), + UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index ef5461ccbb3e..31724f5aef0a 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -823,6 +823,7 @@ private Permissions() { "internal_application_mgt_delete", "internal_application_mgt_update", "internal_application_mgt_view", "internal_user_mgt_list"}; public static final String KEY_MANAGER_CLIENT_APPLICATION_PREFIX = "wso2_apim_km_"; + public static final String DEFAULT_APP_SHARING_KEYWORD = "private"; public static final String TOKEN_URL = "TokenURL"; public static final String REVOKE_URL = "RevokeURL"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index ae44701e65d6..bf3ab8f624de 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -1664,6 +1664,9 @@ public int addApplication(Application application, String userId, String organiz if (StringUtils.isBlank(application.getCallbackUrl())) { application.setCallbackUrl(null); } + if (StringUtils.isEmpty(application.getSharedOrganization())) { + application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); + } int applicationId = apiMgtDAO.addApplication(application, userId, organization); Application createdApplication = apiMgtDAO.getApplicationById(applicationId); @@ -1894,6 +1897,9 @@ public void updateApplication(Application application) throws APIManagementExcep application.setApplicationAttributes(null); } validateApplicationPolicy(application, existingApp.getOrganization()); + if (StringUtils.isEmpty(application.getSharedOrganization())) { + application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); + } apiMgtDAO.updateApplication(application); Application updatedApplication = apiMgtDAO.getApplicationById(application.getId()); if (log.isDebugEnabled()) { @@ -2786,19 +2792,20 @@ public String[] getGroupIds(String response) throws APIManagementException { * @param sortColumn The sort column. * @param sortOrder The sort order. * @param organization Identifier of an Organization + * @param sharedOrganization * @return Application[] The Applications. * @throws APIManagementException */ @Override public Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, int offset - , String search, String sortColumn, String sortOrder, String organization) + , String search, String sortColumn, String sortOrder, String organization, String sharedOrganization) throws APIManagementException { if (APIUtil.isOnPremResolver()) { organization = tenantDomain; } return apiMgtDAO.getApplicationsWithPagination(subscriber, groupingId, start, offset, - search, sortColumn, sortOrder, organization); + search, sortColumn, sortOrder, organization, sharedOrganization); } /** diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 06decdd09709..40a4771b5b47 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -3497,6 +3497,7 @@ public int addApplication(Application application, String userId, Connection con ps.setString(11, application.getUUID()); ps.setString(12, String.valueOf(application.getTokenType())); ps.setString(13, organization); + ps.setString(14, application.getSharedOrganization()); ps.executeUpdate(); rs = ps.getGeneratedKeys(); @@ -3537,7 +3538,8 @@ public void updateApplication(Application application) throws APIManagementExcep ps.setString(5, null); ps.setTimestamp(6, new Timestamp(System.currentTimeMillis())); ps.setString(7, application.getTokenType()); - ps.setInt(8, application.getId()); + ps.setString(8, application.getSharedOrganization()); + ps.setInt(9, application.getId()); ps.executeUpdate(); @@ -4118,7 +4120,8 @@ public boolean updateApplicationOwner(String userName, Application application) * @throws APIManagementException */ public Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, - int offset, String search, String sortColumn, String sortOrder, String organization) + int offset, String search, String sortColumn, String sortOrder, String organization, + String sharedOrganization) throws APIManagementException { Connection connection = null; @@ -4126,7 +4129,7 @@ public Application[] getApplicationsWithPagination(Subscriber subscriber, String ResultSet rs = null; Application[] applications = null; String sqlQuery = null; - + boolean isOrgSharingEnabled = true; //TODO need to come from config or from user info if (groupingId != null && !"null".equals(groupingId) && !groupingId.isEmpty()) { if (multiGroupAppSharingEnabled) { if (forceCaseInsensitiveComparisons) { @@ -4147,9 +4150,19 @@ public Application[] getApplicationsWithPagination(Subscriber subscriber, String } } else { if (forceCaseInsensitiveComparisons) { - sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE"); + if (isOrgSharingEnabled) { + sqlQuery = SQLConstantManagerFactory + .getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE_WITH_ORGSHARING"); + } else { + sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE"); + } } else { - sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE"); + if (isOrgSharingEnabled) { + sqlQuery = SQLConstantManagerFactory + .getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE_WITH_ORGSHARING"); + } else { + sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE"); + } } } @@ -4196,12 +4209,22 @@ public Application[] getApplicationsWithPagination(Subscriber subscriber, String prepStmt.setInt(6, offset); } } else { - prepStmt = connection.prepareStatement(sqlQuery); - prepStmt.setString(1, subscriber.getName()); - prepStmt.setString(2, organization); - prepStmt.setString(3, "%" + search + "%"); - prepStmt.setInt(4, start); - prepStmt.setInt(5, offset); + if (isOrgSharingEnabled) { + prepStmt = connection.prepareStatement(sqlQuery); + prepStmt.setString(1, subscriber.getName()); + prepStmt.setString(2, sharedOrganization); + prepStmt.setString(3, organization); + prepStmt.setString(4, "%" + search + "%"); + prepStmt.setInt(5, start); + prepStmt.setInt(6, offset); + } else { + prepStmt = connection.prepareStatement(sqlQuery); + prepStmt.setString(1, subscriber.getName()); + prepStmt.setString(2, organization); + prepStmt.setString(3, "%" + search + "%"); + prepStmt.setInt(4, start); + prepStmt.setInt(5, offset); + } } if (log.isDebugEnabled()) { log.debug("Query: " + sqlQuery); @@ -4238,6 +4261,7 @@ public Application[] getApplicationsWithPagination(Subscriber subscriber, String // Get custom attributes of application Map applicationAttributes = getApplicationAttributes(connection, applicationId); application.setApplicationAttributes(applicationAttributes); + application.setSharedOrganization(rs.getString("SHARED_ORGANIZATION")); applicationsList.add(application); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index e52d62eaa65a..0f4fcc9d6eef 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -1009,8 +1009,8 @@ public class SQLConstants { public static final String APP_APPLICATION_SQL = " INSERT INTO AM_APPLICATION (NAME, SUBSCRIBER_ID, APPLICATION_TIER, " + " CALLBACK_URL, DESCRIPTION, APPLICATION_STATUS, GROUP_ID, CREATED_BY, CREATED_TIME, UPDATED_TIME, " + - "UUID, TOKEN_TYPE, ORGANIZATION)" + - " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"; + "UUID, TOKEN_TYPE, ORGANIZATION, SHARED_ORGANIZATION)" + + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; public static final String UPDATE_APPLICATION_SQL = " UPDATE " + @@ -1022,7 +1022,8 @@ public class SQLConstants { " DESCRIPTION = ?, " + " UPDATED_BY = ?, " + " UPDATED_TIME = ?, " + - " TOKEN_TYPE = ? " + + " TOKEN_TYPE = ?, " + + " SHARED_ORGANIZATION = ? " + " WHERE" + " APPLICATION_ID = ?"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java index 03aead5993a2..5c09b58ec01a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java @@ -181,7 +181,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " GROUP_ID, " + " UUID, " + " APP.CREATED_BY AS CREATED_BY, " + - " APP.TOKEN_TYPE AS TOKEN_TYPE " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + " FROM" + " AM_APPLICATION APP, " + " AM_SUBSCRIBER SUB " + @@ -212,7 +213,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " GROUP_ID, " + " UUID, " + " APP.CREATED_BY AS CREATED_BY, " + - " APP.TOKEN_TYPE AS TOKEN_TYPE " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + " FROM" + " AM_APPLICATION APP, " + " AM_SUBSCRIBER SUB " + @@ -227,6 +229,68 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + " ORDER BY $1 $2 limit ? , ?"; + public static final String GET_APPLICATIONS_PREFIX_CASESENSITVE_WITH_ORGSHARING = + "select distinct x.*,bl.ENABLED from (" + + "SELECT " + + " APPLICATION_ID, " + + " NAME," + + " APPLICATION_TIER," + + " APP.SUBSCRIBER_ID, " + + " APP.CREATED_TIME AS APP_CREATED_TIME, " + + " APP.UPDATED_TIME AS APP_UPDATED_TIME, " + + " CALLBACK_URL, " + + " DESCRIPTION, " + + " APPLICATION_STATUS, " + + " USER_ID, " + + " GROUP_ID, " + + " UUID, " + + " APP.CREATED_BY AS CREATED_BY, " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + + " FROM" + + " AM_APPLICATION APP, " + + " AM_SUBSCRIBER SUB " + + " WHERE " + + " SUB.SUBSCRIBER_ID = APP.SUBSCRIBER_ID " + + " AND (LOWER(SUB.USER_ID) = LOWER(?) OR APP.SHARED_ORGANIZATION = ? )" + + " AND " + + " APP.ORGANIZATION = ? " + + " And "+ + " LOWER (NAME) like LOWER (?)"+ + " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + + " ORDER BY $1 $2 limit ? , ?"; + + public static final String GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE_WITH_ORGSHARING = + "select distinct x.*,bl.ENABLED from (" + + "SELECT " + + " APPLICATION_ID, " + + " NAME," + + " APPLICATION_TIER," + + " APP.SUBSCRIBER_ID, " + + " APP.CREATED_TIME AS APP_CREATED_TIME, " + + " APP.UPDATED_TIME AS APP_UPDATED_TIME, " + + " CALLBACK_URL, " + + " DESCRIPTION, " + + " APPLICATION_STATUS, " + + " USER_ID, " + + " GROUP_ID, " + + " UUID, " + + " APP.CREATED_BY AS CREATED_BY, " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + + " FROM" + + " AM_APPLICATION APP, " + + " AM_SUBSCRIBER SUB " + + " WHERE " + + " SUB.SUBSCRIBER_ID = APP.SUBSCRIBER_ID " + + " AND (LOWER(SUB.USER_ID) = LOWER(?) OR APP.SHARED_ORGANIZATION = ? )" + + " AND " + + " APP.ORGANIZATION = ? " + + " And "+ + " LOWER (NAME) like LOWER (?)"+ + " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + + " ORDER BY $1 $2 limit ? , ?"; + public static final String GET_APPLICATIONS_BY_TENANT_ID = " SELECT " + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java index 225f12efa074..ec38b804982a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java @@ -73,6 +73,38 @@ public static TokenTypeEnum fromValue(String v) { private String createdTime = null; private String updatedTime = null; + @XmlType(name="VisibilityEnum") + @XmlEnum(String.class) + public enum VisibilityEnum { + PRIVATE("PRIVATE"), + SHARED_WITH_ORG("SHARED_WITH_ORG"); + private String value; + + VisibilityEnum (String v) { + value = v; + } + + public String value() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static VisibilityEnum fromValue(String v) { + for (VisibilityEnum b : VisibilityEnum.values()) { + if (String.valueOf(b.value).equals(v)) { + return b; + } + } +return null; + } + } + private VisibilityEnum visibility = null; + /** **/ public ApplicationDTO applicationId(String applicationId) { @@ -334,6 +366,23 @@ public void setUpdatedTime(String updatedTime) { this.updatedTime = updatedTime; } + /** + **/ + public ApplicationDTO visibility(VisibilityEnum visibility) { + this.visibility = visibility; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("visibility") + public VisibilityEnum getVisibility() { + return visibility; + } + public void setVisibility(VisibilityEnum visibility) { + this.visibility = visibility; + } + @Override public boolean equals(java.lang.Object o) { @@ -358,12 +407,13 @@ public boolean equals(java.lang.Object o) { Objects.equals(owner, application.owner) && Objects.equals(hashEnabled, application.hashEnabled) && Objects.equals(createdTime, application.createdTime) && - Objects.equals(updatedTime, application.updatedTime); + Objects.equals(updatedTime, application.updatedTime) && + Objects.equals(visibility, application.visibility); } @Override public int hashCode() { - return Objects.hash(applicationId, name, throttlingPolicy, description, tokenType, status, groups, subscriptionCount, keys, attributes, subscriptionScopes, owner, hashEnabled, createdTime, updatedTime); + return Objects.hash(applicationId, name, throttlingPolicy, description, tokenType, status, groups, subscriptionCount, keys, attributes, subscriptionScopes, owner, hashEnabled, createdTime, updatedTime, visibility); } @Override @@ -386,6 +436,7 @@ public String toString() { sb.append(" hashEnabled: ").append(toIndentedString(hashEnabled)).append("\n"); sb.append(" createdTime: ").append(toIndentedString(createdTime)).append("\n"); sb.append(" updatedTime: ").append(toIndentedString(updatedTime)).append("\n"); + sb.append(" visibility: ").append(toIndentedString(visibility)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index 616753f2b2d0..619f74850c8c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -44,6 +44,7 @@ import org.wso2.carbon.apimgt.api.model.Application; import org.wso2.carbon.apimgt.api.model.ApplicationConstants; import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.Subscriber; import org.wso2.carbon.apimgt.impl.APIConstants; @@ -62,6 +63,7 @@ import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyGenerateRequestDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyRevokeRequestDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO; +import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO.VisibilityEnum; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationInfoDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationKeyDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationKeyGenerateRequestDTO; @@ -137,12 +139,14 @@ public Response applicationsGet(String groupId, String query, String sortBy, Str groupId = RestApiUtil.getLoggedInUserGroupId(); try { String organization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); Subscriber subscriber = new Subscriber(username); Application[] applications; + String sharedOrganization = orgInfo.getName(); applications = apiConsumer .getApplicationsWithPagination(new Subscriber(username), groupId, offset, limit, query, sortBy, - sortOrder, organization); + sortOrder, organization, sharedOrganization); if (applications != null) { JSONArray applicationAttributesFromConfig = apiConsumer.getAppAttributesFromConfig(username); for (Application application : applications) { @@ -243,15 +247,16 @@ public Response applicationsGet(String groupId, String query, String sortBy, Str } String organization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); if (APIUtil.isApplicationExist(ownerId, applicationDTO.getName(), applicationGroupId, organization) && update != null && update) { int appId = APIUtil.getApplicationId(applicationDTO.getName(), ownerId); Application oldApplication = apiConsumer.getApplicationById(appId); application = preProcessAndUpdateApplication(ownerId, applicationDTO, oldApplication, - oldApplication.getUUID()); + oldApplication.getUUID(), orgInfo.getName()); } else { - application = preProcessAndAddApplication(ownerId, applicationDTO, organization); + application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getName()); update = Boolean.FALSE; } @@ -323,7 +328,8 @@ public Response applicationsPost(ApplicationDTO body, MessageContext messageCont body.setTokenType(ApplicationDTO.TokenTypeEnum.JWT); String organization = RestApiUtil.getValidatedOrganization(messageContext); - Application createdApplication = preProcessAndAddApplication(username, body, organization); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + Application createdApplication = preProcessAndAddApplication(username, body, organization, orgInfo.getName()); ApplicationDTO createdApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(createdApplication); //to be set as the Location header @@ -356,8 +362,8 @@ public Response applicationsPost(ApplicationDTO body, MessageContext messageCont * @param organization Identifier of an organization * @return Created application */ - private Application preProcessAndAddApplication(String username, ApplicationDTO applicationDto, String organization) - throws APIManagementException { + private Application preProcessAndAddApplication(String username, ApplicationDTO applicationDto, String organization, + String sharedOrganization) throws APIManagementException { APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); //validate the tier specified for the application @@ -375,6 +381,12 @@ private Application preProcessAndAddApplication(String username, ApplicationDTO //subscriber field of the body is not honored. It is taken from the context Application application = ApplicationMappingUtil.fromDTOtoApplication(applicationDto, username); + + application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); // default + if ((applicationDto.getVisibility() != null) + && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { + application.setSharedOrganization(sharedOrganization); + } int applicationId = apiConsumer.addApplication(application, username, organization); @@ -468,8 +480,9 @@ public Response applicationsApplicationIdPut(String applicationId, ApplicationDT "A duplicate application already exists by the name - " + body.getName()); } } + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); Application updatedApplication = preProcessAndUpdateApplication(username, body, oldApplication, - applicationId); + applicationId, orgInfo.getName()); ApplicationDTO updatedApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(updatedApplication); return Response.ok().entity(updatedApplicationDTO).build(); @@ -531,7 +544,7 @@ public Response applicationsApplicationIdResetThrottlePolicyPost(String applicat * @return Updated application */ private Application preProcessAndUpdateApplication(String username, ApplicationDTO applicationDto, - Application oldApplication, String applicationId) throws APIManagementException { + Application oldApplication, String applicationId, String sharedOrganization) throws APIManagementException { APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); Object applicationAttributesFromUser = applicationDto.getAttributes(); Map applicationAttributes = new ObjectMapper() @@ -547,6 +560,11 @@ private Application preProcessAndUpdateApplication(String username, ApplicationD //we do not honor the application id which is sent via the request body application.setUUID(oldApplication != null ? oldApplication.getUUID() : null); + application.setSharedOrganization(oldApplication.getSharedOrganization()); // default + if ((applicationDto.getVisibility() != null) + && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { + application.setSharedOrganization(sharedOrganization); + } apiConsumer.updateApplication(application); //retrieves the updated application and send as the response diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml index b99d43642ed8..296ce294b71d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml @@ -4363,6 +4363,11 @@ components: type: string readOnly: true example: 1651555310208 + visibility: + type: string + enum: + - PRIVATE + - SHARED_WITH_ORG ApplicationInfo: title: Application info object with basic application details type: object diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index 16a72011705b..4687988fc523 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -1542,6 +1542,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( UUID VARCHAR(256), TOKEN_TYPE VARCHAR(10), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql index a4bace7ddf78..71cbc6bd6267 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql @@ -1490,6 +1490,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( UUID VARCHAR(256), TOKEN_TYPE VARCHAR(10), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), From 9514f90c2d315efe699bba7f3a8b7b457a965614 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Sat, 17 Aug 2024 08:54:57 +0530 Subject: [PATCH 04/74] Remove invalid files --- .../apimgt/org.wso2.carbon.apimgt.impl/code | 648 ------------------ 1 file changed, 648 deletions(-) delete mode 100644 components/apimgt/org.wso2.carbon.apimgt.impl/code diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/code b/components/apimgt/org.wso2.carbon.apimgt.impl/code deleted file mode 100644 index 07d29e164d3f..000000000000 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/code +++ /dev/null @@ -1,648 +0,0 @@ -diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java -index f3edb073ec6..06d9a3e4ac2 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java -@@ -462,12 +462,13 @@ public interface APIConsumer extends APIManager { - * @param offset - * @param groupingId the groupId to which the applications must belong. - * @param organization Identifier of an organization -+ * @param sharedOrganization - * @return Applications - * @throws APIManagementException if failed to applications for given subscriber - */ - - Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, int offset, -- String search, String sortColumn, String sortOrder, String organization) -+ String search, String sortColumn, String sortOrder, String organization, String sharedOrganization) - throws APIManagementException; - - /** -diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java -index 556746ea27c..e40003eeb9f 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Application.java -@@ -58,6 +58,8 @@ public class Application { - private String keyType; - private int subscriptionCount; - private String keyManager; -+ private String sharedOrganization; -+ - public String getCreatedTime() { - return createdTime; - } -@@ -320,4 +322,12 @@ public class Application { - - this.organization = organization; - } -+ -+ public String getSharedOrganization() { -+ return sharedOrganization; -+ } -+ -+ public void setSharedOrganization(String sharedOrganization) { -+ this.sharedOrganization = sharedOrganization; -+ } - } -diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java -index ef5461ccbb3..31724f5aef0 100755 ---- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java -@@ -823,6 +823,7 @@ public final class APIConstants { - "internal_application_mgt_delete", "internal_application_mgt_update", "internal_application_mgt_view", - "internal_user_mgt_list"}; - public static final String KEY_MANAGER_CLIENT_APPLICATION_PREFIX = "wso2_apim_km_"; -+ public static final String DEFAULT_APP_SHARING_KEYWORD = "private"; - - public static final String TOKEN_URL = "TokenURL"; - public static final String REVOKE_URL = "RevokeURL"; -diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java -index ae44701e65d..bf3ab8f624d 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java -@@ -1664,6 +1664,9 @@ public class APIConsumerImpl extends AbstractAPIManager implements APIConsumer { - if (StringUtils.isBlank(application.getCallbackUrl())) { - application.setCallbackUrl(null); - } -+ if (StringUtils.isEmpty(application.getSharedOrganization())) { -+ application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); -+ } - int applicationId = apiMgtDAO.addApplication(application, userId, organization); - Application createdApplication = apiMgtDAO.getApplicationById(applicationId); - -@@ -1894,6 +1897,9 @@ public class APIConsumerImpl extends AbstractAPIManager implements APIConsumer { - application.setApplicationAttributes(null); - } - validateApplicationPolicy(application, existingApp.getOrganization()); -+ if (StringUtils.isEmpty(application.getSharedOrganization())) { -+ application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); -+ } - apiMgtDAO.updateApplication(application); - Application updatedApplication = apiMgtDAO.getApplicationById(application.getId()); - if (log.isDebugEnabled()) { -@@ -2786,19 +2792,20 @@ APIConstants.AuditLogConstants.DELETED, this.username); - * @param sortColumn The sort column. - * @param sortOrder The sort order. - * @param organization Identifier of an Organization -+ * @param sharedOrganization - * @return Application[] The Applications. - * @throws APIManagementException - */ - @Override - public Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, int offset -- , String search, String sortColumn, String sortOrder, String organization) -+ , String search, String sortColumn, String sortOrder, String organization, String sharedOrganization) - throws APIManagementException { - - if (APIUtil.isOnPremResolver()) { - organization = tenantDomain; - } - return apiMgtDAO.getApplicationsWithPagination(subscriber, groupingId, start, offset, -- search, sortColumn, sortOrder, organization); -+ search, sortColumn, sortOrder, organization, sharedOrganization); - } - - /** -diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java -index 06decdd0970..40a4771b5b4 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java -@@ -3497,6 +3497,7 @@ public class ApiMgtDAO { - ps.setString(11, application.getUUID()); - ps.setString(12, String.valueOf(application.getTokenType())); - ps.setString(13, organization); -+ ps.setString(14, application.getSharedOrganization()); - ps.executeUpdate(); - - rs = ps.getGeneratedKeys(); -@@ -3537,7 +3538,8 @@ public class ApiMgtDAO { - ps.setString(5, null); - ps.setTimestamp(6, new Timestamp(System.currentTimeMillis())); - ps.setString(7, application.getTokenType()); -- ps.setInt(8, application.getId()); -+ ps.setString(8, application.getSharedOrganization()); -+ ps.setInt(9, application.getId()); - - ps.executeUpdate(); - -@@ -4118,7 +4120,8 @@ public class ApiMgtDAO { - * @throws APIManagementException - */ - public Application[] getApplicationsWithPagination(Subscriber subscriber, String groupingId, int start, -- int offset, String search, String sortColumn, String sortOrder, String organization) -+ int offset, String search, String sortColumn, String sortOrder, String organization, -+ String sharedOrganization) - throws APIManagementException { - - Connection connection = null; -@@ -4126,7 +4129,7 @@ public class ApiMgtDAO { - ResultSet rs = null; - Application[] applications = null; - String sqlQuery = null; -- -+ boolean isOrgSharingEnabled = true; //TODO need to come from config or from user info - if (groupingId != null && !"null".equals(groupingId) && !groupingId.isEmpty()) { - if (multiGroupAppSharingEnabled) { - if (forceCaseInsensitiveComparisons) { -@@ -4147,9 +4150,19 @@ public class ApiMgtDAO { - } - } else { - if (forceCaseInsensitiveComparisons) { -- sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE"); -+ if (isOrgSharingEnabled) { -+ sqlQuery = SQLConstantManagerFactory -+ .getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE_WITH_ORGSHARING"); -+ } else { -+ sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE"); -+ } - } else { -- sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE"); -+ if (isOrgSharingEnabled) { -+ sqlQuery = SQLConstantManagerFactory -+ .getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE_WITH_ORGSHARING"); -+ } else { -+ sqlQuery = SQLConstantManagerFactory.getSQlString("GET_APPLICATIONS_PREFIX_CASESENSITVE"); -+ } - } - } - -@@ -4196,12 +4209,22 @@ public class ApiMgtDAO { - prepStmt.setInt(6, offset); - } - } else { -- prepStmt = connection.prepareStatement(sqlQuery); -- prepStmt.setString(1, subscriber.getName()); -- prepStmt.setString(2, organization); -- prepStmt.setString(3, "%" + search + "%"); -- prepStmt.setInt(4, start); -- prepStmt.setInt(5, offset); -+ if (isOrgSharingEnabled) { -+ prepStmt = connection.prepareStatement(sqlQuery); -+ prepStmt.setString(1, subscriber.getName()); -+ prepStmt.setString(2, sharedOrganization); -+ prepStmt.setString(3, organization); -+ prepStmt.setString(4, "%" + search + "%"); -+ prepStmt.setInt(5, start); -+ prepStmt.setInt(6, offset); -+ } else { -+ prepStmt = connection.prepareStatement(sqlQuery); -+ prepStmt.setString(1, subscriber.getName()); -+ prepStmt.setString(2, organization); -+ prepStmt.setString(3, "%" + search + "%"); -+ prepStmt.setInt(4, start); -+ prepStmt.setInt(5, offset); -+ } - } - if (log.isDebugEnabled()) { - log.debug("Query: " + sqlQuery); -@@ -4238,6 +4261,7 @@ public class ApiMgtDAO { - // Get custom attributes of application - Map applicationAttributes = getApplicationAttributes(connection, applicationId); - application.setApplicationAttributes(applicationAttributes); -+ application.setSharedOrganization(rs.getString("SHARED_ORGANIZATION")); - - applicationsList.add(application); - } -diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java -index e52d62eaa65..0f4fcc9d6ee 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java -@@ -1009,8 +1009,8 @@ public class SQLConstants { - public static final String APP_APPLICATION_SQL = - " INSERT INTO AM_APPLICATION (NAME, SUBSCRIBER_ID, APPLICATION_TIER, " + - " CALLBACK_URL, DESCRIPTION, APPLICATION_STATUS, GROUP_ID, CREATED_BY, CREATED_TIME, UPDATED_TIME, " + -- "UUID, TOKEN_TYPE, ORGANIZATION)" + -- " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"; -+ "UUID, TOKEN_TYPE, ORGANIZATION, SHARED_ORGANIZATION)" + -+ " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; - - public static final String UPDATE_APPLICATION_SQL = - " UPDATE " + -@@ -1022,7 +1022,8 @@ public class SQLConstants { - " DESCRIPTION = ?, " + - " UPDATED_BY = ?, " + - " UPDATED_TIME = ?, " + -- " TOKEN_TYPE = ? " + -+ " TOKEN_TYPE = ?, " + -+ " SHARED_ORGANIZATION = ? " + - " WHERE" + - " APPLICATION_ID = ?"; - -diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java -index 03aead5993a..5c09b58ec01 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java -@@ -181,7 +181,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ - " GROUP_ID, " + - " UUID, " + - " APP.CREATED_BY AS CREATED_BY, " + -- " APP.TOKEN_TYPE AS TOKEN_TYPE " + -+ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + -+ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + - " FROM" + - " AM_APPLICATION APP, " + - " AM_SUBSCRIBER SUB " + -@@ -212,7 +213,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ - " GROUP_ID, " + - " UUID, " + - " APP.CREATED_BY AS CREATED_BY, " + -- " APP.TOKEN_TYPE AS TOKEN_TYPE " + -+ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + -+ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + - " FROM" + - " AM_APPLICATION APP, " + - " AM_SUBSCRIBER SUB " + -@@ -227,6 +229,68 @@ public class SQLConstantsH2MySQL extends SQLConstants{ - " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + - " ORDER BY $1 $2 limit ? , ?"; - -+ public static final String GET_APPLICATIONS_PREFIX_CASESENSITVE_WITH_ORGSHARING = -+ "select distinct x.*,bl.ENABLED from (" + -+ "SELECT " + -+ " APPLICATION_ID, " + -+ " NAME," + -+ " APPLICATION_TIER," + -+ " APP.SUBSCRIBER_ID, " + -+ " APP.CREATED_TIME AS APP_CREATED_TIME, " + -+ " APP.UPDATED_TIME AS APP_UPDATED_TIME, " + -+ " CALLBACK_URL, " + -+ " DESCRIPTION, " + -+ " APPLICATION_STATUS, " + -+ " USER_ID, " + -+ " GROUP_ID, " + -+ " UUID, " + -+ " APP.CREATED_BY AS CREATED_BY, " + -+ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + -+ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + -+ " FROM" + -+ " AM_APPLICATION APP, " + -+ " AM_SUBSCRIBER SUB " + -+ " WHERE " + -+ " SUB.SUBSCRIBER_ID = APP.SUBSCRIBER_ID " + -+ " AND (LOWER(SUB.USER_ID) = LOWER(?) OR APP.SHARED_ORGANIZATION = ? )" + -+ " AND " + -+ " APP.ORGANIZATION = ? " + -+ " And "+ -+ " LOWER (NAME) like LOWER (?)"+ -+ " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + -+ " ORDER BY $1 $2 limit ? , ?"; -+ -+ public static final String GET_APPLICATIONS_PREFIX_NONE_CASESENSITVE_WITH_ORGSHARING = -+ "select distinct x.*,bl.ENABLED from (" + -+ "SELECT " + -+ " APPLICATION_ID, " + -+ " NAME," + -+ " APPLICATION_TIER," + -+ " APP.SUBSCRIBER_ID, " + -+ " APP.CREATED_TIME AS APP_CREATED_TIME, " + -+ " APP.UPDATED_TIME AS APP_UPDATED_TIME, " + -+ " CALLBACK_URL, " + -+ " DESCRIPTION, " + -+ " APPLICATION_STATUS, " + -+ " USER_ID, " + -+ " GROUP_ID, " + -+ " UUID, " + -+ " APP.CREATED_BY AS CREATED_BY, " + -+ " APP.TOKEN_TYPE AS TOKEN_TYPE, " + -+ " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + -+ " FROM" + -+ " AM_APPLICATION APP, " + -+ " AM_SUBSCRIBER SUB " + -+ " WHERE " + -+ " SUB.SUBSCRIBER_ID = APP.SUBSCRIBER_ID " + -+ " AND (LOWER(SUB.USER_ID) = LOWER(?) OR APP.SHARED_ORGANIZATION = ? )" + -+ " AND " + -+ " APP.ORGANIZATION = ? " + -+ " And "+ -+ " LOWER (NAME) like LOWER (?)"+ -+ " )x left join AM_BLOCK_CONDITIONS bl on ( bl.TYPE = 'APPLICATION' AND bl.BLOCK_CONDITION = concat(concat(x.USER_ID,':'),x.name)) " + -+ " ORDER BY $1 $2 limit ? , ?"; -+ - - public static final String GET_APPLICATIONS_BY_TENANT_ID = - " SELECT " + -diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml -index ca7602542f8..cbd88d5ea90 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml -+++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml -@@ -8167,7 +8167,7 @@ paths: - x-code-samples: - - lang: Curl - source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" -- -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 -+ -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 - "https://127.0.0.1:9443/api/am/publisher/v4/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/operation-policies"' - - -@@ -8411,7 +8411,7 @@ paths: - x-code-samples: - - lang: Curl - source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" -- -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 -+ -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 - "https://127.0.0.1:9443/api/am/publisher/v4/operation-policies"' - - /operation-policies/export: -@@ -9226,6 +9226,12 @@ components: - enum: - - PUBLIC - - SINGLE -+ audiences: -+ type: array -+ description: The audiences of the API for jwt validation. Accepted values are any String values -+ items: -+ type: string -+ example: [ "aud1","aud2","aud3" ] - lifeCycleStatus: - type: string - example: CREATED -@@ -9443,6 +9449,12 @@ components: - enum: - - PUBLIC - - SINGLE -+ audiences: -+ type: array -+ description: The audiences of the API for jwt validation. Accepted values are any String values -+ items: -+ type: string -+ example: [ "aud1","aud2","aud3" ] - transport: - type: array - description: | -@@ -10042,6 +10054,12 @@ components: - gatewayVendor: - type: string - example: wso2 -+ audiences: -+ type: array -+ description: The audiences of the API product for jwt validation. Accepted values are any String values -+ items: -+ type: string -+ example: [ "aud1","aud2","aud3" ] - monetizedInfo: - type: boolean - example: true -@@ -10315,6 +10333,12 @@ components: - workflowStatus: - type: string - example: APPROVED -+ audiences: -+ type: array -+ description: The audiences of the API for jwt validation. Accepted values are any String values -+ items: -+ type: string -+ example: [ "aud1","aud2","aud3" ] - ProductAPI: - title: ProductAPI - required: -diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java -index 225f12efa07..ec38b804982 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/ApplicationDTO.java -@@ -73,6 +73,38 @@ return null; - private String createdTime = null; - private String updatedTime = null; - -+ @XmlType(name="VisibilityEnum") -+ @XmlEnum(String.class) -+ public enum VisibilityEnum { -+ PRIVATE("PRIVATE"), -+ SHARED_WITH_ORG("SHARED_WITH_ORG"); -+ private String value; -+ -+ VisibilityEnum (String v) { -+ value = v; -+ } -+ -+ public String value() { -+ return value; -+ } -+ -+ @Override -+ public String toString() { -+ return String.valueOf(value); -+ } -+ -+ @JsonCreator -+ public static VisibilityEnum fromValue(String v) { -+ for (VisibilityEnum b : VisibilityEnum.values()) { -+ if (String.valueOf(b.value).equals(v)) { -+ return b; -+ } -+ } -+return null; -+ } -+ } -+ private VisibilityEnum visibility = null; -+ - /** - **/ - public ApplicationDTO applicationId(String applicationId) { -@@ -334,6 +366,23 @@ return null; - this.updatedTime = updatedTime; - } - -+ /** -+ **/ -+ public ApplicationDTO visibility(VisibilityEnum visibility) { -+ this.visibility = visibility; -+ return this; -+ } -+ -+ -+ @ApiModelProperty(value = "") -+ @JsonProperty("visibility") -+ public VisibilityEnum getVisibility() { -+ return visibility; -+ } -+ public void setVisibility(VisibilityEnum visibility) { -+ this.visibility = visibility; -+ } -+ - - @Override - public boolean equals(java.lang.Object o) { -@@ -358,12 +407,13 @@ return null; - Objects.equals(owner, application.owner) && - Objects.equals(hashEnabled, application.hashEnabled) && - Objects.equals(createdTime, application.createdTime) && -- Objects.equals(updatedTime, application.updatedTime); -+ Objects.equals(updatedTime, application.updatedTime) && -+ Objects.equals(visibility, application.visibility); - } - - @Override - public int hashCode() { -- return Objects.hash(applicationId, name, throttlingPolicy, description, tokenType, status, groups, subscriptionCount, keys, attributes, subscriptionScopes, owner, hashEnabled, createdTime, updatedTime); -+ return Objects.hash(applicationId, name, throttlingPolicy, description, tokenType, status, groups, subscriptionCount, keys, attributes, subscriptionScopes, owner, hashEnabled, createdTime, updatedTime, visibility); - } - - @Override -@@ -386,6 +436,7 @@ return null; - sb.append(" hashEnabled: ").append(toIndentedString(hashEnabled)).append("\n"); - sb.append(" createdTime: ").append(toIndentedString(createdTime)).append("\n"); - sb.append(" updatedTime: ").append(toIndentedString(updatedTime)).append("\n"); -+ sb.append(" visibility: ").append(toIndentedString(visibility)).append("\n"); - sb.append("}"); - return sb.toString(); - } -diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java -index 616753f2b2d..619f74850c8 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java -+++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java -@@ -44,6 +44,7 @@ import org.wso2.carbon.apimgt.api.model.AccessTokenInfo; - import org.wso2.carbon.apimgt.api.model.Application; - import org.wso2.carbon.apimgt.api.model.ApplicationConstants; - import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; -+import org.wso2.carbon.apimgt.api.model.OrganizationInfo; - import org.wso2.carbon.apimgt.api.model.Scope; - import org.wso2.carbon.apimgt.api.model.Subscriber; - import org.wso2.carbon.apimgt.impl.APIConstants; -@@ -62,6 +63,7 @@ import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyDTO; - import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyGenerateRequestDTO; - import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIKeyRevokeRequestDTO; - import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO; -+import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO.VisibilityEnum; - import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationInfoDTO; - import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationKeyDTO; - import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationKeyGenerateRequestDTO; -@@ -137,12 +139,14 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - groupId = RestApiUtil.getLoggedInUserGroupId(); - try { - String organization = RestApiUtil.getValidatedOrganization(messageContext); -+ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); - APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); - Subscriber subscriber = new Subscriber(username); - Application[] applications; -+ String sharedOrganization = orgInfo.getName(); - applications = apiConsumer - .getApplicationsWithPagination(new Subscriber(username), groupId, offset, limit, query, sortBy, -- sortOrder, organization); -+ sortOrder, organization, sharedOrganization); - if (applications != null) { - JSONArray applicationAttributesFromConfig = apiConsumer.getAppAttributesFromConfig(username); - for (Application application : applications) { -@@ -243,15 +247,16 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - } - - String organization = RestApiUtil.getValidatedOrganization(messageContext); -+ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); - - if (APIUtil.isApplicationExist(ownerId, applicationDTO.getName(), applicationGroupId, organization) && update != null - && update) { - int appId = APIUtil.getApplicationId(applicationDTO.getName(), ownerId); - Application oldApplication = apiConsumer.getApplicationById(appId); - application = preProcessAndUpdateApplication(ownerId, applicationDTO, oldApplication, -- oldApplication.getUUID()); -+ oldApplication.getUUID(), orgInfo.getName()); - } else { -- application = preProcessAndAddApplication(ownerId, applicationDTO, organization); -+ application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getName()); - update = Boolean.FALSE; - } - -@@ -323,7 +328,8 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - body.setTokenType(ApplicationDTO.TokenTypeEnum.JWT); - - String organization = RestApiUtil.getValidatedOrganization(messageContext); -- Application createdApplication = preProcessAndAddApplication(username, body, organization); -+ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); -+ Application createdApplication = preProcessAndAddApplication(username, body, organization, orgInfo.getName()); - ApplicationDTO createdApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(createdApplication); - - //to be set as the Location header -@@ -356,8 +362,8 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - * @param organization Identifier of an organization - * @return Created application - */ -- private Application preProcessAndAddApplication(String username, ApplicationDTO applicationDto, String organization) -- throws APIManagementException { -+ private Application preProcessAndAddApplication(String username, ApplicationDTO applicationDto, String organization, -+ String sharedOrganization) throws APIManagementException { - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - - //validate the tier specified for the application -@@ -375,6 +381,12 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - - //subscriber field of the body is not honored. It is taken from the context - Application application = ApplicationMappingUtil.fromDTOtoApplication(applicationDto, username); -+ -+ application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); // default -+ if ((applicationDto.getVisibility() != null) -+ && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { -+ application.setSharedOrganization(sharedOrganization); -+ } - - int applicationId = apiConsumer.addApplication(application, username, organization); - -@@ -468,8 +480,9 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - "A duplicate application already exists by the name - " + body.getName()); - } - } -+ OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); - Application updatedApplication = preProcessAndUpdateApplication(username, body, oldApplication, -- applicationId); -+ applicationId, orgInfo.getName()); - ApplicationDTO updatedApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(updatedApplication); - return Response.ok().entity(updatedApplicationDTO).build(); - -@@ -531,7 +544,7 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - * @return Updated application - */ - private Application preProcessAndUpdateApplication(String username, ApplicationDTO applicationDto, -- Application oldApplication, String applicationId) throws APIManagementException { -+ Application oldApplication, String applicationId, String sharedOrganization) throws APIManagementException { - APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); - Object applicationAttributesFromUser = applicationDto.getAttributes(); - Map applicationAttributes = new ObjectMapper() -@@ -547,6 +560,11 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { - //we do not honor the application id which is sent via the request body - application.setUUID(oldApplication != null ? oldApplication.getUUID() : null); - -+ application.setSharedOrganization(oldApplication.getSharedOrganization()); // default -+ if ((applicationDto.getVisibility() != null) -+ && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { -+ application.setSharedOrganization(sharedOrganization); -+ } - apiConsumer.updateApplication(application); - - //retrieves the updated application and send as the response -diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml -index b99d43642ed..296ce294b71 100644 ---- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml -+++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml -@@ -4363,6 +4363,11 @@ components: - type: string - readOnly: true - example: 1651555310208 -+ visibility: -+ type: string -+ enum: -+ - PRIVATE -+ - SHARED_WITH_ORG - ApplicationInfo: - title: Application info object with basic application details - type: object -diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql -index 16a72011705..4687988fc52 100644 ---- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql -+++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql -@@ -1542,6 +1542,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( - UUID VARCHAR(256), - TOKEN_TYPE VARCHAR(10), - ORGANIZATION VARCHAR(100), -+ SHARED_ORGANIZATION VARCHAR(100), - FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, - PRIMARY KEY(APPLICATION_ID), - UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), -diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql -index a4bace7ddf7..71cbc6bd626 100644 ---- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql -+++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql -@@ -1490,6 +1490,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( - UUID VARCHAR(256), - TOKEN_TYPE VARCHAR(10), - ORGANIZATION VARCHAR(100), -+ SHARED_ORGANIZATION VARCHAR(100), - FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, - PRIMARY KEY(APPLICATION_ID), - UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), From 74ce0a943e7c5644f4cc8d52f87ed001e8e644bf Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 21 Aug 2024 12:21:07 +0530 Subject: [PATCH 05/74] Add application visibility info to the payload --- .../java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java | 1 + .../carbon/apimgt/impl/dao/constants/SQLConstants.java | 1 + .../rest/api/store/v1/mappings/ApplicationMappingUtil.java | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 40a4771b5b47..5438ff4c2a02 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -6682,6 +6682,7 @@ public Application getApplicationByUUID(String uuid) throws APIManagementExcepti application.setTokenType(rs.getString("TOKEN_TYPE")); application.setOwner(rs.getString("CREATED_BY")); application.setOrganization(rs.getString("ORGANIZATION")); + application.setSharedOrganization(rs.getString("SHARED_ORGANIZATION")); subscriber.setId(rs.getInt("SUBSCRIBER_ID")); application.setLastUpdatedTime(String.valueOf(rs.getTimestamp("UPDATED_TIME").getTime())); application.setCreatedTime(String.valueOf(rs.getTimestamp("CREATED_TIME").getTime())); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index 0f4fcc9d6eef..6afaa9682145 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -1630,6 +1630,7 @@ public class SQLConstants { " APP.TOKEN_TYPE," + " APP.CREATED_BY," + " APP.ORGANIZATION ORGANIZATION,"+ + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION, " + " SUB.USER_ID " + " FROM " + " AM_SUBSCRIBER SUB," + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/ApplicationMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/ApplicationMappingUtil.java index 0531358de3b1..7f49b061f031 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/ApplicationMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/ApplicationMappingUtil.java @@ -28,6 +28,7 @@ import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationAttributeDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationAttributeListDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO; +import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationDTO.VisibilityEnum; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationInfoDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.ApplicationListDTO; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.PaginationDTO; @@ -64,6 +65,12 @@ public static ApplicationDTO fromApplicationtoDTO(Application application) throw .equals(application.getTokenType())) { applicationDTO.setTokenType(ApplicationDTO.TokenTypeEnum.valueOf(application.getTokenType())); } + if ((application.getSharedOrganization() == null) + || (APIConstants.DEFAULT_APP_SHARING_KEYWORD.equals(application.getSharedOrganization()))) { + applicationDTO.setVisibility(VisibilityEnum.PRIVATE); + } else { + applicationDTO.setVisibility(VisibilityEnum.SHARED_WITH_ORG); + } //todo: Uncomment when this is implemented /*List applicationKeyDTOs = new ArrayList<>(); From 44adec37fa44b901b4cc5f4ef89084eb06330f4d Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 21 Aug 2024 12:21:26 +0530 Subject: [PATCH 06/74] Allow api visibility to admin users --- .../carbon/apimgt/persistence/RegistryPersistenceImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 4767a11f1c80..a7831db71360 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -43,6 +43,7 @@ import org.wso2.carbon.apimgt.persistence.internal.ServiceReferenceHolder; import org.wso2.carbon.apimgt.persistence.mapper.APIMapper; import org.wso2.carbon.apimgt.persistence.mapper.APIProductMapper; +import org.wso2.carbon.apimgt.persistence.utils.PersistenceUtil; import org.wso2.carbon.apimgt.persistence.utils.PublisherAPISearchResultComparator; import org.wso2.carbon.apimgt.persistence.utils.RegistryPersistenceDocUtil; import org.wso2.carbon.apimgt.persistence.utils.RegistryPersistenceUtil; @@ -1078,8 +1079,10 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String log.debug("Requested query for devportal search: " + searchQuery); String modifiedQuery = RegistrySearchUtil.getDevPortalSearchQuery(searchQuery, ctx, isAllowDisplayAPIsWithMultipleStatus(), isAllowDisplayAPIsWithMultipleVersions()); - modifiedQuery = modifiedQuery + "&visibleOrganizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" - + ctx.getOrganization().getName() + "*)"; + if (!PersistenceUtil.isAdminUser(ctx)) { + modifiedQuery = modifiedQuery + "&visibleOrganizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" + + ctx.getOrganization().getName() + "*)"; + } log.debug("Modified query for devportal search: " + modifiedQuery); String userNameLocal; if (holder.isAnonymousMode()) { From 9b4b931a0fac125a2920ba05afabc64c5a88fc75 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 21 Aug 2024 17:56:01 +0530 Subject: [PATCH 07/74] Fix bug --- .../api/store/v1/impl/ApplicationsApiServiceImpl.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index 619f74850c8c..e2968fd67bda 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -561,9 +561,13 @@ private Application preProcessAndUpdateApplication(String username, ApplicationD application.setUUID(oldApplication != null ? oldApplication.getUUID() : null); application.setSharedOrganization(oldApplication.getSharedOrganization()); // default - if ((applicationDto.getVisibility() != null) - && applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { - application.setSharedOrganization(sharedOrganization); + if (applicationDto.getVisibility() != null) { + if (applicationDto.getVisibility() == VisibilityEnum.SHARED_WITH_ORG && sharedOrganization != null) { + application.setSharedOrganization(sharedOrganization); + } else if (applicationDto.getVisibility() == VisibilityEnum.PRIVATE) { + application.setSharedOrganization(APIConstants.DEFAULT_APP_SHARING_KEYWORD); + } + } apiConsumer.updateApplication(application); From cbbec05db6b74b7bf8061c082e379a845f2c2789 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Fri, 23 Aug 2024 17:42:51 +0530 Subject: [PATCH 08/74] Add subscription tiers visibility by org --- .../api/model/policy/SubscriptionPolicy.java | 21 +++- .../wso2/carbon/apimgt/impl/APIConstants.java | 1 + .../carbon/apimgt/impl/APIConsumerImpl.java | 1 + .../apimgt/impl/ThrottlePolicyConstants.java | 2 + .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 119 ++++++++++++------ .../impl/dao/constants/SQLConstants.java | 14 ++- .../carbon/apimgt/impl/utils/APIUtil.java | 17 +++ .../SubscriptionThrottlePolicyAllOfDTO.java | 24 +++- .../v1/dto/SubscriptionThrottlePolicyDTO.java | 24 +++- ...SubscriptionThrottlePolicyMappingUtil.java | 2 + .../src/main/resources/admin-api.yaml | 4 + .../api/store/v1/impl/ApisApiServiceImpl.java | 29 +++-- .../src/main/resources/sql/h2.sql | 1 + .../src/main/resources/sql/mysql.sql | 1 + 14 files changed, 197 insertions(+), 63 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java index 481308c21d01..32c4b046d4cb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java @@ -18,8 +18,10 @@ package org.wso2.carbon.apimgt.api.model.policy; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; public class SubscriptionPolicy extends Policy { @@ -34,6 +36,7 @@ public class SubscriptionPolicy extends Policy { private String tierQuotaType; private int graphQLMaxDepth; private int graphQLMaxComplexity; + private List allowedOrganizations = new ArrayList(); public SubscriptionPolicy(String name) { super(name); @@ -122,11 +125,11 @@ public void setGraphQLMaxComplexity(int graphQLMaxComplexity) { @Override public String toString() { return "SubscriptionPolicy [rateLimitCount=" + rateLimitCount + ", rateLimitTimeUnit=" + rateLimitTimeUnit - + ", customAttributes=" + Arrays.toString(customAttributes) + ", stopOnQuotaReach=" + stopOnQuotaReach - + ", billingPlan=" + billingPlan + ", monetizationPlan=" + monetizationPlan - + ", monetizationPlanProperties=" + monetizationPlanProperties + ", tierQuotaType=" + tierQuotaType - + ", maxDepth=" + graphQLMaxDepth + ", maxComplexity=" + graphQLMaxComplexity - + ", subscriberCount= " + subscriberCount + "]"; + + ", subscriberCount=" + subscriberCount + ", customAttributes=" + Arrays.toString(customAttributes) + + ", stopOnQuotaReach=" + stopOnQuotaReach + ", billingPlan=" + billingPlan + ", monetizationPlan=" + + monetizationPlan + ", monetizationPlanProperties=" + monetizationPlanProperties + ", tierQuotaType=" + + tierQuotaType + ", graphQLMaxDepth=" + graphQLMaxDepth + ", graphQLMaxComplexity=" + + graphQLMaxComplexity + ", allowedOrganizations=" + allowedOrganizations + "]"; } public int getSubscriberCount() { @@ -136,4 +139,12 @@ public int getSubscriberCount() { public void setSubscriberCount(int subscriberCount) { this.subscriberCount = subscriberCount; } + + public List getAllowedOrganizations() { + return allowedOrganizations; + } + + public void setAllowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index 31724f5aef0a..06488f27465a 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -1959,6 +1959,7 @@ public enum RegistryResourceTypesForUI { public static final String API_POLICY_API_LEVEL = "apiLevel"; public static final String BILLING_PLAN_FREE = "FREE"; + public static final String ALLOWED_ORGANIZATIONS_DEFAULT = "ALL"; public static final String POLICY_RESET = "reset"; public static final String BLOCKING_EVENT_TYPE = "wso2event"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index bf3ab8f624de..9a343f1b04b6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -3997,6 +3997,7 @@ private API addTiersToAPI(API api, String organization) throws APIManagementExce int tenantId = APIUtil.getInternalIdFromTenantDomainOrOrganization(organization); Set tierNames = api.getAvailableTiers(); + apiMgtDAO.getSubscriptionPolicies(tenantId); Map definedTiers = APIUtil.getTiers(tenantId); Set availableTiers = new HashSet(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java index 6280f6e5386f..ccdbd79663eb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java @@ -125,4 +125,6 @@ public class ThrottlePolicyConstants { public static final String COLUMN_MAX_DEPTH = "MAX_DEPTH"; public static final String COLUMN_MAX_COMPLEXITY = "MAX_COMPLEXITY"; + + public static final String COLUMN_ALLOWED_ORGANIZATIONS = "ALLOWED_ORGANIZATIONS"; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 5438ff4c2a02..3643489c5daf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -11484,8 +11484,25 @@ public void addSubscriptionPolicy(SubscriptionPolicy policy) throws APIManagemen policyStatement.setInt(15, policy.getGraphQLMaxDepth()); policyStatement.setInt(16, policy.getGraphQLMaxComplexity()); policyStatement.setString(17, policy.getBillingPlan()); + List list = policy.getAllowedOrganizations(); + String allowedOrganizations = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; //Default + if (list != null && !list.isEmpty()) { + allowedOrganizations = String.join(",", list); + } + policyStatement.setString(18, allowedOrganizations); if (hasCustomAttrib) { - policyStatement.setBytes(18, policy.getCustomAttributes()); + policyStatement.setBytes(19, policy.getCustomAttributes()); + policyStatement.setString(20, policy.getMonetizationPlan()); + policyStatement.setString(21, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); + policyStatement.setString(22, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); + policyStatement.setString(23, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); + policyStatement.setString(24, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); + policyStatement.setInt(25, policy.getSubscriberCount()); + } else { policyStatement.setString(19, policy.getMonetizationPlan()); policyStatement.setString(20, policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); @@ -11496,17 +11513,6 @@ public void addSubscriptionPolicy(SubscriptionPolicy policy) throws APIManagemen policyStatement.setString(23, policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); policyStatement.setInt(24, policy.getSubscriberCount()); - } else { - policyStatement.setString(18, policy.getMonetizationPlan()); - policyStatement.setString(19, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); - policyStatement.setString(20, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); - policyStatement.setString(21, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); - policyStatement.setString(22, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); - policyStatement.setInt(23, policy.getSubscriberCount()); } policyStatement.executeUpdate(); conn.commit(); @@ -12221,6 +12227,13 @@ public SubscriptionPolicy[] getSubscriptionPolicies(int tenantID) throws APIMana monetizationPlanProperties.put(APIConstants.Monetization.CURRENCY, rs.getString(ThrottlePolicyConstants.COLUMN_CURRENCY)); subPolicy.setMonetizationPlanProperties(monetizationPlanProperties); + String allowedOrgs = rs.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS); + if(allowedOrgs == null) { + allowedOrgs = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; // set default if null + } + String[] items = allowedOrgs.split(","); + ArrayList allowedOrglist = new ArrayList<>(Arrays.asList(items)); + subPolicy.setAllowedOrganizations(allowedOrglist); InputStream binary = rs.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -12648,6 +12661,13 @@ public SubscriptionPolicy getSubscriptionPolicy(String policyName, int tenantId) policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); + String allowedOrgs = resultSet.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS); + if(allowedOrgs == null) { + allowedOrgs = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; // set default if null + } + String[] items = allowedOrgs.split(","); + ArrayList allowedOrglist = new ArrayList<>(Arrays.asList(items)); + policy.setAllowedOrganizations(allowedOrglist); InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -12700,6 +12720,15 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); + + String allowedOrgs = resultSet.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS); + if(allowedOrgs == null) { + allowedOrgs = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; // set default if null + } + String[] items = allowedOrgs.split(","); + ArrayList allowedOrglist = new ArrayList<>(Arrays.asList(items)); + policy.setAllowedOrganizations(allowedOrglist); + InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -13137,10 +13166,45 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage updateStatement.setInt(11, policy.getGraphQLMaxDepth()); updateStatement.setInt(12, policy.getGraphQLMaxComplexity()); updateStatement.setString(13, policy.getBillingPlan()); + + List list = policy.getAllowedOrganizations(); + String allowedOrganizations = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; //Default + if (list != null && !list.isEmpty()) { + allowedOrganizations = String.join(",", list); + } + updateStatement.setString(14, allowedOrganizations); + if (hasCustomAttrib) { long lengthOfStream = policy.getCustomAttributes().length; - updateStatement.setBinaryStream(14, new ByteArrayInputStream(policy.getCustomAttributes()), + updateStatement.setBinaryStream(15, new ByteArrayInputStream(policy.getCustomAttributes()), lengthOfStream); + if (!StringUtils.isBlank(policy.getPolicyName()) && policy.getTenantId() != -1) { + updateStatement.setString(16, policy.getMonetizationPlan()); + updateStatement.setString(17, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); + updateStatement.setString(18, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); + updateStatement.setString(19, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); + updateStatement.setString(20, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); + updateStatement.setInt(21, policy.getSubscriberCount()); + updateStatement.setString(22, policy.getPolicyName()); + updateStatement.setInt(23, policy.getTenantId()); + } else if (!StringUtils.isBlank(policy.getUUID())) { + updateStatement.setString(16, policy.getMonetizationPlan()); + updateStatement.setString(17, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); + updateStatement.setString(18, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); + updateStatement.setString(19, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); + updateStatement.setString(20, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); + updateStatement.setInt(21, policy.getSubscriberCount()); + updateStatement.setString(22, policy.getUUID()); + } + } else { if (!StringUtils.isBlank(policy.getPolicyName()) && policy.getTenantId() != -1) { updateStatement.setString(15, policy.getMonetizationPlan()); updateStatement.setString(16, @@ -13154,6 +13218,7 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage updateStatement.setInt(20, policy.getSubscriberCount()); updateStatement.setString(21, policy.getPolicyName()); updateStatement.setInt(22, policy.getTenantId()); + } else if (!StringUtils.isBlank(policy.getUUID())) { updateStatement.setString(15, policy.getMonetizationPlan()); updateStatement.setString(16, @@ -13167,34 +13232,6 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage updateStatement.setInt(20, policy.getSubscriberCount()); updateStatement.setString(21, policy.getUUID()); } - } else { - if (!StringUtils.isBlank(policy.getPolicyName()) && policy.getTenantId() != -1) { - updateStatement.setString(14, policy.getMonetizationPlan()); - updateStatement.setString(15, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); - updateStatement.setString(16, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); - updateStatement.setString(17, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); - updateStatement.setString(18, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); - updateStatement.setInt(19, policy.getSubscriberCount()); - updateStatement.setString(20, policy.getPolicyName()); - updateStatement.setInt(21, policy.getTenantId()); - - } else if (!StringUtils.isBlank(policy.getUUID())) { - updateStatement.setString(14, policy.getMonetizationPlan()); - updateStatement.setString(15, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); - updateStatement.setString(16, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); - updateStatement.setString(17, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); - updateStatement.setString(18, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); - updateStatement.setInt(19, policy.getSubscriberCount()); - updateStatement.setString(20, policy.getUUID()); - } } updateStatement.executeUpdate(); connection.commit(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index 6afaa9682145..2c1903551256 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -2355,16 +2355,16 @@ public class SQLConstants { "INSERT INTO AM_POLICY_SUBSCRIPTION (NAME, DISPLAY_NAME, TENANT_ID, DESCRIPTION, QUOTA_TYPE, QUOTA, \n" + " QUOTA_UNIT, UNIT_TIME, TIME_UNIT, IS_DEPLOYED, UUID, RATE_LIMIT_COUNT, \n" + " RATE_LIMIT_TIME_UNIT,STOP_ON_QUOTA_REACH, MAX_DEPTH, MAX_COMPLEXITY, \n" + - " BILLING_PLAN,MONETIZATION_PLAN,FIXED_RATE,BILLING_CYCLE,PRICE_PER_REQUEST,CURRENCY, CONNECTIONS_COUNT) \n" + - " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + " BILLING_PLAN,ALLOWED_ORGANIZATIONS,MONETIZATION_PLAN,FIXED_RATE,BILLING_CYCLE,PRICE_PER_REQUEST,CURRENCY, CONNECTIONS_COUNT) \n" + + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; public static final String INSERT_SUBSCRIPTION_POLICY_WITH_CUSTOM_ATTRIB_SQL = "INSERT INTO AM_POLICY_SUBSCRIPTION (NAME, DISPLAY_NAME, TENANT_ID, DESCRIPTION, QUOTA_TYPE, QUOTA, \n" + " QUOTA_UNIT, UNIT_TIME, TIME_UNIT, IS_DEPLOYED, UUID, RATE_LIMIT_COUNT, \n" + - " RATE_LIMIT_TIME_UNIT, STOP_ON_QUOTA_REACH, MAX_DEPTH, MAX_COMPLEXITY, \n" + - " BILLING_PLAN, CUSTOM_ATTRIBUTES, MONETIZATION_PLAN, \n" + + " RATE_LIMIT_TIME_UNIT, STOP_ON_QUOTA_REACH, MAX_DEPTH, MAX_COMPLEXITY,\n" + + " BILLING_PLAN, ALLOWED_ORGANIZATIONS, CUSTOM_ATTRIBUTES, MONETIZATION_PLAN, \n" + " FIXED_RATE, BILLING_CYCLE, PRICE_PER_REQUEST, CURRENCY, CONNECTIONS_COUNT) \n" + - " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; public static final String INSERT_GLOBAL_POLICY_SQL = @@ -2580,6 +2580,7 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, " + + "ALLOWED_ORGANIZATIONS = ?, " + "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + "BILLING_CYCLE = ?," + @@ -2604,6 +2605,7 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, "+ + "ALLOWED_ORGANIZATIONS = ?, " + "CUSTOM_ATTRIBUTES = ?, "+ "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + @@ -2629,6 +2631,7 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, "+ + "ALLOWED_ORGANIZATIONS = ?, " + "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + "BILLING_CYCLE = ?," + @@ -2653,6 +2656,7 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, "+ + "ALLOWED_ORGANIZATIONS = ?, " + "CUSTOM_ATTRIBUTES = ?, "+ "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 8d18c7c9f486..01d44180af52 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -10559,4 +10559,21 @@ public static List getPaginatedApplicationList( } return applications.subList(offset, endIndex); } + + public static Set getAllowedTiersForTheOrganization(Set tiers, String organization, + String superOrganization) throws APIManagementException { + int tenantId = APIUtil.getInternalIdFromTenantDomainOrOrganization(superOrganization); + SubscriptionPolicy[] policies = ApiMgtDAO.getInstance().getSubscriptionPolicies(tenantId); + Set allowedTiers = new HashSet(); + for (Tier tier : tiers) { + for (SubscriptionPolicy policy : policies) { + if (policy.getPolicyName().equals(tier.getName()) + && (policy.getAllowedOrganizations().contains(APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT) + || policy.getAllowedOrganizations().contains(organization))) { + allowedTiers.add(tier); + } + } + } + return allowedTiers; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java index d53f65d7e0c0..61ca35a6af83 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java @@ -35,6 +35,7 @@ public class SubscriptionThrottlePolicyAllOfDTO { private Boolean stopOnQuotaReach = false; private String billingPlan = null; private SubscriptionThrottlePolicyPermissionDTO permissions = null; + private List allowedOrganizations = new ArrayList(); /** **/ @@ -200,6 +201,23 @@ public void setPermissions(SubscriptionThrottlePolicyPermissionDTO permissions) this.permissions = permissions; } + /** + **/ + public SubscriptionThrottlePolicyAllOfDTO allowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("allowedOrganizations") + public List getAllowedOrganizations() { + return allowedOrganizations; + } + public void setAllowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + } + @Override public boolean equals(java.lang.Object o) { @@ -218,12 +236,13 @@ public boolean equals(java.lang.Object o) { Objects.equals(customAttributes, subscriptionThrottlePolicyAllOf.customAttributes) && Objects.equals(stopOnQuotaReach, subscriptionThrottlePolicyAllOf.stopOnQuotaReach) && Objects.equals(billingPlan, subscriptionThrottlePolicyAllOf.billingPlan) && - Objects.equals(permissions, subscriptionThrottlePolicyAllOf.permissions); + Objects.equals(permissions, subscriptionThrottlePolicyAllOf.permissions) && + Objects.equals(allowedOrganizations, subscriptionThrottlePolicyAllOf.allowedOrganizations); } @Override public int hashCode() { - return Objects.hash(defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions); + return Objects.hash(defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions, allowedOrganizations); } @Override @@ -240,6 +259,7 @@ public String toString() { sb.append(" stopOnQuotaReach: ").append(toIndentedString(stopOnQuotaReach)).append("\n"); sb.append(" billingPlan: ").append(toIndentedString(billingPlan)).append("\n"); sb.append(" permissions: ").append(toIndentedString(permissions)).append("\n"); + sb.append(" allowedOrganizations: ").append(toIndentedString(allowedOrganizations)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java index 24a1552cf6c0..3bd7155a4abf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java @@ -40,6 +40,7 @@ public class SubscriptionThrottlePolicyDTO extends ThrottlePolicyDTO { private Boolean stopOnQuotaReach = false; private String billingPlan = null; private SubscriptionThrottlePolicyPermissionDTO permissions = null; + private List allowedOrganizations = new ArrayList(); /** * Maximum Complexity of the GraphQL query @@ -241,6 +242,23 @@ public void setPermissions(SubscriptionThrottlePolicyPermissionDTO permissions) this.permissions = permissions; } + /** + **/ + public SubscriptionThrottlePolicyDTO allowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("allowedOrganizations") + public List getAllowedOrganizations() { + return allowedOrganizations; + } + public void setAllowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + } + @Override public boolean equals(java.lang.Object o) { @@ -261,12 +279,13 @@ public boolean equals(java.lang.Object o) { Objects.equals(customAttributes, subscriptionThrottlePolicy.customAttributes) && Objects.equals(stopOnQuotaReach, subscriptionThrottlePolicy.stopOnQuotaReach) && Objects.equals(billingPlan, subscriptionThrottlePolicy.billingPlan) && - Objects.equals(permissions, subscriptionThrottlePolicy.permissions); + Objects.equals(permissions, subscriptionThrottlePolicy.permissions) && + Objects.equals(allowedOrganizations, subscriptionThrottlePolicy.allowedOrganizations); } @Override public int hashCode() { - return Objects.hash(graphQLMaxComplexity, graphQLMaxDepth, defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions); + return Objects.hash(graphQLMaxComplexity, graphQLMaxDepth, defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions, allowedOrganizations); } @Override @@ -285,6 +304,7 @@ public String toString() { sb.append(" stopOnQuotaReach: ").append(toIndentedString(stopOnQuotaReach)).append("\n"); sb.append(" billingPlan: ").append(toIndentedString(billingPlan)).append("\n"); sb.append(" permissions: ").append(toIndentedString(permissions)).append("\n"); + sb.append(" allowedOrganizations: ").append(toIndentedString(allowedOrganizations)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java index 2a568abd9e42..275fc58ad7f7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java @@ -88,6 +88,7 @@ public static SubscriptionThrottlePolicyDTO fromSubscriptionThrottlePolicyToDTO( policyDTO.setGraphQLMaxComplexity(subscriptionPolicy.getGraphQLMaxComplexity()); policyDTO.setGraphQLMaxDepth(subscriptionPolicy.getGraphQLMaxDepth()); policyDTO.setSubscriberCount(subscriptionPolicy.getSubscriberCount()); + policyDTO.setAllowedOrganizations(subscriptionPolicy.getAllowedOrganizations()); byte[] customAttributes = subscriptionPolicy.getCustomAttributes(); if (customAttributes != null) { @@ -142,6 +143,7 @@ public static SubscriptionPolicy fromSubscriptionThrottlePolicyDTOToModel(Subscr subscriptionPolicy.setRateLimitCount(dto.getRateLimitCount()); subscriptionPolicy.setSubscriberCount(dto.getSubscriberCount()); subscriptionPolicy.setStopOnQuotaReach(dto.isStopOnQuotaReach()); + subscriptionPolicy.setAllowedOrganizations(dto.getAllowedOrganizations()); if (dto.getGraphQLMaxComplexity() != null) { subscriptionPolicy.setGraphQLMaxComplexity(dto.getGraphQLMaxComplexity()); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml index 8dff2ebf0c29..bf2ac5538c2c 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml @@ -3858,6 +3858,10 @@ components: example: FREE permissions: $ref: '#/components/schemas/SubscriptionThrottlePolicyPermission' + allowedOrganizations: + type: array + items: + type: string SubscriptionThrottlePolicyPermission: title: SubscriptionThrottlePolicyPermission required: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index ce31ba4b4b35..ed759b418070 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -147,8 +147,10 @@ public Response apisGet(Integer limit, Integer offset, String xWSO2Tenant, Strin @Override public Response apisApiIdGet(String apiId, String xWSO2Tenant, String ifNoneMatch, MessageContext messageContext) throws APIManagementException { - String organization = RestApiUtil.getValidatedOrganization(messageContext); - return Response.ok().entity(getAPIByAPIId(apiId, organization)).build(); + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); + userOrgInfo.setSuperOrganization(superOrganization); + return Response.ok().entity(getAPIByAPIId(apiId, superOrganization, userOrgInfo)).build(); } @@ -801,8 +803,10 @@ public Response apisApiIdSdksLanguageGet(String apiId, String language, String x String message = "Error generating the SDK. API id or language should not be empty"; RestApiUtil.handleBadRequest(message, log); } - String organization = RestApiUtil.getValidatedOrganization(messageContext); - APIDTO api = getAPIByAPIId(apiId, organization); + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); + userOrgInfo.setSuperOrganization(superOrganization); + APIDTO api = getAPIByAPIId(apiId, superOrganization, userOrgInfo); APIClientGenerationManager apiClientGenerationManager = new APIClientGenerationManager(); Map sdkArtifacts; String swaggerDefinition = api.getApiDefinition(); @@ -1135,10 +1139,12 @@ public Response getWSDLOfAPI(String apiId, String environmentName, String ifNone @Override public Response apisApiIdSubscriptionPoliciesGet(String apiId, String xWSO2Tenant, String ifNoneMatch, MessageContext messageContext) throws APIManagementException { - String organization = RestApiUtil.getValidatedOrganization(messageContext); - APIDTO apiInfo = getAPIByAPIId(apiId, organization); + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); + userOrgInfo.setSuperOrganization(superOrganization); + APIDTO apiInfo = getAPIByAPIId(apiId, superOrganization, userOrgInfo); List availableThrottlingPolicyList = new ThrottlingPoliciesApiServiceImpl() - .getThrottlingPolicyList(ThrottlingPolicyDTO.PolicyLevelEnum.SUBSCRIPTION.toString(), organization); + .getThrottlingPolicyList(ThrottlingPolicyDTO.PolicyLevelEnum.SUBSCRIPTION.toString(), superOrganization); if (apiInfo != null ) { List apiTiers = apiInfo.getTiers(); @@ -1157,7 +1163,7 @@ public Response apisApiIdSubscriptionPoliciesGet(String apiId, String xWSO2Tenan return null; } - private APIDTO getAPIByAPIId(String apiId, String organization) { + private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo userOrgInfo) { try { APIConsumer apiConsumer = RestApiCommonUtil.getLoggedInUserConsumer(); ApiTypeWrapper api = apiConsumer.getAPIorAPIProductByUUID(apiId, organization); @@ -1169,6 +1175,13 @@ private APIDTO getAPIByAPIId(String apiId, String organization) { if (APIConstants.PUBLISHED.equals(status) || APIConstants.PROTOTYPED.equals(status) || APIConstants.DEPRECATED.equals(status)) { + if (!api.isAPIProduct()) { + // Add only organization specific tiers + Set tiers = APIUtil.getAllowedTiersForTheOrganization(api.getApi().getAvailableTiers(), + userOrgInfo.getName(), userOrgInfo.getSuperOrganization()); + api.getApi().removeAllTiers(); + api.getApi().setAvailableTiers(tiers); + } APIDTO apidto = APIMappingUtil.fromAPItoDTO(api, organization); long subscriptionCountOfAPI = apiConsumer.getSubscriptionCountOfAPI(apiId, organization); diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index 4687988fc523..5b4cb0873713 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -1855,6 +1855,7 @@ CREATE TABLE IF NOT EXISTS AM_POLICY_SUBSCRIPTION ( MAX_COMPLEXITY INT NOT NULL DEFAULT 0, MAX_DEPTH INT NOT NULL DEFAULT 0, CONNECTIONS_COUNT INT NOT NULL DEFAULT 0, + ALLOWED_ORGANIZATIONS VARCHAR(1024) NULL DEFAULT NULL, PRIMARY KEY (POLICY_ID), UNIQUE (UUID) ); diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql index 71cbc6bd6267..ce7f356ade7f 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql @@ -1797,6 +1797,7 @@ CREATE TABLE IF NOT EXISTS AM_POLICY_SUBSCRIPTION ( MAX_COMPLEXITY INT(11) NOT NULL DEFAULT 0, MAX_DEPTH INT(11) NOT NULL DEFAULT 0, CONNECTIONS_COUNT INT(11) NOT NULL DEFAULT 0, + ALLOWED_ORGANIZATIONS VARCHAR(1024) NULL DEFAULT NULL, PRIMARY KEY (POLICY_ID), UNIQUE INDEX AM_POLICY_SUBSCRIPTION_NAME_TENANT (NAME, TENANT_ID), UNIQUE (UUID) From 364cec902401e2c349704e8280ab83e8b965161e Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 29 Aug 2024 11:55:13 +0530 Subject: [PATCH 09/74] Fix admin dev portal api loading issue --- .../apimgt/persistence/RegistryPersistenceImpl.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index a55f0e4a4f22..a09a4311f670 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1127,13 +1127,19 @@ private List searchDevportalAPIs(String query, int tenantId, fields.remove("overview_visible_organizations"); String filterQuery = RegistryPersistenceUtil.buildFQStringForProperties(query); String modifiedQuery = "q=* TO *&" + filterQuery; - + try { PaginationContext.init(start, offset, "ASC", APIConstants.API_OVERVIEW_NAME, getMaxPaginationLimit()); UserRegistry systemUserRegistry = ServiceReferenceHolder.getInstance().getRegistryService() .getRegistry(CarbonConstants.REGISTRY_SYSTEM_USERNAME, tenantId); ContentBasedSearchService contentBasedSearchService = new ContentBasedSearchService(); - SearchResultsBean resultsBean = contentBasedSearchService.searchByAttribute(modifiedQuery, fields, systemUserRegistry); + SearchResultsBean resultsBean; + if(StringUtils.isEmpty(filterQuery)) { + resultsBean = contentBasedSearchService.searchByAttribute(fields, systemUserRegistry); + } else { + resultsBean = contentBasedSearchService.searchByAttribute(modifiedQuery, fields, systemUserRegistry); + } + if (log.isDebugEnabled()) { log.debug("Search Result: " + resultsBean); } From ba78056fbf34015404aee597f3ffb52c45d6fbc6 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 29 Aug 2024 13:19:52 +0530 Subject: [PATCH 10/74] Add indexed document modification logic --- .../apimgt/impl/AMIndexerPreprocessor.java | 47 +++++++++++++++++++ .../impl/internal/APIManagerComponent.java | 3 ++ 2 files changed, 50 insertions(+) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java new file mode 100644 index 000000000000..3eec76ec1592 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.apimgt.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.registry.core.Resource; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.indexing.indexer.IndexerPreProcessor; + +public class AMIndexerPreprocessor implements IndexerPreProcessor { + + private static final Log log = LogFactory.getLog(AMIndexerPreprocessor.class); + + @Override + public void processResource(Resource resource) throws RegistryException { + if (APIConstants.API_RXT_MEDIA_TYPE.equals(resource.getMediaType())) { + if (log.isDebugEnabled()) { + log.debug("Analyzing API in " + resource.getPath()); + } + if (!resource.getProperties().isEmpty() && !resource.getProperties().contains("visible_organizations")) { + if (log.isDebugEnabled()) { + log.debug("Update property for the resource in " + resource.getPath()); + } + resource.setProperty("visible_organizations", "all"); + } + } + + } + +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/internal/APIManagerComponent.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/internal/APIManagerComponent.java index c2094d7d88af..6a3c9cdbe87c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/internal/APIManagerComponent.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/internal/APIManagerComponent.java @@ -47,6 +47,7 @@ import org.wso2.carbon.apimgt.common.gateway.jwttransformer.JWTTransformer; import org.wso2.carbon.apimgt.eventing.EventPublisherException; import org.wso2.carbon.apimgt.eventing.EventPublisherFactory; +import org.wso2.carbon.apimgt.impl.AMIndexerPreprocessor; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.APIManagerAnalyticsConfiguration; import org.wso2.carbon.apimgt.impl.APIManagerConfiguration; @@ -122,6 +123,7 @@ import org.wso2.carbon.registry.core.session.UserRegistry; import org.wso2.carbon.registry.core.utils.AuthorizationUtils; import org.wso2.carbon.registry.core.utils.RegistryUtils; +import org.wso2.carbon.registry.indexing.indexer.IndexerPreProcessor; import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; import org.wso2.carbon.user.api.AuthorizationManager; import org.wso2.carbon.user.api.UserStoreException; @@ -216,6 +218,7 @@ protected void activate(ComponentContext componentContext) throws Exception { bundleContext.registerService(Notifier.class.getName(),new KeyTemplateNotifier(), null); bundleContext.registerService(Notifier.class.getName(), new CorrelationConfigNotifier(), null); bundleContext.registerService(Notifier.class.getName(), new GatewayPolicyNotifier(), null); + bundleContext.registerService(IndexerPreProcessor.class.getName(), new AMIndexerPreprocessor(), null); if (configuration.getMarketplaceAssistantConfigurationDto().isAuthTokenProvided()) { bundleContext.registerService(Notifier.class.getName(), new MarketplaceAssistantApiPublisherNotifier(), null); } From 78bb1e7f8d7f3e47fb0c3ee55f67bccf4278ade3 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 5 Sep 2024 12:08:00 +0530 Subject: [PATCH 11/74] Fix bug --- .../org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java index 3eec76ec1592..408094d05719 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/AMIndexerPreprocessor.java @@ -34,14 +34,13 @@ public void processResource(Resource resource) throws RegistryException { if (log.isDebugEnabled()) { log.debug("Analyzing API in " + resource.getPath()); } - if (!resource.getProperties().isEmpty() && !resource.getProperties().contains("visible_organizations")) { + if (!resource.getProperties().isEmpty() && (resource.getProperties().get("visible_organizations") == null)) { if (log.isDebugEnabled()) { log.debug("Update property for the resource in " + resource.getPath()); } resource.setProperty("visible_organizations", "all"); } } - } } From 66ba661c671cc592f21b848ceca2409a67bd9e91 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 12 Sep 2024 12:49:40 +0530 Subject: [PATCH 12/74] Fix multiple status display issue --- .../carbon/apimgt/persistence/RegistryPersistenceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index a09a4311f670..789cf0edf3a6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1120,7 +1120,8 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String private List searchDevportalAPIs(String query, int tenantId, Registry reg, int start, int offset) throws APIManagementException { List artifacts = new ArrayList(); - query = query.replace("PUBLISHED", "published").replace("PROTOTYPED", "prototyped");// convert to lowercase + query = query.replace("PUBLISHED", "published").replace("PROTOTYPED", "prototyped").replace("DEPRECATED", + "deprecated");// convert to lowercase Map fields = RegistryPersistenceUtil.getFields(query); //since store_view_roles and overview_visible_organizations are passed as property search value, remove this. fields.remove("overview_store_view_roles"); From 1fa232f1ed772e8e637a47b91c5dee10922feed2 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 12 Sep 2024 12:50:01 +0530 Subject: [PATCH 13/74] Fix shared application view issue --- .../rest/api/store/v1/impl/ApplicationsApiServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index e2968fd67bda..f5ea01076981 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -407,6 +407,7 @@ public Response applicationsApplicationIdGet(String applicationId, String ifNone String username = RestApiCommonUtil.getLoggedInUsername(); try { String organization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); Application application = apiConsumer.getApplicationByUUID(applicationId, organization); if (application != null) { @@ -431,7 +432,8 @@ public Response applicationsApplicationIdGet(String applicationId, String ifNone } } application.setApplicationAttributes(applicationAttributes); - if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application)) { + if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) || (orgInfo.getName() != null + && orgInfo.getName().equals(application.getSharedOrganization()))) { ApplicationDTO applicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(application); applicationDTO.setHashEnabled(OAuthServerConfiguration.getInstance().isClientSecretHashEnabled()); Set scopes = apiConsumer From e28bc64a3a7dee5526eb6c2f7f6f47d5bd588e3d Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 18 Sep 2024 17:25:06 +0530 Subject: [PATCH 14/74] Introduce config to enable org related visibility --- .../wso2/carbon/apimgt/impl/APIConstants.java | 5 +++ .../apimgt/impl/APIManagerConfiguration.java | 21 +++++++++ .../apimgt/impl/dto/OrgAccessControl.java | 43 +++++++++++++++++++ .../carbon/apimgt/impl/utils/APIUtil.java | 9 ++++ .../rest/api/admin/v1/dto/SettingsDTO.java | 23 +++++++++- .../utils/mappings/SettingsMappingUtil.java | 1 + .../src/main/resources/admin-api.yaml | 5 +++ .../src/main/resources/admin-api.yaml | 9 ++++ .../src/main/resources/devportal-api.yaml | 10 +++++ .../src/main/resources/publisher-api.yaml | 34 +++++++++++++-- .../api/publisher/v1/dto/SettingsDTO.java | 23 +++++++++- .../common/mappings/SettingsMappingUtil.java | 1 + .../rest/api/store/v1/dto/SettingsDTO.java | 23 +++++++++- .../v1/mappings/SettingsMappingUtil.java | 1 + .../src/main/resources/devportal-api.yaml | 5 +++ .../repository/conf/api-manager.xml.j2 | 8 ++++ 16 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index 264940e57bcb..fae6def4e4a4 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -1962,6 +1962,7 @@ public enum RegistryResourceTypesForUI { public static final String BILLING_PLAN_FREE = "FREE"; public static final String ALLOWED_ORGANIZATIONS_DEFAULT = "ALL"; + public static final String DEFAULT_VISIBLE_ORG = "all"; public static final String POLICY_RESET = "reset"; public static final String BLOCKING_EVENT_TYPE = "wso2event"; @@ -3177,4 +3178,8 @@ public static class TokenValidationConstants { public static final String TOKEN_VALIDATION_CONFIG = "TokenValidation"; public static final String ENFORCE_JWT_TYPE_HEADER_VALIDATION = "EnforceTypeHeaderValidation"; } + + // For Organization access control Configuration + public static final String ORG_BASED_ACCESS_CONTROL = "OrganizationBasedAccessControl"; + public static final String ORG_BASED_ACCESS_CONTROL_ENABLE = "Enable"; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java index 1923ad13344a..73c01a2826f6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java @@ -44,6 +44,7 @@ import org.wso2.carbon.apimgt.impl.dto.ExtendedJWTConfigurationDto; import org.wso2.carbon.apimgt.impl.dto.GatewayArtifactSynchronizerProperties; import org.wso2.carbon.apimgt.impl.dto.GatewayCleanupSkipList; +import org.wso2.carbon.apimgt.impl.dto.OrgAccessControl; import org.wso2.carbon.apimgt.impl.dto.RedisConfig; import org.wso2.carbon.apimgt.impl.dto.ThrottleProperties; import org.wso2.carbon.apimgt.impl.dto.TokenValidationDto; @@ -131,6 +132,15 @@ public class APIManagerConfiguration { private static String certificateBoundAccessEnabled; private GatewayCleanupSkipList gatewayCleanupSkipList = new GatewayCleanupSkipList(); private RedisConfig redisConfig = new RedisConfig(); + private OrgAccessControl orgAccessControl = new OrgAccessControl(); + public OrgAccessControl getOrgAccessControl() { + return orgAccessControl; + } + + public void setOrgAccessControl(OrgAccessControl orgAccessControl) { + this.orgAccessControl = orgAccessControl; + } + private Map> restApiJWTAuthAudiences = new HashMap<>(); private JSONObject subscriberAttributes = new JSONObject(); private static Map analyticsMaskProps; @@ -660,12 +670,23 @@ private void readChildElements(OMElement serverConfig, setApiChatConfiguration(element); } else if (APIConstants.TokenValidationConstants.TOKEN_VALIDATION_CONFIG.equals(localName)) { setTokenValidation(element); + } else if (APIConstants.ORG_BASED_ACCESS_CONTROL.equals(localName)) { + setOrgBasedAccessControlConfigs(element); } readChildElements(element, nameStack); nameStack.pop(); } } + private void setOrgBasedAccessControlConfigs(OMElement element) { + OMElement orgEnableElement = + element.getFirstChildWithName(new QName(APIConstants.ORG_BASED_ACCESS_CONTROL_ENABLE)); + if (orgEnableElement != null) { + orgAccessControl.setEnabled(Boolean.parseBoolean(orgEnableElement.getText())); + } + + } + public JSONObject getSubscriberAttributes() { return subscriberAttributes; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java new file mode 100644 index 000000000000..313db3d57c1f --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.apimgt.impl.dto; + +public class OrgAccessControl { + private boolean isEnabled; + private String orgNameLocalClaim; + private String orgIdLocalClaim; + public boolean isEnabled() { + return isEnabled; + } + public void setEnabled(boolean isEnabled) { + this.isEnabled = isEnabled; + } + public String getOrgNameLocalClaim() { + return orgNameLocalClaim; + } + public void setOrgNameLocalClaim(String orgNameLocalClaim) { + this.orgNameLocalClaim = orgNameLocalClaim; + } + public String getOrgIdLocalClaim() { + return orgIdLocalClaim; + } + public void setOrgIdLocalClaim(String orgIdLocalClaim) { + this.orgIdLocalClaim = orgIdLocalClaim; + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 01d44180af52..44591fb295cf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -9863,6 +9863,15 @@ public static ExternalEnvironment getExternalEnvironment(String providerName) { return ServiceReferenceHolder.getInstance().getExternalEnvironment(providerName); } + /** + * Get org access control enabled status + * + * @return true or false + */ + public static boolean isOrganizationAccessControlEnabled() { + return ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService().getAPIManagerConfiguration() + .getOrgAccessControl().isEnabled(); + } /** * Get registered API Definition Parsers as a Map * diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SettingsDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SettingsDTO.java index 6348aa234ac4..23ad133b6b75 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SettingsDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SettingsDTO.java @@ -26,6 +26,7 @@ public class SettingsDTO { private List scopes = new ArrayList(); private List gatewayTypes = new ArrayList(); private Boolean isJWTEnabledForLoginTokens = false; + private Boolean orgAccessControlEnabled = null; private List keyManagerConfiguration = new ArrayList(); private Boolean analyticsEnabled = null; @@ -80,6 +81,24 @@ public void setIsJWTEnabledForLoginTokens(Boolean isJWTEnabledForLoginTokens) { this.isJWTEnabledForLoginTokens = isJWTEnabledForLoginTokens; } + /** + * Is Organization-based access control configuration enabled + **/ + public SettingsDTO orgAccessControlEnabled(Boolean orgAccessControlEnabled) { + this.orgAccessControlEnabled = orgAccessControlEnabled; + return this; + } + + + @ApiModelProperty(example = "true", value = "Is Organization-based access control configuration enabled ") + @JsonProperty("orgAccessControlEnabled") + public Boolean isOrgAccessControlEnabled() { + return orgAccessControlEnabled; + } + public void setOrgAccessControlEnabled(Boolean orgAccessControlEnabled) { + this.orgAccessControlEnabled = orgAccessControlEnabled; + } + /** **/ public SettingsDTO keyManagerConfiguration(List keyManagerConfiguration) { @@ -129,13 +148,14 @@ public boolean equals(java.lang.Object o) { return Objects.equals(scopes, settings.scopes) && Objects.equals(gatewayTypes, settings.gatewayTypes) && Objects.equals(isJWTEnabledForLoginTokens, settings.isJWTEnabledForLoginTokens) && + Objects.equals(orgAccessControlEnabled, settings.orgAccessControlEnabled) && Objects.equals(keyManagerConfiguration, settings.keyManagerConfiguration) && Objects.equals(analyticsEnabled, settings.analyticsEnabled); } @Override public int hashCode() { - return Objects.hash(scopes, gatewayTypes, isJWTEnabledForLoginTokens, keyManagerConfiguration, analyticsEnabled); + return Objects.hash(scopes, gatewayTypes, isJWTEnabledForLoginTokens, orgAccessControlEnabled, keyManagerConfiguration, analyticsEnabled); } @Override @@ -146,6 +166,7 @@ public String toString() { sb.append(" scopes: ").append(toIndentedString(scopes)).append("\n"); sb.append(" gatewayTypes: ").append(toIndentedString(gatewayTypes)).append("\n"); sb.append(" isJWTEnabledForLoginTokens: ").append(toIndentedString(isJWTEnabledForLoginTokens)).append("\n"); + sb.append(" orgAccessControlEnabled: ").append(toIndentedString(orgAccessControlEnabled)).append("\n"); sb.append(" keyManagerConfiguration: ").append(toIndentedString(keyManagerConfiguration)).append("\n"); sb.append(" analyticsEnabled: ").append(toIndentedString(analyticsEnabled)).append("\n"); sb.append("}"); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/SettingsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/SettingsMappingUtil.java index 99759d09ff2e..6138ef5355b3 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/SettingsMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/SettingsMappingUtil.java @@ -62,6 +62,7 @@ public SettingsDTO fromSettingsToDTO(Boolean isUserAvailable) throws APIManageme settingsDTO.setScopes(getScopeList()); settingsDTO.setGatewayTypes(APIUtil.getGatewayTypes()); settingsDTO.setIsJWTEnabledForLoginTokens(APIUtil.isJWTEnabledForPortals()); + settingsDTO.setOrgAccessControlEnabled(APIUtil.isOrganizationAccessControlEnabled()); return settingsDTO; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml index bf2ac5538c2c..ce9b2a358c7d 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml @@ -4696,6 +4696,11 @@ components: IsJWTEnabledForLoginTokens: type: boolean default: false + orgAccessControlEnabled: + type: boolean + description: | + Is Organization-based access control configuration enabled + example: true keyManagerConfiguration: type: array items: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml index 8dff2ebf0c29..ce9b2a358c7d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml @@ -3858,6 +3858,10 @@ components: example: FREE permissions: $ref: '#/components/schemas/SubscriptionThrottlePolicyPermission' + allowedOrganizations: + type: array + items: + type: string SubscriptionThrottlePolicyPermission: title: SubscriptionThrottlePolicyPermission required: @@ -4692,6 +4696,11 @@ components: IsJWTEnabledForLoginTokens: type: boolean default: false + orgAccessControlEnabled: + type: boolean + description: | + Is Organization-based access control configuration enabled + example: true keyManagerConfiguration: type: array items: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml index b99d43642ed8..71743bd3501f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/devportal-api.yaml @@ -4363,6 +4363,11 @@ components: type: string readOnly: true example: 1651555310208 + visibility: + type: string + enum: + - PRIVATE + - SHARED_WITH_ORG ApplicationInfo: title: Application info object with basic application details type: object @@ -5518,6 +5523,11 @@ components: IsJWTEnabledForLoginTokens: type: boolean default: false + orgAccessControlEnabled: + type: boolean + description: | + Is Organization-based access control configuration enabled + example: true userStorePasswordPattern: type: string description: The 'PasswordJavaRegEx' cofigured in the UserStoreManager diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index abc67c5fe731..b35339c2153b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -8167,7 +8167,7 @@ paths: x-code-samples: - lang: Curl source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" - -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 + -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 "https://127.0.0.1:9443/api/am/publisher/v4/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/operation-policies"' @@ -8411,7 +8411,7 @@ paths: x-code-samples: - lang: Curl source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" - -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F policyDefinitionFile=@setHeader.j2 + -H "Content-Type: multipart/form-data" -F policySpecFile=@setHeader.yaml -F synapsePolicyDefinitionFile=@setHeader.j2 "https://127.0.0.1:9443/api/am/publisher/v4/operation-policies"' /operation-policies/export: @@ -9365,6 +9365,12 @@ components: enum: - PUBLIC - SINGLE + audiences: + type: array + description: The audiences of the API for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] lifeCycleStatus: type: string example: CREATED @@ -9684,6 +9690,12 @@ components: enum: - PUBLIC - SINGLE + audiences: + type: array + description: The audiences of the API for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] transport: type: array description: | @@ -9754,7 +9766,6 @@ components: - PUBLIC - PRIVATE - RESTRICTED - - RESTRICTED_BY_ORG x-otherScopes: - apim:api_publish - apim:api_manage @@ -10283,6 +10294,12 @@ components: gatewayVendor: type: string example: wso2 + audiences: + type: array + description: The audiences of the API product for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] monetizedInfo: type: boolean example: true @@ -10556,6 +10573,12 @@ components: workflowStatus: type: string example: APPROVED + audiences: + type: array + description: The audiences of the API for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] ProductAPI: title: ProductAPI required: @@ -12585,6 +12608,11 @@ components: IsJWTEnabledForLoginTokens: type: boolean default: false + orgAccessControlEnabled: + type: boolean + description: | + Is Organization-based access control configuration enabled + example: true customProperties: type: array items: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/SettingsDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/SettingsDTO.java index fd6c63149aaf..fe01ef4536a7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/SettingsDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/SettingsDTO.java @@ -41,6 +41,7 @@ public class SettingsDTO { private String defaultSubscriptionPolicy = null; private String authorizationHeader = null; private Boolean isJWTEnabledForLoginTokens = false; + private Boolean orgAccessControlEnabled = null; private List customProperties = new ArrayList(); /** @@ -310,6 +311,24 @@ public void setIsJWTEnabledForLoginTokens(Boolean isJWTEnabledForLoginTokens) { this.isJWTEnabledForLoginTokens = isJWTEnabledForLoginTokens; } + /** + * Is Organization-based access control configuration enabled + **/ + public SettingsDTO orgAccessControlEnabled(Boolean orgAccessControlEnabled) { + this.orgAccessControlEnabled = orgAccessControlEnabled; + return this; + } + + + @ApiModelProperty(example = "true", value = "Is Organization-based access control configuration enabled ") + @JsonProperty("orgAccessControlEnabled") + public Boolean isOrgAccessControlEnabled() { + return orgAccessControlEnabled; + } + public void setOrgAccessControlEnabled(Boolean orgAccessControlEnabled) { + this.orgAccessControlEnabled = orgAccessControlEnabled; + } + /** **/ public SettingsDTO customProperties(List customProperties) { @@ -353,12 +372,13 @@ public boolean equals(java.lang.Object o) { Objects.equals(defaultSubscriptionPolicy, settings.defaultSubscriptionPolicy) && Objects.equals(authorizationHeader, settings.authorizationHeader) && Objects.equals(isJWTEnabledForLoginTokens, settings.isJWTEnabledForLoginTokens) && + Objects.equals(orgAccessControlEnabled, settings.orgAccessControlEnabled) && Objects.equals(customProperties, settings.customProperties); } @Override public int hashCode() { - return Objects.hash(devportalUrl, environment, gatewayTypes, scopes, monetizationAttributes, subscriberContactAttributes, securityAuditProperties, externalStoresEnabled, docVisibilityEnabled, portalConfigurationOnlyModeEnabled, crossTenantSubscriptionEnabled, defaultAdvancePolicy, defaultSubscriptionPolicy, authorizationHeader, isJWTEnabledForLoginTokens, customProperties); + return Objects.hash(devportalUrl, environment, gatewayTypes, scopes, monetizationAttributes, subscriberContactAttributes, securityAuditProperties, externalStoresEnabled, docVisibilityEnabled, portalConfigurationOnlyModeEnabled, crossTenantSubscriptionEnabled, defaultAdvancePolicy, defaultSubscriptionPolicy, authorizationHeader, isJWTEnabledForLoginTokens, orgAccessControlEnabled, customProperties); } @Override @@ -381,6 +401,7 @@ public String toString() { sb.append(" defaultSubscriptionPolicy: ").append(toIndentedString(defaultSubscriptionPolicy)).append("\n"); sb.append(" authorizationHeader: ").append(toIndentedString(authorizationHeader)).append("\n"); sb.append(" isJWTEnabledForLoginTokens: ").append(toIndentedString(isJWTEnabledForLoginTokens)).append("\n"); + sb.append(" orgAccessControlEnabled: ").append(toIndentedString(orgAccessControlEnabled)).append("\n"); sb.append(" customProperties: ").append(toIndentedString(customProperties)).append("\n"); sb.append("}"); return sb.toString(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/SettingsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/SettingsMappingUtil.java index 87156e0d8958..5d73f1fd4a34 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/SettingsMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/SettingsMappingUtil.java @@ -87,6 +87,7 @@ public SettingsDTO fromSettingstoDTO(Boolean isUserAvailable, String organizatio settingsDTO.setExternalStoresEnabled( APIUtil.isExternalStoresEnabled(RestApiCommonUtil.getLoggedInUserTenantDomain())); settingsDTO.setDocVisibilityEnabled(APIUtil.isDocVisibilityLevelsEnabled()); + settingsDTO.setOrgAccessControlEnabled(APIUtil.isOrganizationAccessControlEnabled()); settingsDTO.setPortalConfigurationOnlyModeEnabled(APIUtil.isPortalConfigurationOnlyModeEnabled()); settingsDTO.setCrossTenantSubscriptionEnabled(APIUtil.isCrossTenantSubscriptionsEnabled()); Map gatewayEnvironments = APIUtil.getReadOnlyGatewayEnvironments(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/SettingsDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/SettingsDTO.java index 2c96c6462d5e..839382967d6f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/SettingsDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/store/v1/dto/SettingsDTO.java @@ -35,6 +35,7 @@ public class SettingsDTO { private Boolean isAnonymousModeEnabled = true; private Boolean isPasswordChangeEnabled = true; private Boolean isJWTEnabledForLoginTokens = false; + private Boolean orgAccessControlEnabled = null; private String userStorePasswordPattern = null; private String passwordPolicyPattern = null; private Integer passwordPolicyMinLength = null; @@ -248,6 +249,24 @@ public void setIsJWTEnabledForLoginTokens(Boolean isJWTEnabledForLoginTokens) { this.isJWTEnabledForLoginTokens = isJWTEnabledForLoginTokens; } + /** + * Is Organization-based access control configuration enabled + **/ + public SettingsDTO orgAccessControlEnabled(Boolean orgAccessControlEnabled) { + this.orgAccessControlEnabled = orgAccessControlEnabled; + return this; + } + + + @ApiModelProperty(example = "true", value = "Is Organization-based access control configuration enabled ") + @JsonProperty("orgAccessControlEnabled") + public Boolean isOrgAccessControlEnabled() { + return orgAccessControlEnabled; + } + public void setOrgAccessControlEnabled(Boolean orgAccessControlEnabled) { + this.orgAccessControlEnabled = orgAccessControlEnabled; + } + /** * The 'PasswordJavaRegEx' cofigured in the UserStoreManager **/ @@ -396,6 +415,7 @@ public boolean equals(java.lang.Object o) { Objects.equals(isAnonymousModeEnabled, settings.isAnonymousModeEnabled) && Objects.equals(isPasswordChangeEnabled, settings.isPasswordChangeEnabled) && Objects.equals(isJWTEnabledForLoginTokens, settings.isJWTEnabledForLoginTokens) && + Objects.equals(orgAccessControlEnabled, settings.orgAccessControlEnabled) && Objects.equals(userStorePasswordPattern, settings.userStorePasswordPattern) && Objects.equals(passwordPolicyPattern, settings.passwordPolicyPattern) && Objects.equals(passwordPolicyMinLength, settings.passwordPolicyMinLength) && @@ -407,7 +427,7 @@ public boolean equals(java.lang.Object o) { @Override public int hashCode() { - return Objects.hash(grantTypes, scopes, applicationSharingEnabled, mapExistingAuthApps, apiGatewayEndpoint, monetizationEnabled, recommendationEnabled, isUnlimitedTierPaid, identityProvider, isAnonymousModeEnabled, isPasswordChangeEnabled, isJWTEnabledForLoginTokens, userStorePasswordPattern, passwordPolicyPattern, passwordPolicyMinLength, passwordPolicyMaxLength, apiChatEnabled, aiAuthTokenProvided, marketplaceAssistantEnabled); + return Objects.hash(grantTypes, scopes, applicationSharingEnabled, mapExistingAuthApps, apiGatewayEndpoint, monetizationEnabled, recommendationEnabled, isUnlimitedTierPaid, identityProvider, isAnonymousModeEnabled, isPasswordChangeEnabled, isJWTEnabledForLoginTokens, orgAccessControlEnabled, userStorePasswordPattern, passwordPolicyPattern, passwordPolicyMinLength, passwordPolicyMaxLength, apiChatEnabled, aiAuthTokenProvided, marketplaceAssistantEnabled); } @Override @@ -427,6 +447,7 @@ public String toString() { sb.append(" isAnonymousModeEnabled: ").append(toIndentedString(isAnonymousModeEnabled)).append("\n"); sb.append(" isPasswordChangeEnabled: ").append(toIndentedString(isPasswordChangeEnabled)).append("\n"); sb.append(" isJWTEnabledForLoginTokens: ").append(toIndentedString(isJWTEnabledForLoginTokens)).append("\n"); + sb.append(" orgAccessControlEnabled: ").append(toIndentedString(orgAccessControlEnabled)).append("\n"); sb.append(" userStorePasswordPattern: ").append(toIndentedString(userStorePasswordPattern)).append("\n"); sb.append(" passwordPolicyPattern: ").append(toIndentedString(passwordPolicyPattern)).append("\n"); sb.append(" passwordPolicyMinLength: ").append(toIndentedString(passwordPolicyMinLength)).append("\n"); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/SettingsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/SettingsMappingUtil.java index 4ff6c05a0f6a..dd909db0e0f1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/SettingsMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/SettingsMappingUtil.java @@ -68,6 +68,7 @@ public SettingsDTO fromSettingstoDTO(Boolean isUserAvailable, Boolean moneatizat identityProviderDTO.setExternal(APIUtil.getIdentityProviderConfig() != null); settingsDTO.setIdentityProvider(identityProviderDTO); settingsDTO.setIsAnonymousModeEnabled(anonymousEnabled); + settingsDTO.setOrgAccessControlEnabled(APIUtil.isOrganizationAccessControlEnabled()); APIManagerConfiguration config = ServiceReferenceHolder.getInstance(). getAPIManagerConfigurationService().getAPIManagerConfiguration(); boolean enableChangePassword = diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml index 296ce294b71d..71743bd3501f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/resources/devportal-api.yaml @@ -5523,6 +5523,11 @@ components: IsJWTEnabledForLoginTokens: type: boolean default: false + orgAccessControlEnabled: + type: boolean + description: | + Is Organization-based access control configuration enabled + example: true userStorePasswordPattern: type: string description: The 'PasswordJavaRegEx' cofigured in the UserStoreManager diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 index 1607b483efbc..dfcfda46d296 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 @@ -103,6 +103,14 @@ + {% if apim.organization_based_access_control is defined %} + + {{apim.organization_based_access_control.enable}} + {{apim.organization_based_access_control.organization_name_local_claim}} + {{apim.organization_based_access_control.organization_id_local_claim}} + + {% endif %} + From e1f97f1af36f082d36ce0bcd75729b9fa63b005a Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 18 Sep 2024 17:26:15 +0530 Subject: [PATCH 15/74] Add dev portal org visibility to seperate section --- .../rest/api/publisher/v1/dto/APIDTO.java | 3 +-- .../v1/common/mappings/APIMappingUtil.java | 17 +++++++---------- .../common/mappings/PublisherCommonUtils.java | 8 -------- .../src/main/resources/publisher-api.yaml | 6 +++++- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java index bb7f4eae3552..eae4bd5576d6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java @@ -154,8 +154,7 @@ public static AudienceEnum fromValue(String v) { public enum VisibilityEnum { PUBLIC("PUBLIC"), PRIVATE("PRIVATE"), - RESTRICTED("RESTRICTED"), - RESTRICTED_BY_ORG("RESTRICTED_BY_ORG"); + RESTRICTED("RESTRICTED"); private String value; VisibilityEnum (String v) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java index 206bf4e1b053..1d0d394bce7b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java @@ -317,13 +317,11 @@ public static API fromDTOtoAPI(APIDTO dto, String provider) throws APIManagement } } - if (dto.getVisibleOrganizations() != null) { + if (dto.getVisibleOrganizations() != null && !dto.getVisibleOrganizations().isEmpty()) { String visibleOrgs = StringUtils.join(dto.getVisibleOrganizations(), ','); model.setVisibleOrganizations(visibleOrgs); -// check if need to have a config -// if (APIUtil.isCrossTenantSubscriptionsEnabled()) { -// -// } + } else { + model.setVisibleOrganizations(APIConstants.DEFAULT_VISIBLE_ORG); } List accessControlRoles = dto.getAccessControlRoles(); @@ -943,8 +941,6 @@ private static String mapVisibilityFromDTOtoAPI(APIDTO.VisibilityEnum visibility return APIConstants.API_PRIVATE_VISIBILITY; case RESTRICTED: return APIConstants.API_RESTRICTED_VISIBILITY; - case RESTRICTED_BY_ORG: - return APIConstants.API_RESTRICTED_BY_ORG; // case CONTROLLED: todo add to swagger // return APIConstants.API_CONTROLLED_VISIBILITY; default: @@ -1300,8 +1296,11 @@ public static APIDTO fromAPItoDTO(API model, boolean preserveCredentials, dto.setVisibleRoles(Arrays.asList(model.getVisibleTenants().split(","))); } - if (model.getVisibleOrganizations() != null) { + if (model.getVisibleOrganizations() != null + || !APIConstants.DEFAULT_VISIBLE_ORG.equals(model.getVisibleOrganizations())) { dto.setVisibleOrganizations(Arrays.asList(model.getVisibleOrganizations().split(","))); + } else { + dto.setVisibleOrganizations(Collections.EMPTY_LIST); } if (model.getAdditionalProperties() != null) { @@ -1523,8 +1522,6 @@ private static APIDTO.VisibilityEnum mapVisibilityFromAPItoDTO(String visibility return APIDTO.VisibilityEnum.PRIVATE; case APIConstants.API_RESTRICTED_VISIBILITY: return APIDTO.VisibilityEnum.RESTRICTED; - case APIConstants.API_RESTRICTED_BY_ORG: - return APIDTO.VisibilityEnum.RESTRICTED_BY_ORG; // case APIConstants.API_CONTROLLED_VISIBILITY : todo add this to swagger // return APIDTO.VisibilityEnum.CONTROLLED; default: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index f95ec25f9d97..456aca5b6d41 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -374,7 +374,6 @@ private static API prepareForUpdateApi(API originalAPI, APIDTO apiDtoToUpdate, A apiToUpdate.setVisibleRoles(StringUtils.EMPTY); } apiToUpdate.setUUID(originalAPI.getUUID()); - apiToUpdate.setOrganization(originalAPI.getOrganization()); validateScopes(apiToUpdate); apiToUpdate.setThumbnailUrl(originalAPI.getThumbnailUrl()); if (apiDtoToUpdate.getKeyManagers() instanceof List) { @@ -1267,13 +1266,6 @@ public static API prepareToCreateAPIByDTO(APIDTO body, APIProvider apiProvider, } } - if (body.getVisibility() == APIDTO.VisibilityEnum.RESTRICTED_BY_ORG - && body.getVisibleOrganizations().isEmpty()) { - throw new APIManagementException( - "Valid organizations should be added under 'visibleOrganizations' to restrict " + "the visibility", - ExceptionCodes.ORGS_CANNOT_BE_NULL); - } - //Get all existing versions of api been adding List apiVersions = apiProvider.getApiVersionsMatchingApiNameAndOrganization(body.getName(), diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index 613cbf70684e..b35339c2153b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -9766,7 +9766,6 @@ components: - PUBLIC - PRIVATE - RESTRICTED - - RESTRICTED_BY_ORG x-otherScopes: - apim:api_publish - apim:api_manage @@ -12609,6 +12608,11 @@ components: IsJWTEnabledForLoginTokens: type: boolean default: false + orgAccessControlEnabled: + type: boolean + description: | + Is Organization-based access control configuration enabled + example: true customProperties: type: array items: From 034ca35f5c346e4dc86c7ceb8191325e9dca7ef4 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 18 Sep 2024 17:33:55 +0530 Subject: [PATCH 16/74] Fix bug --- .../api/publisher/v1/common/mappings/PublisherCommonUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index 456aca5b6d41..9e908045e8f6 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -374,6 +374,7 @@ private static API prepareForUpdateApi(API originalAPI, APIDTO apiDtoToUpdate, A apiToUpdate.setVisibleRoles(StringUtils.EMPTY); } apiToUpdate.setUUID(originalAPI.getUUID()); + apiToUpdate.setOrganization(originalAPI.getOrganization()); validateScopes(apiToUpdate); apiToUpdate.setThumbnailUrl(originalAPI.getThumbnailUrl()); if (apiDtoToUpdate.getKeyManagers() instanceof List) { From 134b2c08599fa9b6f8b6bd71171aa59b141ffa35 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 18 Sep 2024 18:02:03 +0530 Subject: [PATCH 17/74] Fix bug --- .../apimgt/persistence/RegistryPersistenceImpl.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 789cf0edf3a6..55b71affdc67 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -175,7 +175,7 @@ public PublisherAPI addAPI(Organization org, PublisherAPI publisherAPI) throws A } String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; - if (APIConstants.API_RESTRICTED_BY_ORG.equals(api.getVisibility())){ + if (!StringUtils.isEmpty(api.getVisibleOrganizations())) { visibleOrgs = api.getVisibleOrganizations(); } @@ -554,9 +554,10 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw String publisherAccessControlRoles = api.getAccessControlRoles(); String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; - if (APIConstants.API_RESTRICTED_BY_ORG.equals(api.getVisibility())){ + if (!StringUtils.isEmpty(api.getVisibleOrganizations())) { visibleOrgs = api.getVisibleOrganizations(); } + updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, api.getAccessControl(), api.getAdditionalProperties(), visibleOrgs); @@ -3340,9 +3341,9 @@ public PublisherAPIProduct addAPIProduct(Organization org, PublisherAPIProduct p String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; - if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ + // if (StringUtils.isEmpty(apiProduct.getVisibleOrganizations())) { //visibleOrgs = apiProduct.getVisibleOrganizations(); TODO fix for products - } + // } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), apiProduct.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(apiProduct.getId().getProviderName(), @@ -3570,9 +3571,9 @@ public PublisherAPIProduct updateAPIProduct(Organization org, PublisherAPIProduc String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; - if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ + // if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ //visibleOrgs = apiProduct.getVisibleOrganizations(); TODO fix for products - } + // } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), apiProduct.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(apiProduct.getId().getProviderName(), From 62c00fc81ad6111eaa5932a4b9d7ff7685b14157 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 24 Sep 2024 11:36:36 +0530 Subject: [PATCH 18/74] Add capability to append org id and org name to dev portal token urls --- .../v1/impl/KeyManagersApiServiceImpl.java | 5 ++- .../v1/mappings/KeyManagerMappingUtil.java | 31 ++++++++++++++----- .../impl/OAuthOpaqueAuthenticatorImpl.java | 17 +++++++--- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java index cab23de7858e..a68b1803daed 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java @@ -7,6 +7,7 @@ import org.wso2.carbon.apimgt.api.APIConsumer; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.impl.APIAdminImpl; import org.wso2.carbon.apimgt.impl.APIConsumerImpl; import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; @@ -26,6 +27,7 @@ public Response keyManagersGet(String xWSO2Tenant, MessageContext messageContext String organization = RestApiUtil.getOrganization(messageContext); try { + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); APIAdmin apiAdmin = new APIAdminImpl(); APIConsumer apiConsumer = new APIConsumerImpl(); String username = RestApiCommonUtil.getLoggedInUsername(); @@ -34,7 +36,8 @@ public Response keyManagersGet(String xWSO2Tenant, MessageContext messageContext List globalKeyManagerConfigurations = apiAdmin.getGlobalKeyManagerConfigurations(); permittedKeyManagerConfigurations.addAll(globalKeyManagerConfigurations); - return Response.ok(KeyManagerMappingUtil.toKeyManagerListDto(permittedKeyManagerConfigurations)).build(); + return Response.ok(KeyManagerMappingUtil.toKeyManagerListDto(permittedKeyManagerConfigurations, orgInfo)) + .build(); } catch (APIManagementException e) { RestApiUtil.handleInternalServerError( diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java index 29750278f3e2..8267cd946090 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java @@ -8,6 +8,7 @@ import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.model.ConfigurationDto; import org.wso2.carbon.apimgt.api.model.KeyManagerConnectorConfiguration; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.KeyManagerApplicationConfigurationDTO; @@ -22,7 +23,7 @@ public class KeyManagerMappingUtil { public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDto( - KeyManagerConfigurationDTO keyManagerConfigurationDTO) { + KeyManagerConfigurationDTO keyManagerConfigurationDTO, OrganizationInfo orgInfo) { KeyManagerInfoDTO keyManagerInfoDTO = new KeyManagerInfoDTO(); keyManagerInfoDTO.setId(keyManagerConfigurationDTO.getUuid()); @@ -62,8 +63,13 @@ public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDt if (jsonObject.has(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT) && !jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).isJsonNull() && !jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString().trim().isEmpty()) { - keyManagerInfoDTO.setTokenEndpoint( - jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString()); + if (orgInfo != null && orgInfo.getName() != null && orgInfo.getId() != null) { + keyManagerInfoDTO.setTokenEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT) + .getAsString().replace("{org_name}", orgInfo.getName()).replace("{org_id}", orgInfo.getId())); + } else { + keyManagerInfoDTO + .setTokenEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString()); + } } else { if (jsonObject.has(APIConstants.KeyManager.TOKEN_ENDPOINT)){ keyManagerInfoDTO.setTokenEndpoint( @@ -73,8 +79,17 @@ public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDt if (jsonObject.has(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT) && !jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).isJsonNull() && !jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString().trim().isEmpty()) { - keyManagerInfoDTO.setRevokeEndpoint( - jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString()); + if (orgInfo != null && orgInfo.getName() != null && orgInfo.getId() != null) { + keyManagerInfoDTO.setRevokeEndpoint( + jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT) + .getAsString() + .replace("{org_name}", orgInfo.getName()) + .replace("{org_id}", orgInfo.getId()) + ); + } else { + keyManagerInfoDTO.setRevokeEndpoint( + jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString()); + } } else { if (jsonObject.has(APIConstants.KeyManager.REVOKE_ENDPOINT)) { keyManagerInfoDTO.setRevokeEndpoint( @@ -118,12 +133,14 @@ public static JsonObject fromConfigurationMapToJson(Map configuration) { return jsonObject; } - public static KeyManagerListDTO toKeyManagerListDto(List keyManagerConfigurations) { + public static KeyManagerListDTO toKeyManagerListDto(List keyManagerConfigurations, + OrganizationInfo orgInfo) { KeyManagerListDTO keyManagerListDTO = new KeyManagerListDTO(); List keyManagerInfoDTOList = new ArrayList<>(); for (KeyManagerConfigurationDTO keyManagerConfigurationDTO : keyManagerConfigurations) { - keyManagerInfoDTOList.add(fromKeyManagerConfigurationDtoToKeyManagerInfoDto(keyManagerConfigurationDTO)); + keyManagerInfoDTOList + .add(fromKeyManagerConfigurationDtoToKeyManagerInfoDto(keyManagerConfigurationDTO, orgInfo)); } keyManagerListDTO.setList(keyManagerInfoDTOList); keyManagerListDTO.setCount(keyManagerInfoDTOList.size()); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index d1b9f687c101..b9dd63e21861 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -253,11 +253,17 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username int tenantId = MultitenantConstants.SUPER_TENANT_ID; APIManagerConfiguration config = ServiceReferenceHolder.getInstance(). getAPIManagerConfigurationService().getAPIManagerConfiguration(); - String claim = config.getFirstProperty(APIConstants.API_STORE_GROUP_EXTRACTOR_CLAIM_URI); - if (StringUtils.isBlank(claim)) { - claim = "http://wso2.org/claims/organization"; + String orgNameClaim = config.getOrgAccessControl().getOrgNameLocalClaim(); + String orgIdClaim = config.getOrgAccessControl().getOrgIdLocalClaim(); + if (StringUtils.isBlank(orgNameClaim)) { + orgNameClaim = "http://wso2.org/claims/organization"; } + if (StringUtils.isBlank(orgIdClaim)) { + orgIdClaim = "http://wso2.org/claims/organizationid"; + } + String organization = null; + String organizationId = null; String[] groupIdArray = null; try { if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { @@ -276,7 +282,9 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username UserRealm realm = (UserRealm) realmService.getTenantUserRealm(tenantId); UserStoreManager manager = realm.getUserStoreManager(); organization = - manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), claim, null); + manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgNameClaim, null); + organizationId = + manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); if (organization != null) { if (organization.contains(",")) { groupIdArray = organization.split(","); @@ -287,6 +295,7 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username organization = organization.trim(); groupIdArray = new String[] {organization}; orgInfo.setName(organization); // check for multiple orgs + orgInfo.setId(organizationId); } } else { // If claim is null then returning a empty string From a33a3dd97e78dd4afc1720d698e959f29e6b6927 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 2 Oct 2024 15:29:57 +0530 Subject: [PATCH 19/74] Backend for keymanager visibility --- .../api/dto/KeyManagerConfigurationDTO.java | 12 ++++ .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 58 +++++++++++++++++++ .../impl/dao/constants/SQLConstants.java | 18 ++++++ .../rest/api/admin/v1/dto/KeyManagerDTO.java | 24 +++++++- .../utils/mappings/KeyManagerMappingUtil.java | 8 +++ .../src/main/resources/admin-api.yaml | 5 +- .../src/main/resources/admin-api.yaml | 5 +- .../v1/impl/KeyManagersApiServiceImpl.java | 3 + .../rest/api/store/v1/utils/APIUtils.java | 19 ++++++ .../impl/OAuthOpaqueAuthenticatorImpl.java | 2 +- .../src/main/resources/sql/h2.sql | 7 +++ 11 files changed, 156 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/KeyManagerConfigurationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/KeyManagerConfigurationDTO.java index f1a61252290b..295f07b3fb8e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/KeyManagerConfigurationDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/KeyManagerConfigurationDTO.java @@ -19,7 +19,9 @@ package org.wso2.carbon.apimgt.api.dto; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -44,6 +46,7 @@ public class KeyManagerConfigurationDTO implements Serializable { private String alias = null; private KeyManagerPermissionConfigurationDTO permissions = new KeyManagerPermissionConfigurationDTO(); private Boolean isUsed = null; + private List allowedOrganizations = new ArrayList(); public KeyManagerConfigurationDTO() { } @@ -62,6 +65,7 @@ public KeyManagerConfigurationDTO(KeyManagerConfigurationDTO keyManagerConfigura this.externalReferenceId = keyManagerConfigurationDTO.getExternalReferenceId(); this.endpoints = keyManagerConfigurationDTO.getEndpoints(); this.setPermissions(keyManagerConfigurationDTO.getPermissions()); + this.allowedOrganizations = keyManagerConfigurationDTO.getAllowedOrganizations(); } public String getName() { @@ -207,4 +211,12 @@ public void setUsed(Boolean isUsed) { this.isUsed = isUsed; } + + public List getAllowedOrganizations() { + return allowedOrganizations; + } + + public void setAllowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 1c0067c51953..38e154ce856f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -9431,6 +9431,7 @@ public List getKeyManagerConfigurationsByOrganizatio log.error("Error while converting configurations in " + uuid, e); } keyManagerConfigurationDTO.setPermissions(getKeyManagerPermissions(keyManagerConfigurationDTO.getUuid())); + keyManagerConfigurationDTO.setAllowedOrganizations(getKeymanagerVisibleOrgs(uuid)); keyManagerConfigurationDTOS.add(keyManagerConfigurationDTO); } } @@ -9470,6 +9471,7 @@ public KeyManagerConfigurationDTO getKeyManagerConfigurationByID(String organiza keyManagerConfigurationDTO.setAdditionalProperties(map); } keyManagerConfigurationDTO.setPermissions(getKeyManagerPermissions(keyManagerConfigurationDTO.getUuid())); + keyManagerConfigurationDTO.setAllowedOrganizations(getKeymanagerVisibleOrgs(uuid)); return keyManagerConfigurationDTO; } } @@ -9541,6 +9543,7 @@ private KeyManagerConfigurationDTO getKeyManagerConfigurationByName(Connection c keyManagerConfigurationDTO.setAdditionalProperties(map); } keyManagerConfigurationDTO.setPermissions(getKeyManagerPermissions(uuid)); + keyManagerConfigurationDTO.setAllowedOrganizations(getKeymanagerVisibleOrgs(uuid)); return keyManagerConfigurationDTO; } } @@ -9583,6 +9586,7 @@ private KeyManagerConfigurationDTO getKeyManagerConfigurationByUUID(Connection c keyManagerConfigurationDTO.setAdditionalProperties(map); } keyManagerConfigurationDTO.setPermissions(getKeyManagerPermissions(uuid)); + keyManagerConfigurationDTO.setAllowedOrganizations(getKeymanagerVisibleOrgs(uuid)); return keyManagerConfigurationDTO; } } @@ -9623,6 +9627,18 @@ public void addKeyManagerConfiguration(KeyManagerConfigurationDTO keyManagerConf addPermissionStatement.executeBatch(); } } + List allowedOrgs = keyManagerConfigurationDTO.getAllowedOrganizations(); + if (allowedOrgs != null && !allowedOrgs.isEmpty()) { + try (PreparedStatement addVisibleOrgsStatement = conn.prepareStatement( + SQLConstants.KeyManagerOrgVisibilitySqlConstants.ADD_KEY_MANAGER_ORG_VISIBILITY_SQL)) { + for (String org : allowedOrgs) { + addVisibleOrgsStatement.setString(1, keyManagerConfigurationDTO.getUuid()); + addVisibleOrgsStatement.setString(2, org); + addVisibleOrgsStatement.addBatch(); + } + addVisibleOrgsStatement.executeBatch(); + } + } conn.commit(); } catch (SQLException e) { conn.rollback(); @@ -9703,6 +9719,23 @@ public void updateKeyManagerConfiguration(KeyManagerConfigurationDTO keyManagerC addPermissionStatement.executeBatch(); } } + try (PreparedStatement deleteOrgStatement = conn.prepareStatement(SQLConstants + .KeyManagerOrgVisibilitySqlConstants.DELETE_ALL_KEY_MANAGER_ORG_VISIBILITY_SQL)) { + deleteOrgStatement.setString(1, keyManagerConfigurationDTO.getUuid()); + deleteOrgStatement.executeUpdate(); + } + List allowedOrgs = keyManagerConfigurationDTO.getAllowedOrganizations(); + if (allowedOrgs != null && !allowedOrgs.isEmpty()) { + try (PreparedStatement addVisibleOrgsStatement = conn.prepareStatement( + SQLConstants.KeyManagerOrgVisibilitySqlConstants.ADD_KEY_MANAGER_ORG_VISIBILITY_SQL)) { + for (String org : allowedOrgs) { + addVisibleOrgsStatement.setString(1, keyManagerConfigurationDTO.getUuid()); + addVisibleOrgsStatement.setString(2, org); + addVisibleOrgsStatement.addBatch(); + } + addVisibleOrgsStatement.executeBatch(); + } + } conn.commit(); } catch (SQLException e) { conn.rollback(); @@ -9775,6 +9808,30 @@ public KeyManagerPermissionConfigurationDTO getKeyManagerPermissions(String keyM } return keyManagerPermissions; } + + public List getKeymanagerVisibleOrgs(String keyManagerUUID) throws APIManagementException { + List orgList = new ArrayList(); + try (Connection conn = APIMgtDBUtil.getConnection()) { + try { + String getKeyManagerPermissionQuery = SQLConstants.KeyManagerOrgVisibilitySqlConstants.GET_KEY_MANAGER_ORG_VISIBILITY_SQL; + PreparedStatement ps = conn.prepareStatement(getKeyManagerPermissionQuery); + ps.setString(1, keyManagerUUID); + ResultSet resultSet = ps.executeQuery(); + while (resultSet.next()) { + orgList.add(resultSet.getString("ALLOWED_ORGANIZATIONS")); + } + } catch (SQLException e) { + conn.rollback(); + handleException("Failed to get Key Manager organizations information for Key Manager " + keyManagerUUID, + e); + } + } catch (SQLException e) { + throw new APIManagementException( + "Error while retrieving key manager organizations with id " + keyManagerUUID, e); + } + return orgList; + } + public List getKeyManagerConfigurations() throws APIManagementException { List keyManagerConfigurationDTOS = new ArrayList<>(); @@ -9802,6 +9859,7 @@ public List getKeyManagerConfigurations() throws API log.error("Error while converting configurations in " + uuid, e); } keyManagerConfigurationDTO.setPermissions(getKeyManagerPermissions(uuid)); + keyManagerConfigurationDTO.setAllowedOrganizations(getKeymanagerVisibleOrgs(uuid)); keyManagerConfigurationDTOS.add(keyManagerConfigurationDTO); } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index b1b3339bc4b7..a85415609cbb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -3777,6 +3777,24 @@ public static class KeyManagerPermissionsSqlConstants { " WHERE KEY_MANAGER_UUID = ?"; } + /** + * Static class to hold database queries related to AM_KEY_MANAGER_PERMISSIONS table + */ + public static class KeyManagerOrgVisibilitySqlConstants { + + public static final String ADD_KEY_MANAGER_ORG_VISIBILITY_SQL = + " INSERT INTO" + + " AM_KEY_MANAGER_ALLOWED_ORGS (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS)" + + " VALUES(?, ?)"; + + public static final String DELETE_ALL_KEY_MANAGER_ORG_VISIBILITY_SQL = "DELETE FROM AM_KEY_MANAGER_ALLOWED_ORGS" + + " WHERE KEY_MANAGER_UUID = ?"; + + public static final String GET_KEY_MANAGER_ORG_VISIBILITY_SQL = + "SELECT ALLOWED_ORGANIZATIONS" + + " FROM AM_KEY_MANAGER_ALLOWED_ORGS " + + " WHERE KEY_MANAGER_UUID = ?"; + } /** * Static class to hold database queries related to AM_TENANT_THEMES table */ diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/KeyManagerDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/KeyManagerDTO.java index 5d38b2739773..cfd81adad440 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/KeyManagerDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/KeyManagerDTO.java @@ -94,6 +94,7 @@ public static TokenTypeEnum fromValue(String v) { } } private TokenTypeEnum tokenType = TokenTypeEnum.DIRECT; + private List allowedOrganizations = new ArrayList(); /** **/ @@ -702,6 +703,23 @@ public void setTokenType(TokenTypeEnum tokenType) { this.tokenType = tokenType; } + /** + **/ + public KeyManagerDTO allowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("allowedOrganizations") + public List getAllowedOrganizations() { + return allowedOrganizations; + } + public void setAllowedOrganizations(List allowedOrganizations) { + this.allowedOrganizations = allowedOrganizations; + } + @Override public boolean equals(java.lang.Object o) { @@ -746,12 +764,13 @@ public boolean equals(java.lang.Object o) { Objects.equals(global, keyManager.global) && Objects.equals(additionalProperties, keyManager.additionalProperties) && Objects.equals(permissions, keyManager.permissions) && - Objects.equals(tokenType, keyManager.tokenType); + Objects.equals(tokenType, keyManager.tokenType) && + Objects.equals(allowedOrganizations, keyManager.allowedOrganizations); } @Override public int hashCode() { - return Objects.hash(id, name, displayName, type, description, wellKnownEndpoint, introspectionEndpoint, clientRegistrationEndpoint, tokenEndpoint, displayTokenEndpoint, revokeEndpoint, displayRevokeEndpoint, userInfoEndpoint, authorizeEndpoint, endpoints, certificates, issuer, alias, scopeManagementEndpoint, availableGrantTypes, enableTokenGeneration, enableTokenEncryption, enableTokenHashing, enableMapOAuthConsumerApps, enableOAuthAppCreation, enableSelfValidationJWT, claimMapping, consumerKeyClaim, scopesClaim, tokenValidation, enabled, global, additionalProperties, permissions, tokenType); + return Objects.hash(id, name, displayName, type, description, wellKnownEndpoint, introspectionEndpoint, clientRegistrationEndpoint, tokenEndpoint, displayTokenEndpoint, revokeEndpoint, displayRevokeEndpoint, userInfoEndpoint, authorizeEndpoint, endpoints, certificates, issuer, alias, scopeManagementEndpoint, availableGrantTypes, enableTokenGeneration, enableTokenEncryption, enableTokenHashing, enableMapOAuthConsumerApps, enableOAuthAppCreation, enableSelfValidationJWT, claimMapping, consumerKeyClaim, scopesClaim, tokenValidation, enabled, global, additionalProperties, permissions, tokenType, allowedOrganizations); } @Override @@ -794,6 +813,7 @@ public String toString() { sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); sb.append(" permissions: ").append(toIndentedString(permissions)).append("\n"); sb.append(" tokenType: ").append(toIndentedString(tokenType)).append("\n"); + sb.append(" allowedOrganizations: ").append(toIndentedString(allowedOrganizations)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/KeyManagerMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/KeyManagerMappingUtil.java index 42ec4fb3673c..fbe5a2c7abfc 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/KeyManagerMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/KeyManagerMappingUtil.java @@ -218,6 +218,10 @@ public static KeyManagerDTO toKeyManagerDTO(KeyManagerConfigurationDTO keyManage jsonObject.remove(APIConstants.KeyManager.CONSUMER_KEY_CLAIM); } keyManagerDTO.setAdditionalProperties(new Gson().fromJson(jsonObject, Map.class)); + + if (keyManagerConfigurationDTO.getAllowedOrganizations() != null) { + keyManagerDTO.setAllowedOrganizations(keyManagerConfigurationDTO.getAllowedOrganizations()); + } return keyManagerDTO; } @@ -316,6 +320,10 @@ public static KeyManagerConfigurationDTO toKeyManagerConfigurationDTO(String ten } } keyManagerConfigurationDTO.setEndpoints(endpoints); + + if (keyManagerDTO.getAllowedOrganizations() != null) { + keyManagerConfigurationDTO.setAllowedOrganizations(keyManagerDTO.getAllowedOrganizations()); + } additionalProperties .put(APIConstants.KeyManager.ENABLE_OAUTH_APP_CREATION, keyManagerDTO.isEnableOAuthAppCreation()); additionalProperties.put(APIConstants.KeyManager.ENABLE_MAP_OAUTH_CONSUMER_APPS, diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml index ce9b2a358c7d..d5ccec61c545 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml @@ -4958,7 +4958,10 @@ components: - EXCHANGED - DIRECT - BOTH - + allowedOrganizations: + type: array + items: + type: string KeyManagerEndpoint: title: Key Manager Endpoint. required: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml index ce9b2a358c7d..d5ccec61c545 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml @@ -4958,7 +4958,10 @@ components: - EXCHANGED - DIRECT - BOTH - + allowedOrganizations: + type: array + items: + type: string KeyManagerEndpoint: title: Key Manager Endpoint. required: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java index a68b1803daed..b729bdf66559 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java @@ -13,6 +13,7 @@ import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.store.v1.KeyManagersApiService; import org.wso2.carbon.apimgt.rest.api.store.v1.mappings.KeyManagerMappingUtil; +import org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils; import org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil; import java.util.List; @@ -36,6 +37,8 @@ public Response keyManagersGet(String xWSO2Tenant, MessageContext messageContext List globalKeyManagerConfigurations = apiAdmin.getGlobalKeyManagerConfigurations(); permittedKeyManagerConfigurations.addAll(globalKeyManagerConfigurations); + permittedKeyManagerConfigurations = APIUtils + .filterAllowedKeyManagersForOrganizations(permittedKeyManagerConfigurations, orgInfo); return Response.ok(KeyManagerMappingUtil.toKeyManagerListDto(permittedKeyManagerConfigurations, orgInfo)) .build(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java index a88b927db7ab..f0d2b184a2b9 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java @@ -20,10 +20,12 @@ import org.wso2.carbon.apimgt.api.APIConsumer; import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.APIProduct; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.api.model.Environment; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.APIDefaultVersionURLsDTO; @@ -199,4 +201,21 @@ public static List extractEndpointURLs(APIProduct apiProduct return apiEndpointsList; } + + public static List filterAllowedKeyManagersForOrganizations( + List keymanagerConfigs, OrganizationInfo orgInfo) { + + List allowedList = new ArrayList(); + String organization = orgInfo.getName(); + for (KeyManagerConfigurationDTO keyManagerConfigurationDTO : keymanagerConfigs) { + List allowedOrgs = keyManagerConfigurationDTO.getAllowedOrganizations(); + // Add to allowedList if no organizations are restricted or if the organization is allowed + if (allowedOrgs == null || allowedOrgs.isEmpty() || allowedOrgs.contains(organization)) { + allowedList.add(keyManagerConfigurationDTO); + } + + } + + return allowedList; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index b9dd63e21861..ef1b54449c57 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -259,7 +259,7 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username orgNameClaim = "http://wso2.org/claims/organization"; } if (StringUtils.isBlank(orgIdClaim)) { - orgIdClaim = "http://wso2.org/claims/organizationid"; + orgIdClaim = "http://wso2.org/claims/organizationId"; } String organization = null; diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index 5b4cb0873713..f9395a283e14 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -2123,6 +2123,13 @@ CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +); + -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- CREATE TABLE IF NOT EXISTS AM_GW_PUBLISHED_API_DETAILS ( From 1ea20af1819947f8a8e2c7381a00cf6cbc5820be Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 2 Oct 2024 15:36:26 +0530 Subject: [PATCH 20/74] Revert url template change --- .../v1/impl/KeyManagersApiServiceImpl.java | 3 +- .../v1/mappings/KeyManagerMappingUtil.java | 30 +++++-------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java index b729bdf66559..a0af9db2f833 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/KeyManagersApiServiceImpl.java @@ -39,8 +39,7 @@ public Response keyManagersGet(String xWSO2Tenant, MessageContext messageContext permittedKeyManagerConfigurations.addAll(globalKeyManagerConfigurations); permittedKeyManagerConfigurations = APIUtils .filterAllowedKeyManagersForOrganizations(permittedKeyManagerConfigurations, orgInfo); - return Response.ok(KeyManagerMappingUtil.toKeyManagerListDto(permittedKeyManagerConfigurations, orgInfo)) - .build(); + return Response.ok(KeyManagerMappingUtil.toKeyManagerListDto(permittedKeyManagerConfigurations)).build(); } catch (APIManagementException e) { RestApiUtil.handleInternalServerError( diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java index 8267cd946090..4b334e03c495 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java @@ -23,7 +23,7 @@ public class KeyManagerMappingUtil { public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDto( - KeyManagerConfigurationDTO keyManagerConfigurationDTO, OrganizationInfo orgInfo) { + KeyManagerConfigurationDTO keyManagerConfigurationDTO) { KeyManagerInfoDTO keyManagerInfoDTO = new KeyManagerInfoDTO(); keyManagerInfoDTO.setId(keyManagerConfigurationDTO.getUuid()); @@ -63,13 +63,8 @@ public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDt if (jsonObject.has(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT) && !jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).isJsonNull() && !jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString().trim().isEmpty()) { - if (orgInfo != null && orgInfo.getName() != null && orgInfo.getId() != null) { - keyManagerInfoDTO.setTokenEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT) - .getAsString().replace("{org_name}", orgInfo.getName()).replace("{org_id}", orgInfo.getId())); - } else { - keyManagerInfoDTO - .setTokenEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString()); - } + keyManagerInfoDTO + .setTokenEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString()); } else { if (jsonObject.has(APIConstants.KeyManager.TOKEN_ENDPOINT)){ keyManagerInfoDTO.setTokenEndpoint( @@ -79,17 +74,8 @@ public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDt if (jsonObject.has(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT) && !jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).isJsonNull() && !jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString().trim().isEmpty()) { - if (orgInfo != null && orgInfo.getName() != null && orgInfo.getId() != null) { - keyManagerInfoDTO.setRevokeEndpoint( - jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT) - .getAsString() - .replace("{org_name}", orgInfo.getName()) - .replace("{org_id}", orgInfo.getId()) - ); - } else { - keyManagerInfoDTO.setRevokeEndpoint( - jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString()); - } + keyManagerInfoDTO + .setRevokeEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString()); } else { if (jsonObject.has(APIConstants.KeyManager.REVOKE_ENDPOINT)) { keyManagerInfoDTO.setRevokeEndpoint( @@ -133,14 +119,12 @@ public static JsonObject fromConfigurationMapToJson(Map configuration) { return jsonObject; } - public static KeyManagerListDTO toKeyManagerListDto(List keyManagerConfigurations, - OrganizationInfo orgInfo) { + public static KeyManagerListDTO toKeyManagerListDto(List keyManagerConfigurations) { KeyManagerListDTO keyManagerListDTO = new KeyManagerListDTO(); List keyManagerInfoDTOList = new ArrayList<>(); for (KeyManagerConfigurationDTO keyManagerConfigurationDTO : keyManagerConfigurations) { - keyManagerInfoDTOList - .add(fromKeyManagerConfigurationDtoToKeyManagerInfoDto(keyManagerConfigurationDTO, orgInfo)); + keyManagerInfoDTOList.add(fromKeyManagerConfigurationDtoToKeyManagerInfoDto(keyManagerConfigurationDTO)); } keyManagerListDTO.setList(keyManagerInfoDTOList); keyManagerListDTO.setCount(keyManagerInfoDTOList.size()); From 8a875bce5babe2f8f28accf1533702c75131743e Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 2 Oct 2024 15:38:45 +0530 Subject: [PATCH 21/74] Format --- .../api/store/v1/mappings/KeyManagerMappingUtil.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java index 4b334e03c495..29750278f3e2 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/mappings/KeyManagerMappingUtil.java @@ -8,7 +8,6 @@ import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.model.ConfigurationDto; import org.wso2.carbon.apimgt.api.model.KeyManagerConnectorConfiguration; -import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.KeyManagerApplicationConfigurationDTO; @@ -63,8 +62,8 @@ public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDt if (jsonObject.has(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT) && !jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).isJsonNull() && !jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString().trim().isEmpty()) { - keyManagerInfoDTO - .setTokenEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString()); + keyManagerInfoDTO.setTokenEndpoint( + jsonObject.get(APIConstants.KeyManager.DISPLAY_TOKEN_ENDPOINT).getAsString()); } else { if (jsonObject.has(APIConstants.KeyManager.TOKEN_ENDPOINT)){ keyManagerInfoDTO.setTokenEndpoint( @@ -74,8 +73,8 @@ public static KeyManagerInfoDTO fromKeyManagerConfigurationDtoToKeyManagerInfoDt if (jsonObject.has(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT) && !jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).isJsonNull() && !jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString().trim().isEmpty()) { - keyManagerInfoDTO - .setRevokeEndpoint(jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString()); + keyManagerInfoDTO.setRevokeEndpoint( + jsonObject.get(APIConstants.KeyManager.DISPLAY_REVOKE_ENDPOINT).getAsString()); } else { if (jsonObject.has(APIConstants.KeyManager.REVOKE_ENDPOINT)) { keyManagerInfoDTO.setRevokeEndpoint( From 9477c98ed4c4d3f720ccdbab3de32cf1cebfea79 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Fri, 4 Oct 2024 18:24:54 +0530 Subject: [PATCH 22/74] Refactor subcription visibility db --- .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 179 ++++++++++-------- .../impl/dao/constants/SQLConstants.java | 28 ++- .../carbon/apimgt/impl/utils/APIUtil.java | 2 +- .../src/main/resources/sql/h2.sql | 8 +- 4 files changed, 130 insertions(+), 87 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 38e154ce856f..a89a8946ab4e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -11542,25 +11542,9 @@ public void addSubscriptionPolicy(SubscriptionPolicy policy) throws APIManagemen policyStatement.setInt(15, policy.getGraphQLMaxDepth()); policyStatement.setInt(16, policy.getGraphQLMaxComplexity()); policyStatement.setString(17, policy.getBillingPlan()); - List list = policy.getAllowedOrganizations(); - String allowedOrganizations = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; //Default - if (list != null && !list.isEmpty()) { - allowedOrganizations = String.join(",", list); - } - policyStatement.setString(18, allowedOrganizations); + if (hasCustomAttrib) { - policyStatement.setBytes(19, policy.getCustomAttributes()); - policyStatement.setString(20, policy.getMonetizationPlan()); - policyStatement.setString(21, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); - policyStatement.setString(22, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); - policyStatement.setString(23, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); - policyStatement.setString(24, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); - policyStatement.setInt(25, policy.getSubscriberCount()); - } else { + policyStatement.setBytes(18, policy.getCustomAttributes()); policyStatement.setString(19, policy.getMonetizationPlan()); policyStatement.setString(20, policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); @@ -11571,6 +11555,30 @@ public void addSubscriptionPolicy(SubscriptionPolicy policy) throws APIManagemen policyStatement.setString(23, policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); policyStatement.setInt(24, policy.getSubscriberCount()); + } else { + policyStatement.setString(18, policy.getMonetizationPlan()); + policyStatement.setString(19, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); + policyStatement.setString(20, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); + policyStatement.setString(21, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); + policyStatement.setString(22, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); + policyStatement.setInt(23, policy.getSubscriberCount()); + } + + List allowedOrgs = policy.getAllowedOrganizations(); + if (allowedOrgs != null && !allowedOrgs.isEmpty()) { + try (PreparedStatement addVisibleOrgsStatement = conn + .prepareStatement(SQLConstants.PolicyOrgVisibilitySqlConstants.ADD_POLICY_ORG_VISIBILITY_SQL)) { + for (String org : allowedOrgs) { + addVisibleOrgsStatement.setString(1, policy.getUUID()); + addVisibleOrgsStatement.setString(2, org); + addVisibleOrgsStatement.addBatch(); + } + addVisibleOrgsStatement.executeBatch(); + } } policyStatement.executeUpdate(); conn.commit(); @@ -12285,13 +12293,7 @@ public SubscriptionPolicy[] getSubscriptionPolicies(int tenantID) throws APIMana monetizationPlanProperties.put(APIConstants.Monetization.CURRENCY, rs.getString(ThrottlePolicyConstants.COLUMN_CURRENCY)); subPolicy.setMonetizationPlanProperties(monetizationPlanProperties); - String allowedOrgs = rs.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS); - if(allowedOrgs == null) { - allowedOrgs = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; // set default if null - } - String[] items = allowedOrgs.split(","); - ArrayList allowedOrglist = new ArrayList<>(Arrays.asList(items)); - subPolicy.setAllowedOrganizations(allowedOrglist); + subPolicy.setAllowedOrganizations(getPolicyVisibleOrgs(subPolicy.getUUID())); InputStream binary = rs.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -12719,13 +12721,7 @@ public SubscriptionPolicy getSubscriptionPolicy(String policyName, int tenantId) policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); - String allowedOrgs = resultSet.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS); - if(allowedOrgs == null) { - allowedOrgs = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; // set default if null - } - String[] items = allowedOrgs.split(","); - ArrayList allowedOrglist = new ArrayList<>(Arrays.asList(items)); - policy.setAllowedOrganizations(allowedOrglist); + policy.setAllowedOrganizations(getPolicyVisibleOrgs(policy.getUUID())); InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -12778,14 +12774,7 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); - - String allowedOrgs = resultSet.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS); - if(allowedOrgs == null) { - allowedOrgs = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; // set default if null - } - String[] items = allowedOrgs.split(","); - ArrayList allowedOrglist = new ArrayList<>(Arrays.asList(items)); - policy.setAllowedOrganizations(allowedOrglist); + policy.setAllowedOrganizations(getPolicyVisibleOrgs(policy.getUUID())); InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { @@ -12816,6 +12805,29 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan } return policy; } + + public List getPolicyVisibleOrgs(String policyUUID) throws APIManagementException { + List orgList = new ArrayList(); + try (Connection conn = APIMgtDBUtil.getConnection()) { + try { + String getPolicyPermissionQuery = SQLConstants.PolicyOrgVisibilitySqlConstants.GET_POLICY_ORG_VISIBILITY_SQL; + PreparedStatement ps = conn.prepareStatement(getPolicyPermissionQuery); + ps.setString(1, policyUUID); + ResultSet resultSet = ps.executeQuery(); + while (resultSet.next()) { + orgList.add(resultSet.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS)); + } + } catch (SQLException e) { + conn.rollback(); + handleException("Failed to get policy allowed organizations " + policyUUID, + e); + } + } catch (SQLException e) { + throw new APIManagementException( + "Error while retrieving policy organizations with id " + policyUUID, e); + } + return orgList; + } /** * Retrieves list of pipelines for the policy with policy Id: policyId @@ -13225,44 +13237,10 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage updateStatement.setInt(12, policy.getGraphQLMaxComplexity()); updateStatement.setString(13, policy.getBillingPlan()); - List list = policy.getAllowedOrganizations(); - String allowedOrganizations = APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT; //Default - if (list != null && !list.isEmpty()) { - allowedOrganizations = String.join(",", list); - } - updateStatement.setString(14, allowedOrganizations); - if (hasCustomAttrib) { long lengthOfStream = policy.getCustomAttributes().length; - updateStatement.setBinaryStream(15, new ByteArrayInputStream(policy.getCustomAttributes()), + updateStatement.setBinaryStream(14, new ByteArrayInputStream(policy.getCustomAttributes()), lengthOfStream); - if (!StringUtils.isBlank(policy.getPolicyName()) && policy.getTenantId() != -1) { - updateStatement.setString(16, policy.getMonetizationPlan()); - updateStatement.setString(17, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); - updateStatement.setString(18, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); - updateStatement.setString(19, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); - updateStatement.setString(20, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); - updateStatement.setInt(21, policy.getSubscriberCount()); - updateStatement.setString(22, policy.getPolicyName()); - updateStatement.setInt(23, policy.getTenantId()); - } else if (!StringUtils.isBlank(policy.getUUID())) { - updateStatement.setString(16, policy.getMonetizationPlan()); - updateStatement.setString(17, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); - updateStatement.setString(18, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); - updateStatement.setString(19, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); - updateStatement.setString(20, - policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); - updateStatement.setInt(21, policy.getSubscriberCount()); - updateStatement.setString(22, policy.getUUID()); - } - } else { if (!StringUtils.isBlank(policy.getPolicyName()) && policy.getTenantId() != -1) { updateStatement.setString(15, policy.getMonetizationPlan()); updateStatement.setString(16, @@ -13276,7 +13254,6 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage updateStatement.setInt(20, policy.getSubscriberCount()); updateStatement.setString(21, policy.getPolicyName()); updateStatement.setInt(22, policy.getTenantId()); - } else if (!StringUtils.isBlank(policy.getUUID())) { updateStatement.setString(15, policy.getMonetizationPlan()); updateStatement.setString(16, @@ -13290,8 +13267,54 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage updateStatement.setInt(20, policy.getSubscriberCount()); updateStatement.setString(21, policy.getUUID()); } + } else { + if (!StringUtils.isBlank(policy.getPolicyName()) && policy.getTenantId() != -1) { + updateStatement.setString(14, policy.getMonetizationPlan()); + updateStatement.setString(15, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); + updateStatement.setString(16, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); + updateStatement.setString(17, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); + updateStatement.setString(18, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); + updateStatement.setInt(19, policy.getSubscriberCount()); + updateStatement.setString(20, policy.getPolicyName()); + updateStatement.setInt(21, policy.getTenantId()); + + } else if (!StringUtils.isBlank(policy.getUUID())) { + updateStatement.setString(14, policy.getMonetizationPlan()); + updateStatement.setString(15, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.FIXED_PRICE)); + updateStatement.setString(16, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.BILLING_CYCLE)); + updateStatement.setString(17, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.PRICE_PER_REQUEST)); + updateStatement.setString(18, + policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); + updateStatement.setInt(19, policy.getSubscriberCount()); + updateStatement.setString(20, policy.getUUID()); + } } updateStatement.executeUpdate(); + + try (PreparedStatement deleteOrgsStatement = connection.prepareStatement(SQLConstants + .PolicyOrgVisibilitySqlConstants.DELETE_ALL_POLICY_ORG_VISIBILITY_SQL)) { + deleteOrgsStatement.setString(1, policy.getUUID()); + deleteOrgsStatement.executeUpdate(); + } + List allowedOrgs = policy.getAllowedOrganizations(); + if (allowedOrgs != null && !allowedOrgs.isEmpty()) { + try (PreparedStatement addOrgsStatement = connection.prepareStatement(SQLConstants + .PolicyOrgVisibilitySqlConstants.ADD_POLICY_ORG_VISIBILITY_SQL)) { + for (String org : allowedOrgs) { + addOrgsStatement.setString(1, policy.getUUID()); + addOrgsStatement.setString(2, org); + addOrgsStatement.addBatch(); + } + addOrgsStatement.executeBatch(); + } + } connection.commit(); } catch (SQLException e) { if (connection != null) { @@ -13507,7 +13530,9 @@ private void setCommonParametersForPolicy(PreparedStatement policyStatement, Pol if (!StringUtils.isBlank(policy.getUUID())) { policyStatement.setString(11, policy.getUUID()); } else { - policyStatement.setString(11, UUID.randomUUID().toString()); + String uuid = UUID.randomUUID().toString(); + policy.setUUID(uuid); + policyStatement.setString(11, uuid); } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index a85415609cbb..c91e360466cf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -2355,16 +2355,16 @@ public class SQLConstants { "INSERT INTO AM_POLICY_SUBSCRIPTION (NAME, DISPLAY_NAME, TENANT_ID, DESCRIPTION, QUOTA_TYPE, QUOTA, \n" + " QUOTA_UNIT, UNIT_TIME, TIME_UNIT, IS_DEPLOYED, UUID, RATE_LIMIT_COUNT, \n" + " RATE_LIMIT_TIME_UNIT,STOP_ON_QUOTA_REACH, MAX_DEPTH, MAX_COMPLEXITY, \n" + - " BILLING_PLAN,ALLOWED_ORGANIZATIONS,MONETIZATION_PLAN,FIXED_RATE,BILLING_CYCLE,PRICE_PER_REQUEST,CURRENCY, CONNECTIONS_COUNT) \n" + - " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + " BILLING_PLAN,MONETIZATION_PLAN,FIXED_RATE,BILLING_CYCLE,PRICE_PER_REQUEST,CURRENCY, CONNECTIONS_COUNT) \n" + + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; public static final String INSERT_SUBSCRIPTION_POLICY_WITH_CUSTOM_ATTRIB_SQL = "INSERT INTO AM_POLICY_SUBSCRIPTION (NAME, DISPLAY_NAME, TENANT_ID, DESCRIPTION, QUOTA_TYPE, QUOTA, \n" + " QUOTA_UNIT, UNIT_TIME, TIME_UNIT, IS_DEPLOYED, UUID, RATE_LIMIT_COUNT, \n" + " RATE_LIMIT_TIME_UNIT, STOP_ON_QUOTA_REACH, MAX_DEPTH, MAX_COMPLEXITY,\n" + - " BILLING_PLAN, ALLOWED_ORGANIZATIONS, CUSTOM_ATTRIBUTES, MONETIZATION_PLAN, \n" + + " BILLING_PLAN, CUSTOM_ATTRIBUTES, MONETIZATION_PLAN, \n" + " FIXED_RATE, BILLING_CYCLE, PRICE_PER_REQUEST, CURRENCY, CONNECTIONS_COUNT) \n" + - " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; public static final String INSERT_GLOBAL_POLICY_SQL = @@ -2580,7 +2580,6 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, " + - "ALLOWED_ORGANIZATIONS = ?, " + "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + "BILLING_CYCLE = ?," + @@ -2605,7 +2604,6 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, "+ - "ALLOWED_ORGANIZATIONS = ?, " + "CUSTOM_ATTRIBUTES = ?, "+ "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + @@ -2631,7 +2629,6 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, "+ - "ALLOWED_ORGANIZATIONS = ?, " + "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + "BILLING_CYCLE = ?," + @@ -2656,7 +2653,6 @@ public class SQLConstants { "MAX_DEPTH = ?, " + "MAX_COMPLEXITY = ?, " + "BILLING_PLAN = ?, "+ - "ALLOWED_ORGANIZATIONS = ?, " + "CUSTOM_ATTRIBUTES = ?, "+ "MONETIZATION_PLAN = ?," + "FIXED_RATE = ?," + @@ -3795,6 +3791,22 @@ public static class KeyManagerOrgVisibilitySqlConstants { " FROM AM_KEY_MANAGER_ALLOWED_ORGS " + " WHERE KEY_MANAGER_UUID = ?"; } + + public static class PolicyOrgVisibilitySqlConstants { + + public static final String ADD_POLICY_ORG_VISIBILITY_SQL = + " INSERT INTO" + + " AM_POLICY_ALLOWED_ORGS (POLICY_UUID, ALLOWED_ORGANIZATIONS)" + + " VALUES(?, ?)"; + + public static final String DELETE_ALL_POLICY_ORG_VISIBILITY_SQL = "DELETE FROM AM_POLICY_ALLOWED_ORGS" + + " WHERE POLICY_UUID = ?"; + + public static final String GET_POLICY_ORG_VISIBILITY_SQL = + "SELECT ALLOWED_ORGANIZATIONS" + + " FROM AM_POLICY_ALLOWED_ORGS " + + " WHERE POLICY_UUID = ?"; + } /** * Static class to hold database queries related to AM_TENANT_THEMES table */ diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 44591fb295cf..5b6b48ee3142 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -10577,7 +10577,7 @@ public static Set getAllowedTiersForTheOrganization(Set tiers, Strin for (Tier tier : tiers) { for (SubscriptionPolicy policy : policies) { if (policy.getPolicyName().equals(tier.getName()) - && (policy.getAllowedOrganizations().contains(APIConstants.ALLOWED_ORGANIZATIONS_DEFAULT) + && (policy.getAllowedOrganizations().isEmpty() || policy.getAllowedOrganizations().contains(organization))) { allowedTiers.add(tier); } diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index f9395a283e14..d2cd9413e282 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -1855,7 +1855,6 @@ CREATE TABLE IF NOT EXISTS AM_POLICY_SUBSCRIPTION ( MAX_COMPLEXITY INT NOT NULL DEFAULT 0, MAX_DEPTH INT NOT NULL DEFAULT 0, CONNECTIONS_COUNT INT NOT NULL DEFAULT 0, - ALLOWED_ORGANIZATIONS VARCHAR(1024) NULL DEFAULT NULL, PRIMARY KEY (POLICY_ID), UNIQUE (UUID) ); @@ -2130,6 +2129,13 @@ CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_ALLOWED_ORGS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS AM_POLICY_ALLOWED_ORGS ( + ALLOWED_ORGS_ID INT NOT NULL AUTO_INCREMENT, + POLICY_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (ALLOWED_ORGS_ID) +); + -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- CREATE TABLE IF NOT EXISTS AM_GW_PUBLISHED_API_DETAILS ( From 48ec34ab04e1a6af2e20dd2e8b9e015b3067c91d Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Mon, 7 Oct 2024 13:19:10 +0530 Subject: [PATCH 23/74] Fix app keys loading issue for shared apps --- .../store/v1/impl/ApplicationsApiServiceImpl.java | 12 ++++++++---- .../api/util/impl/OAuthOpaqueAuthenticatorImpl.java | 5 ++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index f5ea01076981..972f3e73c073 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -918,16 +918,19 @@ public Response applicationsApplicationIdKeysKeyTypeCleanUpPost(String applicati * Used to get all keys of an application * * @param applicationUUID Id of the application + * @param orgInfo * @return List of application keys */ - private Set getApplicationKeys(String applicationUUID, String tenantDomain) { + private Set getApplicationKeys(String applicationUUID, String tenantDomain, OrganizationInfo orgInfo) { String username = RestApiCommonUtil.getLoggedInUsername(); try { APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); Application application = apiConsumer.getLightweightApplicationByUUID(applicationUUID); if (application != null) { - if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application)) { + if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) + || (orgInfo != null && orgInfo.getName() != null + && orgInfo.getName().equals(application.getSharedOrganization()))) { return apiConsumer.getApplicationKeysOfApplication(application.getId(), tenantDomain); } else { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_APPLICATION, applicationUUID, log); @@ -949,7 +952,7 @@ private Set getApplicationKeys(String applicationUUID, String tenantDoma */ private Set getApplicationKeys(String applicationUUID) { - return getApplicationKeys(applicationUUID, null); + return getApplicationKeys(applicationUUID, null, null); } @Override @@ -1225,7 +1228,8 @@ public Response applicationsApplicationIdOauthKeysGet(String applicationId, String xWso2Tenant, MessageContext messageContext) throws APIManagementException { String organization = RestApiUtil.getValidatedOrganization(messageContext); - Set applicationKeys = getApplicationKeys(applicationId, organization); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + Set applicationKeys = getApplicationKeys(applicationId, organization, orgInfo); List keyDTOList = new ArrayList<>(); ApplicationKeyListDTO applicationKeyListDTO = new ApplicationKeyListDTO(); applicationKeyListDTO.setCount(0); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index ef1b54449c57..418349920b6b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -155,7 +155,10 @@ public boolean authenticate(Message message) throws APIManagementException { carbonContext.setUsername(username); message.put(RestApiConstants.AUTH_TOKEN_INFO, tokenInfo); message.put(RestApiConstants.SUB_ORGANIZATION, tenantDomain); - message.put(RestApiConstants.ORGANIZATION_INFO, getOrganizationInfo(tenantDomain, username)); // TODO cache + if (ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService() + .getAPIManagerConfiguration().getOrgAccessControl().isEnabled()) { + message.put(RestApiConstants.ORGANIZATION_INFO, getOrganizationInfo(tenantDomain, username)); + } if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { APIUtil.loadTenantConfigBlockingMode(tenantDomain); } From 88b760745bf0a5d6372ac2f4233b6bed944fd7d0 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 9 Oct 2024 16:06:35 +0530 Subject: [PATCH 24/74] Add capability to use multiple keymanagers with same issuer --- .../OneTimeTokenRevocationMediator.java | 5 +++- .../OneTimeTokenRevocationMediatorTest.java | 4 ++- .../impl/dto/OrganizationKeyManagerDto.java | 30 ++++++++++++------- .../apimgt/impl/factory/KeyManagerHolder.java | 7 +++-- .../impl/jwt/JWTValidationServiceImpl.java | 28 +++++++++++++++-- 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java index f1d344c0ecbf..30761cc71608 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java @@ -60,7 +60,10 @@ public boolean mediate(MessageContext messageContext) { String issuer = authContext.getIssuer(); List scopes = authContext.getRequestTokenScopes(); if (StringUtils.isNotBlank(issuer)) { - KeyManagerDto keyManagerDto = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); + List keyManagerDtoList = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); + KeyManagerDto keyManagerDto = keyManagerDtoList.get(0); // TODO : Does not support multiple km with same + // issuer + if (keyManagerDto != null && StringUtils.isNotBlank(scope) && scopes.contains(scope)) { String token = authContext.getAccessToken(); String consumerKey = authContext.getConsumerKey(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java index 470e0d5e572e..913f4f655988 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java @@ -72,8 +72,10 @@ public void init() { Mockito.when(authContext.getIssuer()).thenReturn("https://localhost:9443/oauth2/token"); Mockito.when(authContext.getRequestTokenScopes()).thenReturn(scopes); + List keymanagerList = new ArrayList(); + keymanagerList.add(keyManagerDto); Mockito.when(KeyManagerHolder.getKeyManagerByIssuer(Mockito.anyString(), Mockito.anyString())). - thenReturn(keyManagerDto); + thenReturn(keymanagerList); Mockito.when(keyManagerDto.getKeyManager()).thenReturn(keyManager); Mockito.doNothing().when(oneTimeExecutorService).execute(() -> keyManagerDto.getKeyManager().revokeOneTimeToken(Mockito.anyString(), Mockito.anyString())); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java index 83fff9803992..df279f62ea9c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java @@ -21,14 +21,16 @@ import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.jwt.JWTValidator; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class OrganizationKeyManagerDto { private Map keyManagerMap = new LinkedHashMap<>(); - private Map issuerNameMap = new HashMap<>(); + private Map> issuerNameMap = new HashMap<>(); public Map getKeyManagerMap() { @@ -51,23 +53,27 @@ public void putKeyManagerDto(KeyManagerDto keyManagerDto) { } else { keyManagerMap.put(keyManagerDto.getName(), keyManagerDto); } - issuerNameMap.put(keyManagerDto.getIssuer(), keyManagerDto.getName()); + issuerNameMap.computeIfAbsent(keyManagerDto.getIssuer(), k -> new ArrayList<>()).add(keyManagerDto.getName()); + } public void removeKeyManagerDtoByName(String name) { KeyManagerDto keyManagerDto = keyManagerMap.get(name); if (keyManagerDto != null) { - issuerNameMap.remove(keyManagerDto.getIssuer()); + issuerNameMap.get(keyManagerDto.getIssuer()).remove(name); + if (issuerNameMap.get(keyManagerDto.getIssuer()).isEmpty()) { + issuerNameMap.remove(keyManagerDto.getIssuer()); + } } keyManagerMap.remove(name); } public JWTValidator getJWTValidatorByIssuer(String issuer) { - String keyManagerName = issuerNameMap.get(issuer); - if (StringUtils.isNotEmpty(keyManagerName)) { - KeyManagerDto keyManagerDto = keyManagerMap.get(keyManagerName); + List keyManagerNames = issuerNameMap.get(issuer); + if (keyManagerNames != null && !keyManagerNames.isEmpty()) { + KeyManagerDto keyManagerDto = keyManagerMap.get(keyManagerNames.get(0)); if (keyManagerDto != null) { return keyManagerDto.getJwtValidator(); } @@ -75,11 +81,15 @@ public JWTValidator getJWTValidatorByIssuer(String issuer) { return null; } - public KeyManagerDto getKeyManagerDtoByIssuer(String issuer) { + public List getKeyManagerDtoByIssuer(String issuer) { - String keyManagerName = issuerNameMap.get(issuer); - if (StringUtils.isNotEmpty(keyManagerName)) { - return keyManagerMap.get(keyManagerName); + List dtoList = new ArrayList(); + List keyManagerNames = issuerNameMap.get(issuer); + if (keyManagerNames != null && !keyManagerNames.isEmpty()) { + for (String keyManagerName : keyManagerNames) { + dtoList.add(keyManagerMap.get(keyManagerName)); + } + return dtoList; } return null; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/factory/KeyManagerHolder.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/factory/KeyManagerHolder.java index b5ec7ff146b6..5e6cfc9bcbdf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/factory/KeyManagerHolder.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/factory/KeyManagerHolder.java @@ -42,6 +42,7 @@ import org.wso2.carbon.apimgt.impl.utils.APIUtil; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -259,10 +260,12 @@ public static KeyManager getKeyManagerInstance(String tenantDomain, String keyMa return keyManager; } - public static KeyManagerDto getKeyManagerByIssuer(String tenantDomain, String issuer) { + public static List getKeyManagerByIssuer(String tenantDomain, String issuer) { if (globalJWTValidatorMap.containsKey(issuer)) { - return globalJWTValidatorMap.get(issuer); + List list = new ArrayList(); + list.add(globalJWTValidatorMap.get(issuer)); + return list; } OrganizationKeyManagerDto organizationKeyManagerDto = getTenantKeyManagerDto(tenantDomain); if (organizationKeyManagerDto != null) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java index a4cd18dcb1f5..52eecbb825c8 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java @@ -18,6 +18,8 @@ package org.wso2.carbon.apimgt.impl.jwt; +import java.util.List; + import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -39,7 +41,18 @@ public JWTValidationInfo validateJWTToken(SignedJWTInfo signedJWTInfo) throws AP JWTValidationInfo jwtValidationInfo = new JWTValidationInfo(); String issuer = signedJWTInfo.getJwtClaimsSet().getIssuer(); if (StringUtils.isNotEmpty(issuer)) { - KeyManagerDto keyManagerDto = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); + List keyManagerDtoList = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); + KeyManagerDto keyManagerDto = null; + if (keyManagerDtoList.size() == 1) { // only one keymanager. no need to check if it can handle token + keyManagerDto = keyManagerDtoList.get(0); + } else { + for (KeyManagerDto kmrDto : keyManagerDtoList) { + if (kmrDto.getKeyManager().canHandleToken(signedJWTInfo.getToken())) { + keyManagerDto = kmrDto; + break; + } + } + } if (keyManagerDto != null && keyManagerDto.getJwtValidator() != null) { JWTValidationInfo validationInfo = keyManagerDto.getJwtValidator().validateToken(signedJWTInfo); validationInfo.setKeyManager(keyManagerDto.getName()); @@ -56,7 +69,18 @@ public String getKeyManagerNameIfJwtValidatorExist(SignedJWTInfo signedJWTInfo) String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String issuer = signedJWTInfo.getJwtClaimsSet().getIssuer(); - KeyManagerDto keyManagerDto = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); + List keyManagerDtoList = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); + KeyManagerDto keyManagerDto = null; + if (keyManagerDtoList.size() == 1) { // only one keymanager. no need to check if it can handle token + keyManagerDto = keyManagerDtoList.get(0); + } else { + for (KeyManagerDto kmrDto : keyManagerDtoList) { + if (kmrDto.getKeyManager().canHandleToken(signedJWTInfo.getToken())) { + keyManagerDto = kmrDto; + break; + } + } + } if (keyManagerDto != null && keyManagerDto.getJwtValidator() != null) { return keyManagerDto.getName(); }else{ From 6a6d5ce62ef6e80c67f2309a10bca0d4d4e24cfa Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 10 Oct 2024 15:27:15 +0530 Subject: [PATCH 25/74] Add org with spaces in the name --- .../carbon/apimgt/persistence/RegistryPersistenceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 55b71affdc67..aaa8e0ddf5ca 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1090,8 +1090,12 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String String modifiedQuery = RegistrySearchUtil.getDevPortalSearchQuery(searchQuery, ctx, isAllowDisplayAPIsWithMultipleStatus(), isAllowDisplayAPIsWithMultipleVersions()); if (!PersistenceUtil.isAdminUser(ctx)) { + String orgName = ctx.getOrganization().getName(); + if (orgName != null && orgName.contains(" ")) { + orgName = "\"" + orgName + "\""; + } modifiedQuery = modifiedQuery + "&visible_organizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" - + ctx.getOrganization().getName() + "*)"; + + orgName + "*)"; } log.debug("Modified query for devportal search: " + modifiedQuery); String userNameLocal; From 9081ab962c53966c95071c6587a141c222ffdad2 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Fri, 11 Oct 2024 14:14:38 +0530 Subject: [PATCH 26/74] Fix orgs with space --- .../apimgt/persistence/RegistryPersistenceImpl.java | 9 ++++++--- .../persistence/utils/RegistryPersistenceUtil.java | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index aaa8e0ddf5ca..61a598515a3d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1092,10 +1092,10 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String if (!PersistenceUtil.isAdminUser(ctx)) { String orgName = ctx.getOrganization().getName(); if (orgName != null && orgName.contains(" ")) { - orgName = "\"" + orgName + "\""; + orgName = orgName.replace(" ", "+"); } - modifiedQuery = modifiedQuery + "&visible_organizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR *" - + orgName + "*)"; + modifiedQuery = modifiedQuery + "&visible_organizations=(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR " + + orgName + ")"; } log.debug("Modified query for devportal search: " + modifiedQuery); String userNameLocal; @@ -3088,6 +3088,9 @@ private void updateRegistryResources(Registry registry, String artifactPath, Str // the roles that were specified can be maintained. apiResource.setProperty(APIConstants.DISPLAY_PUBLISHER_ROLES, publisherAccessControlRoles); apiResource.setProperty(APIConstants.ACCESS_CONTROL, publisherAccessControl); + if (!StringUtils.isEmpty(visibleOrganizations) && visibleOrganizations.contains(" ")) { + visibleOrganizations = visibleOrganizations.replace(" ", "+"); + } apiResource.setProperty(APIConstants.VISIBLE_ORGANIZATIONS, visibleOrganizations); apiResource.removeProperty(APIConstants.CUSTOM_API_INDEXER_PROPERTY); if (additionalProperties != null && additionalProperties.size() != 0) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index 68d68151ced6..c5333097b498 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -800,7 +800,11 @@ private static API setResourceProperties(API api, Resource apiResource, String a } } api.setAccessControl(apiResource.getProperty(APIConstants.ACCESS_CONTROL)); - api.setVisibleOrganizations(apiResource.getProperty(APIConstants.VISIBLE_ORGANIZATIONS)); + String visibleOrg = apiResource.getProperty(APIConstants.VISIBLE_ORGANIZATIONS); + if (visibleOrg != null) { + visibleOrg = visibleOrg.replace("+", " "); + } + api.setVisibleOrganizations(visibleOrg); String accessControlRoles = null; From 763494ab973d5fc762bfee59c8f1a1f86f510577 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 15 Oct 2024 16:25:44 +0530 Subject: [PATCH 27/74] Provide config to set claim to select the organization info --- .../apimgt/api/model/OrganizationInfo.java | 7 +++++++ .../wso2/carbon/apimgt/impl/APIConstants.java | 3 +++ .../carbon/apimgt/impl/APIConsumerImpl.java | 8 ++++---- .../apimgt/impl/APIManagerConfiguration.java | 16 +++++++++++++++ .../apimgt/impl/dto/OrgAccessControl.java | 7 +++++++ .../api/store/v1/impl/ApisApiServiceImpl.java | 2 +- .../v1/impl/ApplicationsApiServiceImpl.java | 20 ++++++++++--------- .../rest/api/store/v1/utils/APIUtils.java | 2 +- .../impl/OAuthOpaqueAuthenticatorImpl.java | 9 +++++++++ .../repository/conf/api-manager.xml.j2 | 1 + 10 files changed, 60 insertions(+), 15 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java index a3b832296bee..ba05a3a9705a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java @@ -23,6 +23,7 @@ public class OrganizationInfo { String superOrganization; String name; String id; + String organizationSelector; OrganizationInfo parentOrganization; OrganizationInfo[] childOrganizations; @@ -56,4 +57,10 @@ public OrganizationInfo[] getChildOrganizations() { public void setChildOrganizations(OrganizationInfo[] childOrganizations) { this.childOrganizations = childOrganizations; } + public String getOrganizationSelector() { + return organizationSelector; + } + public void setOrganizationSelector(String organizationSelector) { + this.organizationSelector = organizationSelector; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index fae6def4e4a4..4426e22ca467 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -3182,4 +3182,7 @@ public static class TokenValidationConstants { // For Organization access control Configuration public static final String ORG_BASED_ACCESS_CONTROL = "OrganizationBasedAccessControl"; public static final String ORG_BASED_ACCESS_CONTROL_ENABLE = "Enable"; + public static final String ORG_BASED_ACCESS_CONTROL_ORG_NAME_CLAIM = "OrganizationNameLocalClaim"; + public static final String ORG_BASED_ACCESS_CONTROL_ORG_ID_CLAIM = "OrganizationIDLocalClaim"; + public static final String ORG_BASED_ACCESS_CONTROL_SELECTOR_CLAIM = "OrgaizationSelectorLocalClaim"; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 9a343f1b04b6..bae01ba03e8c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -3849,10 +3849,10 @@ public Map searchPaginatedAPIs(String searchQuery, OrganizationI String userName = (userNameWithoutChange != null) ? userNameWithoutChange : username; String[] roles = APIUtil.getListOfRoles(userName); Map properties = APIUtil.getUserProperties(userName); - UserContext userCtx = new UserContext(userNameWithoutChange, new Organization(organizationInfo.getName()), - properties, roles); - - return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); + UserContext userCtx = new UserContext(userNameWithoutChange, + new Organization(organizationInfo.getOrganizationSelector()), properties, roles); + + return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); } private Map searchPaginatedAPIs(String searchQuery, int start, int end, Organization org, diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java index 73c01a2826f6..657a0a40203e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java @@ -685,6 +685,22 @@ private void setOrgBasedAccessControlConfigs(OMElement element) { orgAccessControl.setEnabled(Boolean.parseBoolean(orgEnableElement.getText())); } + OMElement orgSelectorElement = + element.getFirstChildWithName(new QName(APIConstants.ORG_BASED_ACCESS_CONTROL_SELECTOR_CLAIM)); + if (orgSelectorElement != null) { + orgAccessControl.setOrgSelectorClaim(orgSelectorElement.getText()); + } + OMElement orgNameElement = + element.getFirstChildWithName(new QName(APIConstants.ORG_BASED_ACCESS_CONTROL_ORG_NAME_CLAIM)); + if (orgNameElement != null) { + orgAccessControl.setOrgNameLocalClaim(orgNameElement.getText());; + } + OMElement orgIdElement = + element.getFirstChildWithName(new QName(APIConstants.ORG_BASED_ACCESS_CONTROL_ORG_ID_CLAIM)); + if (orgIdElement != null) { + orgAccessControl.setOrgIdLocalClaim(orgIdElement.getText()); + } + } public JSONObject getSubscriberAttributes() { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java index 313db3d57c1f..3c24445940e9 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java @@ -22,6 +22,7 @@ public class OrgAccessControl { private boolean isEnabled; private String orgNameLocalClaim; private String orgIdLocalClaim; + private String orgselectorClaim; public boolean isEnabled() { return isEnabled; } @@ -40,4 +41,10 @@ public String getOrgIdLocalClaim() { public void setOrgIdLocalClaim(String orgIdLocalClaim) { this.orgIdLocalClaim = orgIdLocalClaim; } + public String getOrgSelectorClaim() { + return orgselectorClaim; + } + public void setOrgSelectorClaim(String orgselectorClaim) { + this.orgselectorClaim = orgselectorClaim; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index ed759b418070..bcf1837a2ea0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1178,7 +1178,7 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo if (!api.isAPIProduct()) { // Add only organization specific tiers Set tiers = APIUtil.getAllowedTiersForTheOrganization(api.getApi().getAvailableTiers(), - userOrgInfo.getName(), userOrgInfo.getSuperOrganization()); + userOrgInfo.getOrganizationSelector(), userOrgInfo.getSuperOrganization()); api.getApi().removeAllTiers(); api.getApi().setAvailableTiers(tiers); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index 972f3e73c073..88caa764acd1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -143,7 +143,7 @@ public Response applicationsGet(String groupId, String query, String sortBy, Str APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); Subscriber subscriber = new Subscriber(username); Application[] applications; - String sharedOrganization = orgInfo.getName(); + String sharedOrganization = orgInfo.getOrganizationSelector(); applications = apiConsumer .getApplicationsWithPagination(new Subscriber(username), groupId, offset, limit, query, sortBy, sortOrder, organization, sharedOrganization); @@ -254,9 +254,9 @@ public Response applicationsGet(String groupId, String query, String sortBy, Str int appId = APIUtil.getApplicationId(applicationDTO.getName(), ownerId); Application oldApplication = apiConsumer.getApplicationById(appId); application = preProcessAndUpdateApplication(ownerId, applicationDTO, oldApplication, - oldApplication.getUUID(), orgInfo.getName()); + oldApplication.getUUID(), orgInfo.getOrganizationSelector()); } else { - application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getName()); + application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getOrganizationSelector()); update = Boolean.FALSE; } @@ -329,7 +329,8 @@ public Response applicationsPost(ApplicationDTO body, MessageContext messageCont String organization = RestApiUtil.getValidatedOrganization(messageContext); OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); - Application createdApplication = preProcessAndAddApplication(username, body, organization, orgInfo.getName()); + Application createdApplication = preProcessAndAddApplication(username, body, organization, + orgInfo.getOrganizationSelector()); ApplicationDTO createdApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(createdApplication); //to be set as the Location header @@ -432,8 +433,9 @@ public Response applicationsApplicationIdGet(String applicationId, String ifNone } } application.setApplicationAttributes(applicationAttributes); - if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) || (orgInfo.getName() != null - && orgInfo.getName().equals(application.getSharedOrganization()))) { + if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) + || (orgInfo.getOrganizationSelector() != null + && orgInfo.getOrganizationSelector().equals(application.getSharedOrganization()))) { ApplicationDTO applicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(application); applicationDTO.setHashEnabled(OAuthServerConfiguration.getInstance().isClientSecretHashEnabled()); Set scopes = apiConsumer @@ -484,7 +486,7 @@ public Response applicationsApplicationIdPut(String applicationId, ApplicationDT } OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); Application updatedApplication = preProcessAndUpdateApplication(username, body, oldApplication, - applicationId, orgInfo.getName()); + applicationId, orgInfo.getOrganizationSelector()); ApplicationDTO updatedApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(updatedApplication); return Response.ok().entity(updatedApplicationDTO).build(); @@ -929,8 +931,8 @@ private Set getApplicationKeys(String applicationUUID, String tenantDoma Application application = apiConsumer.getLightweightApplicationByUUID(applicationUUID); if (application != null) { if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) - || (orgInfo != null && orgInfo.getName() != null - && orgInfo.getName().equals(application.getSharedOrganization()))) { + || (orgInfo != null && orgInfo.getOrganizationSelector() != null + && orgInfo.getOrganizationSelector().equals(application.getSharedOrganization()))) { return apiConsumer.getApplicationKeysOfApplication(application.getId(), tenantDomain); } else { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_APPLICATION, applicationUUID, log); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java index f0d2b184a2b9..7b8c9e00fe66 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java @@ -206,7 +206,7 @@ public static List filterAllowedKeyManagersForOrgani List keymanagerConfigs, OrganizationInfo orgInfo) { List allowedList = new ArrayList(); - String organization = orgInfo.getName(); + String organization = orgInfo.getOrganizationSelector(); for (KeyManagerConfigurationDTO keyManagerConfigurationDTO : keymanagerConfigs) { List allowedOrgs = keyManagerConfigurationDTO.getAllowedOrganizations(); // Add to allowedList if no organizations are restricted or if the organization is allowed diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index 418349920b6b..c3ecdb3d7b99 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -258,6 +258,7 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username getAPIManagerConfigurationService().getAPIManagerConfiguration(); String orgNameClaim = config.getOrgAccessControl().getOrgNameLocalClaim(); String orgIdClaim = config.getOrgAccessControl().getOrgIdLocalClaim(); + String orgSelectorClaim = config.getOrgAccessControl().getOrgSelectorClaim(); if (StringUtils.isBlank(orgNameClaim)) { orgNameClaim = "http://wso2.org/claims/organization"; } @@ -267,6 +268,7 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username String organization = null; String organizationId = null; + String orgSelector = null; String[] groupIdArray = null; try { if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { @@ -288,6 +290,12 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgNameClaim, null); organizationId = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); + if (StringUtils.isBlank(orgSelectorClaim)) { + orgSelector = organization; // default selector will be organization name + } else { + orgSelector = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), + orgSelectorClaim, null); + } if (organization != null) { if (organization.contains(",")) { groupIdArray = organization.split(","); @@ -299,6 +307,7 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username groupIdArray = new String[] {organization}; orgInfo.setName(organization); // check for multiple orgs orgInfo.setId(organizationId); + orgInfo.setOrganizationSelector(orgSelector); } } else { // If claim is null then returning a empty string diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 index dfcfda46d296..d682e648b40c 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/conf_templates/templates/repository/conf/api-manager.xml.j2 @@ -108,6 +108,7 @@ {{apim.organization_based_access_control.enable}} {{apim.organization_based_access_control.organization_name_local_claim}} {{apim.organization_based_access_control.organization_id_local_claim}} + {{apim.organization_based_access_control.organization_selector_local_claim}} {% endif %} From 1c6916b6f8d8b868f74a16341a66bd7743364d70 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 16 Oct 2024 16:22:36 +0530 Subject: [PATCH 28/74] Fix api overview page visibility --- .../apimgt/persistence/dto/DevPortalAPI.java | 31 ++++++++++++------- .../api/store/v1/impl/ApisApiServiceImpl.java | 6 ++++ .../v1/impl/ApplicationsApiServiceImpl.java | 4 ++- .../rest/api/util/utils/RestApiUtil.java | 17 ++++++++++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPI.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPI.java index 956ab6313028..a93f27358dbd 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPI.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPI.java @@ -45,6 +45,7 @@ public class DevPortalAPI extends DevPortalAPIInfo { private String subscriptionAvailability; // need to decide isSubscriptionAvailable private String subscriptionAvailableOrgs; // (subscriptionAvailableTenants): need to decide the value of "isSubscriptionAvailable" + private String visibleOrganizations; //visible organizations private String authorizationHeader; private String apiKeyHeader; private List securityScheme = new ArrayList<>(); @@ -340,13 +341,20 @@ public void setGatewayVendor(String gatewayVendor) { this.gatewayVendor = gatewayVendor; } + public String getVisibleOrganizations() { + return visibleOrganizations; + } + + public void setVisibleOrganizations(String visibleOrganizations) { + this.visibleOrganizations = visibleOrganizations; + } + public String getAsyncTransportProtocols() { return asyncTransportProtocols; } public void setAsyncTransportProtocols(String asyncTransportProtocols) { this.asyncTransportProtocols = asyncTransportProtocols; } - @Override public String toString() { return "DevPortalAPI [status=" + status + ", isDefaultVersion=" + isDefaultVersion + ", description=" @@ -355,16 +363,17 @@ public String toString() { + businessOwnerEmail + ", transports=" + transports + ", redirectURL=" + redirectURL + ", apiExternalProductionEndpoint=" + apiExternalProductionEndpoint + ", apiExternalSandboxEndpoint=" + apiExternalSandboxEndpoint + ", apiOwner=" + apiOwner + ", advertiseOnly=" + advertiseOnly - + ", subscriptionAvailability=" + subscriptionAvailability + ", subscriptionAvailableOrgs=" - + subscriptionAvailableOrgs + ", authorizationHeader=" + authorizationHeader + ", securityScheme=" - + securityScheme + ", environments=" + environments + ", gatewayVendor=" + gatewayVendor - + ", asyncTransportProtocols=" + asyncTransportProtocols + ", apiCategories=" + apiCategories - + ", isMonetizationEnabled=" + isMonetizationEnabled + ", keyManagers=" + keyManagers - + ", deploymentEnvironments=" + deploymentEnvironments + ", tags=" + tags + ", additionalProperties=" - + additionalProperties + ", endpointConfig=" + endpointConfig + ", type=" + type + ", advertisedOnly=" - + advertisedOnly + ", swaggerDefinition=" + swaggerDefinition + ", contextTemplate=" + contextTemplate - + ", apiSecurity=" + apiSecurity + ", visibility=" + visibility + ", visibleRoles=" + visibleRoles - + "]"; + + ", vendor=" + vendor + ", subscriptionAvailability=" + subscriptionAvailability + + ", subscriptionAvailableOrgs=" + subscriptionAvailableOrgs + ", visibleOrganizations=" + + visibleOrganizations + ", authorizationHeader=" + authorizationHeader + ", apiKeyHeader=" + + apiKeyHeader + ", securityScheme=" + securityScheme + ", environments=" + environments + + ", apiCategories=" + apiCategories + ", isMonetizationEnabled=" + isMonetizationEnabled + + ", keyManagers=" + keyManagers + ", deploymentEnvironments=" + deploymentEnvironments + ", tags=" + + tags + ", additionalProperties=" + additionalProperties + ", endpointConfig=" + endpointConfig + + ", type=" + type + ", advertisedOnly=" + advertisedOnly + ", swaggerDefinition=" + swaggerDefinition + + ", contextTemplate=" + contextTemplate + ", apiSecurity=" + apiSecurity + ", visibility=" + visibility + + ", visibleRoles=" + visibleRoles + ", gatewayVendor=" + gatewayVendor + ", asyncTransportProtocols=" + + asyncTransportProtocols + "]"; } public String getApiSecurity() { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index bcf1837a2ea0..b678299d4466 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1168,6 +1168,12 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo APIConsumer apiConsumer = RestApiCommonUtil.getLoggedInUserConsumer(); ApiTypeWrapper api = apiConsumer.getAPIorAPIProductByUUID(apiId, organization); String status = api.getStatus(); + String visibleOrgs = api.getApi().getVisibleOrganizations(); + String userOrg = userOrgInfo.getOrganizationSelector(); + + if (!api.isAPIProduct() && !RestApiUtil.isOrganizationVisibilityAllowed(visibleOrgs, userOrg)) { + RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); + } // Extracting clicked API name by the user, for the recommendation system String userName = RestApiCommonUtil.getLoggedInUsername(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index 88caa764acd1..8c4acd89f5a7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -1297,9 +1297,11 @@ public Response applicationsApplicationIdOauthKeysKeyMappingIdGenerateTokenPost( String username = RestApiCommonUtil.getLoggedInUsername(); APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); Application application = apiConsumer.getApplicationByUUID(applicationId); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); if (application != null) { - if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application)) { + if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) || (orgInfo.getOrganizationSelector() != null + && orgInfo.getOrganizationSelector().equals(application.getSharedOrganization()))) { ApplicationKeyDTO appKey = getApplicationKeyByAppIDAndKeyMapping(applicationId, keyMappingId); if (appKey != null) { String jsonInput = null; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java index 7f6140ed4b55..d89ac2392efd 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java @@ -1293,4 +1293,21 @@ public static String resolveOrganization (HashMap message) throws String organization = resolver.resolve(properties); return organization; } + + public static boolean isOrganizationVisibilityAllowed(String visibleOrgs, String userOrg) { + boolean allowed = false; + + if (StringUtils.isEmpty(visibleOrgs) || APIConstants.DEFAULT_VISIBLE_ORG.equals(visibleOrgs)) { + allowed = true; + } else { + List visibleOrgList = Arrays.asList(visibleOrgs.split(",")); + + if(visibleOrgList.contains(userOrg)) { + allowed = true; + } else { + allowed = false; + } + } + return allowed; + } } From 60c483ec418cc65aa4c921cdc6c4e932e9d383dd Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Fri, 22 Nov 2024 13:35:46 +0530 Subject: [PATCH 29/74] Fix issues related to unit test failures -carbon.apimgt.persistence --- .../RegistryPersistenceImplTestCase.java | 21 +++++++++++++++++-- .../persistence/mapper/APIMapperTestCase.java | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java index a496e38d05ca..01ba1b19ac8a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java @@ -18,6 +18,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.times; +import static org.wso2.carbon.CarbonConstants.REGISTRY_SYSTEM_USERNAME; import java.sql.Timestamp; import java.time.LocalDateTime; @@ -66,6 +67,8 @@ import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.registry.core.session.UserRegistry; +import org.wso2.carbon.registry.indexing.indexer.IndexerException; +import org.wso2.carbon.registry.indexing.solr.SolrClient; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UserRealm; import org.wso2.carbon.user.core.service.RealmService; @@ -75,7 +78,7 @@ @RunWith(PowerMockRunner.class) @PrepareForTest({ CarbonContext.class, RegistryPersistenceUtil.class, ServiceReferenceHolder.class, - PrivilegedCarbonContext.class, GovernanceUtils.class }) + PrivilegedCarbonContext.class, GovernanceUtils.class, SolrClient.class }) public class RegistryPersistenceImplTestCase { private final int SUPER_TENANT_ID = -1234; private final String SUPER_TENANT_DOMAIN = "carbon.super"; @@ -83,7 +86,7 @@ public class RegistryPersistenceImplTestCase { private final String TENANT_DOMAIN = "wso2.com"; @Before - public void setupClass() throws UserStoreException { + public void setupClass() throws UserStoreException, IndexerException { System.setProperty("carbon.home", ""); ServiceReferenceHolder serviceRefHolder = Mockito.mock(ServiceReferenceHolder.class); PowerMockito.mockStatic(ServiceReferenceHolder.class); @@ -100,6 +103,10 @@ public void setupClass() throws UserStoreException { PowerMockito.when(CarbonContext.getThreadLocalCarbonContext()).thenReturn(context); PowerMockito.mockStatic(GovernanceUtils.class); + + SolrClient solrClient = Mockito.mock(SolrClient.class); + PowerMockito.mockStatic(SolrClient.class); + PowerMockito.when(SolrClient.getInstance()).thenReturn(solrClient); } @Test @@ -132,6 +139,9 @@ public void testRegistrySelectionForSuperTenantUser() throws Exception { PowerMockito.when(ServiceReferenceHolder.getInstance()).thenReturn(serviceRefHolder); RealmService realmService = Mockito.mock(RealmService.class); PowerMockito.when(serviceRefHolder.getRealmService()).thenReturn(realmService); + PowerMockito.when(serviceRefHolder.getRegistryService()).thenReturn(registryService); + UserRegistry userRegistry = Mockito.mock(UserRegistry.class); + PowerMockito.when(registryService.getRegistry(REGISTRY_SYSTEM_USERNAME, SUPER_TENANT_ID)).thenReturn(userRegistry); UserRealm realm = Mockito.mock(UserRealm.class); PowerMockito.when(realmService.getTenantUserRealm(SUPER_TENANT_ID)).thenReturn(realm); @@ -193,6 +203,9 @@ public void testRegistrySelectionForTenantUser() throws Exception { PowerMockito.when(ServiceReferenceHolder.getInstance()).thenReturn(serviceRefHolder); RealmService realmService = Mockito.mock(RealmService.class); PowerMockito.when(serviceRefHolder.getRealmService()).thenReturn(realmService); + PowerMockito.when(serviceRefHolder.getRegistryService()).thenReturn(registryService); + UserRegistry userRegistry = Mockito.mock(UserRegistry.class); + PowerMockito.when(registryService.getRegistry(REGISTRY_SYSTEM_USERNAME, TENANT_ID)).thenReturn(userRegistry); UserRealm realm = Mockito.mock(UserRealm.class); PowerMockito.when(realmService.getTenantUserRealm(TENANT_ID)).thenReturn(realm); @@ -257,6 +270,10 @@ public void testRegistrySelectionForTenantUserCrossTenatAccess() throws Exceptio RealmService realmService = Mockito.mock(RealmService.class); PowerMockito.when(serviceRefHolder.getRealmService()).thenReturn(realmService); + PowerMockito.when(serviceRefHolder.getRegistryService()).thenReturn(registryService); + UserRegistry userRegistry = Mockito.mock(UserRegistry.class); + PowerMockito.when(registryService.getRegistry(REGISTRY_SYSTEM_USERNAME, SUPER_TENANT_ID)).thenReturn(userRegistry); + UserRealm realm = Mockito.mock(UserRealm.class); PowerMockito.when(realmService.getTenantUserRealm(TENANT_ID)).thenReturn(realm); PowerMockito.doNothing().when(RegistryPersistenceUtil.class, "loadloadTenantAPIRXT", Mockito.any(String.class), diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapperTestCase.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapperTestCase.java index 5bd205fb9429..4b5a7c10affc 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapperTestCase.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/mapper/APIMapperTestCase.java @@ -105,7 +105,7 @@ public void testAPItoPublisherApiAndBack() throws GovernanceException, APIManage PublisherAPI pubAPI = APIMapper.INSTANCE.toPublisherApi(api); Assert.assertEquals("API name does not match", api.getId().getName(), pubAPI.getApiName()); Assert.assertEquals("API uuid does not match", api.getUuid(), pubAPI.getId()); - Assert.assertTrue("Mapped api does not have status", pubAPI.toString().contains(api.getStatus())); + Assert.assertEquals("Mapped api does not have status", pubAPI.getStatus(), api.getStatus()); API mappedAPI = APIMapper.INSTANCE.toApi(pubAPI); Assert.assertEquals("Mapped api name does not match", mappedAPI.getId().getName(), api.getId().getName()); From 3eafcbc00dcc813b76fe1831f1fa932e90cd6411 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Mon, 25 Nov 2024 03:47:01 +0530 Subject: [PATCH 30/74] Fix issues related to unit test failures - carbon.apimgt.impl --- .../org/wso2/carbon/apimgt/impl/APIConsumerImplTest.java | 7 ++++--- .../wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java | 2 +- pom.xml | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/APIConsumerImplTest.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/APIConsumerImplTest.java index 79123abe8256..17180850614c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/APIConsumerImplTest.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/APIConsumerImplTest.java @@ -530,13 +530,14 @@ public void testUpdateAuthClient() throws APIManagementException { public void testGetApplicationsWithPagination() throws APIManagementException { Application[] applications = new Application[] { new Application(1), new Application(2) }; Mockito.when(apiMgtDAO - .getApplicationsWithPagination((Subscriber) Mockito.any(), Mockito.anyString(), Mockito.anyInt(), + .getApplicationsWithPagination(Mockito.any(), Mockito.anyString(), Mockito.anyInt(), Mockito.anyInt(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), - Mockito.anyString())).thenReturn(applications); + Mockito.anyString(), Mockito.anyString())).thenReturn(applications); APIConsumerImpl apiConsumer = new APIConsumerImplWrapper(apiMgtDAO); Assert.assertEquals( apiConsumer.getApplicationsWithPagination(new Subscriber("sub1"), "1", 0, 5, - "", "", "ASC", "testorg").length, 2); + "", "", "ASC", "testorg", + "sharedOrg").length, 2); } @Test diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java index d55c370503a3..dfdf5cae30de 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java @@ -1828,7 +1828,7 @@ public void testGetAPIRevisionDeploymentsByWorkflowStatusAndApiUUID() throws Exc String apiUUID = "7af95c9d-6177-4191-ab3e-d3f6c1cdc4c2"; String revisionUUID = "821b9664-eeca-4173-9f56-3dc6d46bd6eb"; String deployment = "default"; - Thread.sleep(1000); + Thread.sleep(2000); List apiRevisionDeployments = apiMgtDAO.getAPIRevisionDeploymentsByWorkflowStatusAndApiUUID( apiUUID, workflowStatus); Assert.assertNotNull(apiRevisionDeployments); diff --git a/pom.xml b/pom.xml index 95dcf928b95e..2e1fbb8b763a 100644 --- a/pom.xml +++ b/pom.xml @@ -2083,7 +2083,7 @@ 1.5.3 - 3.2.0 + 3.3.0 1.9.1 1.6.3 From 12961fb290abc1199998b0488466ec01c639d6da Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Mon, 25 Nov 2024 12:44:53 +0530 Subject: [PATCH 31/74] Fix issues related to unit test failures - carbon.apimgt.gateway --- .../OneTimeTokenRevocationMediator.java | 18 ++++++++++-------- .../OneTimeTokenRevocationMediatorTest.java | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java index 30761cc71608..68e6752fe175 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediator.java @@ -61,14 +61,16 @@ public boolean mediate(MessageContext messageContext) { List scopes = authContext.getRequestTokenScopes(); if (StringUtils.isNotBlank(issuer)) { List keyManagerDtoList = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); - KeyManagerDto keyManagerDto = keyManagerDtoList.get(0); // TODO : Does not support multiple km with same - // issuer - - if (keyManagerDto != null && StringUtils.isNotBlank(scope) && scopes.contains(scope)) { - String token = authContext.getAccessToken(); - String consumerKey = authContext.getConsumerKey(); - oneTimeTokenExecutorService.execute(() -> - keyManagerDto.getKeyManager().revokeOneTimeToken(token, consumerKey)); + if (keyManagerDtoList != null) { + KeyManagerDto keyManagerDto = keyManagerDtoList.get(0); // TODO : Does not support multiple km with same + // issuer + + if (keyManagerDto != null && StringUtils.isNotBlank(scope) && scopes.contains(scope)) { + String token = authContext.getAccessToken(); + String consumerKey = authContext.getConsumerKey(); + oneTimeTokenExecutorService.execute(() -> + keyManagerDto.getKeyManager().revokeOneTimeToken(token, consumerKey)); + } } } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java index 913f4f655988..d22a8e09980b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java +++ b/components/apimgt/org.wso2.carbon.apimgt.gateway/src/test/java/org/wso2/carbon/apimgt/gateway/mediators/OneTimeTokenRevocationMediatorTest.java @@ -117,7 +117,7 @@ public void testMediateWithNullIssuer() { * KeyManagerDto is set to null */ @Test - public void testMediateWithNullKeyManagerDto() { + public void testMediateWithNullKeyManagerDtoList() { Mockito.when(KeyManagerHolder.getKeyManagerByIssuer(Mockito.anyString(), Mockito.anyString())). thenReturn(null); From 41002daae6c543f12fe83bb3115df89ebe554f71 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Mon, 25 Nov 2024 16:43:26 +0530 Subject: [PATCH 32/74] Undo expanding waiting time --- .../org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java index dfdf5cae30de..d55c370503a3 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/test/java/org/wso2/carbon/apimgt/impl/dao/test/APIMgtDAOTest.java @@ -1828,7 +1828,7 @@ public void testGetAPIRevisionDeploymentsByWorkflowStatusAndApiUUID() throws Exc String apiUUID = "7af95c9d-6177-4191-ab3e-d3f6c1cdc4c2"; String revisionUUID = "821b9664-eeca-4173-9f56-3dc6d46bd6eb"; String deployment = "default"; - Thread.sleep(2000); + Thread.sleep(1000); List apiRevisionDeployments = apiMgtDAO.getAPIRevisionDeploymentsByWorkflowStatusAndApiUUID( apiUUID, workflowStatus); Assert.assertNotNull(apiRevisionDeployments); From 442cc048b5f638c2d97becdd0b9e9cc7d1038d23 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Mon, 25 Nov 2024 21:58:27 +0530 Subject: [PATCH 33/74] Update language level for apimgt.impl component. This is not affected by the visibility feature. A previously added fix (https://github.com/wso2/carbon-apimgt/commit/7b085185252457e258d6479c12cd1ac40d1642cd) to this component requires language level 9 or later. --- components/apimgt/org.wso2.carbon.apimgt.impl/pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/pom.xml b/components/apimgt/org.wso2.carbon.apimgt.impl/pom.xml index 4d8b4407d821..b027896a161e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/pom.xml +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/pom.xml @@ -646,6 +646,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + From e0c2c6b874fbf5ea4482317679529f3edac78099 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Tue, 26 Nov 2024 12:31:17 +0530 Subject: [PATCH 34/74] Fix unit test related issues --- .../persistence/RegistryPersistenceImpl.java | 4 +- .../RegistryPersistenceImplTestCase.java | 41 ++++++------------- 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 44a1201750ea..fb7a5e98a056 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1168,7 +1168,7 @@ public DevPortalAPISearchResult searchAPIsForDevPortal(Organization org, String return result; } - private List searchDevportalAPIs(String query, int tenantId, Registry reg, int start, int offset) + protected static List searchDevportalAPIs(String query, int tenantId, Registry reg, int start, int offset) throws APIManagementException { List artifacts = new ArrayList(); query = query.replace("PUBLISHED", "published").replace("PROTOTYPED", "prototyped").replace("DEPRECATED", @@ -3165,7 +3165,7 @@ private void updateRegistryResources(Registry registry, String artifactPath, Str } } - protected int getMaxPaginationLimit() { + protected static int getMaxPaginationLimit() { return Integer.MAX_VALUE; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java index 01ba1b19ac8a..ce46bd6f82ed 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/test/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImplTestCase.java @@ -16,6 +16,7 @@ package org.wso2.carbon.apimgt.persistence; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.times; import static org.wso2.carbon.CarbonConstants.REGISTRY_SYSTEM_USERNAME; @@ -78,7 +79,7 @@ @RunWith(PowerMockRunner.class) @PrepareForTest({ CarbonContext.class, RegistryPersistenceUtil.class, ServiceReferenceHolder.class, - PrivilegedCarbonContext.class, GovernanceUtils.class, SolrClient.class }) + PrivilegedCarbonContext.class, GovernanceUtils.class, SolrClient.class, RegistryPersistenceImpl.class }) public class RegistryPersistenceImplTestCase { private final int SUPER_TENANT_ID = -1234; private final String SUPER_TENANT_DOMAIN = "carbon.super"; @@ -86,7 +87,7 @@ public class RegistryPersistenceImplTestCase { private final String TENANT_DOMAIN = "wso2.com"; @Before - public void setupClass() throws UserStoreException, IndexerException { + public void setupClass() throws UserStoreException, IndexerException, APIManagementException { System.setProperty("carbon.home", ""); ServiceReferenceHolder serviceRefHolder = Mockito.mock(ServiceReferenceHolder.class); PowerMockito.mockStatic(ServiceReferenceHolder.class); @@ -102,11 +103,19 @@ public void setupClass() throws UserStoreException, IndexerException { CarbonContext context = Mockito.mock(CarbonContext.class); PowerMockito.when(CarbonContext.getThreadLocalCarbonContext()).thenReturn(context); - PowerMockito.mockStatic(GovernanceUtils.class); - SolrClient solrClient = Mockito.mock(SolrClient.class); PowerMockito.mockStatic(SolrClient.class); PowerMockito.when(SolrClient.getInstance()).thenReturn(solrClient); + + PowerMockito.mockStatic(GovernanceUtils.class); + GovernanceArtifact artifact = Mockito.mock(GovernanceArtifact.class); + List artifacts = new ArrayList(); + artifacts.add(artifact); + + PowerMockito.mockStatic(RegistryPersistenceImpl.class); + PowerMockito.when(RegistryPersistenceImpl.searchDevportalAPIs(anyString(), anyInt(), + any(), anyInt(), anyInt())) + .thenReturn(artifacts); } @Test @@ -124,14 +133,6 @@ public void testRegistrySelectionForSuperTenantUser() throws Exception { PrivilegedCarbonContext privilegedContext = Mockito.mock(PrivilegedCarbonContext.class); PowerMockito.when(PrivilegedCarbonContext.getThreadLocalCarbonContext()).thenReturn(privilegedContext); - PowerMockito.mockStatic(GovernanceUtils.class); - GovernanceArtifact artifact = Mockito.mock(GovernanceArtifact.class); - List artifacts = new ArrayList(); - artifacts.add(artifact); - PowerMockito.when(GovernanceUtils.findGovernanceArtifacts(Mockito.any(String.class), - Mockito.any(Registry.class), Mockito.any(String.class), Mockito.any(Boolean.class))) - .thenReturn(artifacts); - PowerMockito.mockStatic(RegistryPersistenceUtil.class); ServiceReferenceHolder serviceRefHolder = Mockito.mock(ServiceReferenceHolder.class); @@ -188,14 +189,6 @@ public void testRegistrySelectionForTenantUser() throws Exception { PrivilegedCarbonContext privilegedContext = Mockito.mock(PrivilegedCarbonContext.class); PowerMockito.when(PrivilegedCarbonContext.getThreadLocalCarbonContext()).thenReturn(privilegedContext); - PowerMockito.mockStatic(GovernanceUtils.class); - GovernanceArtifact artifact = Mockito.mock(GovernanceArtifact.class); - List artifacts = new ArrayList(); - artifacts.add(artifact); - PowerMockito.when(GovernanceUtils.findGovernanceArtifacts(Mockito.any(String.class), - Mockito.any(Registry.class), Mockito.any(String.class), Mockito.any(Boolean.class))) - .thenReturn(artifacts); - PowerMockito.mockStatic(RegistryPersistenceUtil.class); ServiceReferenceHolder serviceRefHolder = Mockito.mock(ServiceReferenceHolder.class); @@ -254,14 +247,6 @@ public void testRegistrySelectionForTenantUserCrossTenatAccess() throws Exceptio PrivilegedCarbonContext privilegedContext = Mockito.mock(PrivilegedCarbonContext.class); PowerMockito.when(PrivilegedCarbonContext.getThreadLocalCarbonContext()).thenReturn(privilegedContext); - PowerMockito.mockStatic(GovernanceUtils.class); - GovernanceArtifact artifact = Mockito.mock(GovernanceArtifact.class); - List artifacts = new ArrayList(); - artifacts.add(artifact); - PowerMockito.when(GovernanceUtils.findGovernanceArtifacts(Mockito.any(String.class), - Mockito.any(Registry.class), Mockito.any(String.class), Mockito.any(Boolean.class))) - .thenReturn(artifacts); - PowerMockito.mockStatic(RegistryPersistenceUtil.class); ServiceReferenceHolder serviceRefHolder = Mockito.mock(ServiceReferenceHolder.class); From e907f6d1c247caeb69fd7f37fca128494e529397 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Tue, 3 Dec 2024 04:36:44 +0530 Subject: [PATCH 35/74] Fix unified API search for APIs across organizations --- .../wso2/carbon/apimgt/api/APIConsumer.java | 11 ++++ .../carbon/apimgt/impl/APIConsumerImpl.java | 32 +++++++++--- .../persistence/utils/RegistrySearchUtil.java | 51 +++++++++++++++++-- .../store/v1/impl/SearchApiServiceImpl.java | 12 +++-- 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java index 0a41c694beb2..c92b685edafa 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIConsumer.java @@ -904,4 +904,15 @@ boolean isKeyManagerByNameAllowedForUser(String keyManagerName, String organizat */ Map searchPaginatedAPIs(String searchQuery, OrganizationInfo organizationInfo, int start, int end, String sortBy, String sortOrder) throws APIManagementException; + + /** + * @param searchQuery search query + * @param organizationInfo Information about the organization + * @param start + * @param end + * @return + * @throws APIManagementException + */ + Map searchPaginatedContent(String searchQuery, OrganizationInfo organizationInfo, int start, int end) + throws APIManagementException; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 6f723eab0e50..c49ac05d83e6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -4192,6 +4192,31 @@ public API getLightweightAPI(APIIdentifier identifier, String orgId) throws APIM public Map searchPaginatedContent(String searchQuery, String organization, int start, int end) throws APIManagementException { + String userame = (userNameWithoutChange != null) ? userNameWithoutChange : username; + Organization org = new Organization(organization); + Map properties = APIUtil.getUserProperties(userame); + String[] roles = APIUtil.getFilteredUserRoles(userame); + ; + UserContext ctx = new UserContext(userame, org, properties, roles); + return searchPaginatedContent(org, searchQuery, start, end, ctx); + } + + @Override + public Map searchPaginatedContent(String searchQuery, OrganizationInfo organizationInfo, + int start, int end) throws APIManagementException { + + String userName = (userNameWithoutChange != null) ? userNameWithoutChange : username; + Organization org = new Organization(organizationInfo.getSuperOrganization()); + Map properties = APIUtil.getUserProperties(userName); + String[] roles = APIUtil.getFilteredUserRoles(userName); + + UserContext ctx = new UserContext(userName, new Organization(organizationInfo.getOrganizationSelector()), + properties, roles); + return searchPaginatedContent(org, searchQuery, start, end, ctx); + } + + private Map searchPaginatedContent(Organization org, String searchQuery, int start, int end, + UserContext ctx) throws APIManagementException { ArrayList compoundResult = new ArrayList(); Map docMap = new HashMap(); Map result = new HashMap(); @@ -4200,13 +4225,6 @@ public Map searchPaginatedContent(String searchQuery, String org List defSearchList = new ArrayList<>(); int totalLength = 0; - String userame = (userNameWithoutChange != null) ? userNameWithoutChange : username; - Organization org = new Organization(organization); - Map properties = APIUtil.getUserProperties(userame); - String[] roles = APIUtil.getFilteredUserRoles(userame); - ; - UserContext ctx = new UserContext(userame, org, properties, roles); - try { DevPortalContentSearchResult sResults = apiPersistenceInstance.searchContentForDevPortal(org, searchQuery, start, end, ctx); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java index 7b8f51bb7a09..6e329514dc8f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java @@ -61,6 +61,7 @@ public class RegistrySearchUtil { public static final String SOAP_DEFINITION_INDEXER = "org.wso2.carbon.apimgt.impl.indexing.indexer" + ".SOAPAPIDefinitionIndexer"; public static final String STORE_VIEW_ROLES = "store_view_roles"; + public static final String VISIBLE_ORGANIZATIONS = "visible_organizations"; public static final String PUBLISHER_ROLES = "publisher_roles"; public static final String DOCUMENT_MEDIA_TYPE_KEY = "application/vnd.wso2-document\\+xml"; public static final String API_DEF_MEDIA_TYPE_KEY = "application/json"; @@ -241,12 +242,28 @@ private static Map getSearchAttributes(String searchQuery) { String apiState = ""; String publisherRoles = ""; Map attributes = new HashMap(); + String devportalFilterQuery = ""; + String devportalFilterQueryField = ""; for (String searchCriterea : searchQueries) { String[] keyVal = searchCriterea.split("="); if (STORE_VIEW_ROLES.equals(keyVal[0])) { - attributes.put("propertyName", keyVal[0]); - attributes.put("rightPropertyValue", keyVal[1]); - attributes.put("rightOp", "eq"); + if (!StringUtils.isEmpty(keyVal[1])) { + if (StringUtils.isEmpty(devportalFilterQuery)) { + devportalFilterQueryField = STORE_VIEW_ROLES; + devportalFilterQuery = keyVal[1]; + } else { + devportalFilterQuery += (" AND store_view_roles_ss:" + keyVal[1]); + } + } + } else if (VISIBLE_ORGANIZATIONS.equals(keyVal[0])) { + if (!StringUtils.isEmpty(keyVal[1])) { + if (StringUtils.isEmpty(devportalFilterQuery)) { + devportalFilterQueryField = VISIBLE_ORGANIZATIONS; + devportalFilterQuery = keyVal[1]; + } else { + devportalFilterQuery += (" AND visible_organizations_ss:" + keyVal[1]); + } + } } else if (PUBLISHER_ROLES.equals(keyVal[0])) { publisherRoles = keyVal[1]; } else { @@ -258,6 +275,11 @@ private static Map getSearchAttributes(String searchQuery) { attributes.put(keyVal[0], keyVal[1]); } } + if (!StringUtils.isEmpty(devportalFilterQueryField)) { + attributes.put("propertyName", devportalFilterQueryField); + attributes.put("rightPropertyValue", devportalFilterQuery); + attributes.put("rightOp", "eq"); + } //check whether the new document indexer is engaged RegistryConfigLoader registryConfig = RegistryConfigLoader.getInstance(); @@ -431,6 +453,28 @@ private static String getDevPortalRolesWrappedQuery(String query, UserContext co return criteria; } + private static String getOrganizationVisibilityWrappedQuery(String query, UserContext context) { + if (PersistenceUtil.isAdminUser(context)) { + log.debug("Admin user. no modifications to the query"); + return query; + } + + String orgName = context.getOrganization().getName(); + if (orgName != null && orgName.contains(" ")) { + orgName = orgName.replace(" ", "+"); + } + + String criteria = VISIBLE_ORGANIZATIONS + "=" + "(" + APIConstants.DEFAULT_VISIBLE_ORG + " OR " + orgName + ")"; + if (query != null && !query.trim().isEmpty()) { + criteria = criteria + "&" + query; + } + if (log.isDebugEnabled()) { + log.debug("Organization visibility wrapped query : " + criteria); + } + return criteria; + } + + private static String getUserRolesQuery(String[] userRoles, String skippedRoles) { StringBuilder rolesQuery = new StringBuilder(); @@ -597,6 +641,7 @@ public static Map getDevPortalSearchAttributes(String searchQuer modifiedQuery = StringUtils.replaceIgnoreCase(modifiedQuery, searchString, APIConstants.LCSTATE_SEARCH_TYPE_KEY); } + modifiedQuery = RegistrySearchUtil.getOrganizationVisibilityWrappedQuery(modifiedQuery, ctx); modifiedQuery = RegistrySearchUtil.getDevPortalRolesWrappedQuery(modifiedQuery, ctx); modifiedQuery = RegistrySearchUtil.getDevPortalVisibilityWrappedQuery(modifiedQuery, isCrossTenant); Map attributes = RegistrySearchUtil.getSearchAttributes(modifiedQuery); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java index 8707ee31f411..72d566d367ce 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java @@ -27,6 +27,7 @@ import org.wso2.carbon.apimgt.api.model.APIDefinitionContentSearchResult; import org.wso2.carbon.apimgt.api.model.APIProduct; import org.wso2.carbon.apimgt.api.model.Documentation; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.store.v1.SearchApiService; @@ -55,9 +56,12 @@ public Response searchGet(Integer limit, Integer offset, String xWSO2Tenant, Str limit = limit != null ? limit : RestApiConstants.PAGINATION_LIMIT_DEFAULT; offset = offset != null ? offset : RestApiConstants.PAGINATION_OFFSET_DEFAULT; query = query == null ? "*" : query; - String organization = RestApiUtil.getOrganization(messageContext); try { + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + orgInfo.setSuperOrganization(superOrganization); + if (!query.contains(":")) { query = (APIConstants.CONTENT_SEARCH_TYPE_PREFIX + ":" + query); } @@ -66,11 +70,11 @@ public Response searchGet(Integer limit, Integer offset, String xWSO2Tenant, Str APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); Map result = null; // Extracting search queries for the recommendation system - apiConsumer.publishSearchQuery(query, username, organization); + apiConsumer.publishSearchQuery(query, username, superOrganization); if (query.startsWith(APIConstants.CONTENT_SEARCH_TYPE_PREFIX)) { - result = apiConsumer.searchPaginatedContent(query, organization, offset, limit); + result = apiConsumer.searchPaginatedContent(query, orgInfo, offset, limit); } else { - result = apiConsumer.searchPaginatedAPIs(query, organization, offset, limit, null, null); + result = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, limit, null, null); } ArrayList apis; From 946c8932da53af7d9833ac3a3a95a04a3634535c Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Tue, 3 Dec 2024 23:15:34 +0530 Subject: [PATCH 36/74] Fix tag based search --- .../apimgt/persistence/utils/RegistryPersistenceUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index 5a446c469496..96c0d61b0160 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -1938,6 +1938,9 @@ public static Map getFields(String query) { case "group.sort": outputMap.put("group.sort", "overview_" + value); break; + case "tags": + outputMap.put("tags", value); + break; default: // Add any other cases if needed outputMap.put("overview_" + key, value); From 2565f116a689cfba14d9543bf400c8bf02956a95 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Thu, 5 Dec 2024 01:23:01 +0530 Subject: [PATCH 37/74] Fix api state based search --- .../apimgt/persistence/utils/RegistrySearchUtil.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java index 6e329514dc8f..8e9022379637 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java @@ -567,10 +567,14 @@ public static String getDevPortalSearchQuery(String searchQuery, UserContext ctx } } - String apiOverviewStateCriteria = APIConstants.API_OVERVIEW_STATUS_SEARCH_TYPE_KEY; - apiOverviewStateCriteria = apiOverviewStateCriteria + getORBasedSearchCriteria(statusList); + if (!modifiedQuery.startsWith(APIConstants.API_OVERVIEW_STATUS_SEARCH_TYPE_KEY) && !modifiedQuery + .contains(APIConstants.SEARCH_AND_TAG + APIConstants.API_OVERVIEW_STATUS_SEARCH_TYPE_KEY)) { - modifiedQuery = modifiedQuery + APIConstants.SEARCH_AND_TAG + apiOverviewStateCriteria; + String apiOverviewStateCriteria = APIConstants.API_OVERVIEW_STATUS_SEARCH_TYPE_KEY; + apiOverviewStateCriteria = apiOverviewStateCriteria + getORBasedSearchCriteria(statusList); + + modifiedQuery = modifiedQuery + APIConstants.SEARCH_AND_TAG + apiOverviewStateCriteria; + } } modifiedQuery = RegistrySearchUtil.getDevPortalRolesWrappedQuery(extractQuery(modifiedQuery, true), ctx); return modifiedQuery; From 011aab7feb480fbd24d692b9eb974477d43979ce Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Thu, 5 Dec 2024 01:51:53 +0530 Subject: [PATCH 38/74] Fix api category based search --- .../apimgt/persistence/utils/RegistryPersistenceUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index 96c0d61b0160..a4da31c5f9d8 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -1941,6 +1941,9 @@ public static Map getFields(String query) { case "tags": outputMap.put("tags", value); break; + case "apiCategories_categoryName": + outputMap.put("apiCategories_categoryName", value.toLowerCase()); + break; default: // Add any other cases if needed outputMap.put("overview_" + key, value); From f6aae232efaf07590c0121e20c16bfb64e8ce73a Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Mon, 9 Dec 2024 23:26:04 +0530 Subject: [PATCH 39/74] Fix the visibility of API in Store for admin in same domain --- .../rest/api/store/v1/impl/ApisApiServiceImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 743c27516a06..66a4e58bea69 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1177,13 +1177,16 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo String status = api.getStatus(); String visibleOrgs = api.getApi().getVisibleOrganizations(); String userOrg = userOrgInfo.getOrganizationSelector(); - - if (!api.isAPIProduct() && !RestApiUtil.isOrganizationVisibilityAllowed(visibleOrgs, userOrg)) { + + String userName = RestApiCommonUtil.getLoggedInUsername(); + String[] roles = APIUtil.getListOfRoles(APIUtil.getUserNameWithTenantSuffix(userName)); + + if (!api.isAPIProduct() && !(Arrays.asList(roles).contains("admin")) && + !RestApiUtil.isOrganizationVisibilityAllowed(visibleOrgs, userOrg)) { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); } // Extracting clicked API name by the user, for the recommendation system - String userName = RestApiCommonUtil.getLoggedInUsername(); apiConsumer.publishClickedAPI(api, userName, organization); if (APIConstants.PUBLISHED.equals(status) || APIConstants.PROTOTYPED.equals(status) From 134262e8f932948cfeec3ced93debe46e57b8022 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Wed, 11 Dec 2024 02:22:48 +0530 Subject: [PATCH 40/74] Maintain existing behavior when org visibility is not enabled --- .../api/store/v1/impl/ApisApiServiceImpl.java | 15 ++++++----- .../store/v1/impl/SearchApiServiceImpl.java | 15 +++++++++-- .../rest/api/util/utils/RestApiUtil.java | 26 ++++++++++++------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 66a4e58bea69..9ad31f4aff42 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -110,9 +110,14 @@ public Response apisGet(Integer limit, Integer offset, String xWSO2Tenant, Strin //Map allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, superOrganization, offset, // limit, null, null); - Map allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, - limit, null, null); - + Map allMatchedApisMap; + if (APIUtil.isOrganizationAccessControlEnabled()) { + allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, + limit, null, null); + } else { + allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, superOrganization, offset, + limit, null, null); + } Set sortedSet = (Set) allMatchedApisMap.get("apis"); // This is a SortedSet ArrayList allMatchedApis = new ArrayList<>(sortedSet); @@ -1179,10 +1184,8 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo String userOrg = userOrgInfo.getOrganizationSelector(); String userName = RestApiCommonUtil.getLoggedInUsername(); - String[] roles = APIUtil.getListOfRoles(APIUtil.getUserNameWithTenantSuffix(userName)); - if (!api.isAPIProduct() && !(Arrays.asList(roles).contains("admin")) && - !RestApiUtil.isOrganizationVisibilityAllowed(visibleOrgs, userOrg)) { + if (!api.isAPIProduct() && !RestApiUtil.isOrganizationVisibilityAllowed(userName,visibleOrgs, userOrg)) { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java index 72d566d367ce..1af887badaf6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SearchApiServiceImpl.java @@ -29,6 +29,7 @@ import org.wso2.carbon.apimgt.api.model.Documentation; import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.store.v1.SearchApiService; import org.wso2.carbon.apimgt.rest.api.store.v1.dto.SearchResultDTO; @@ -71,10 +72,20 @@ public Response searchGet(Integer limit, Integer offset, String xWSO2Tenant, Str Map result = null; // Extracting search queries for the recommendation system apiConsumer.publishSearchQuery(query, username, superOrganization); + boolean isOrganizationSupportEnabled = APIUtil.isOrganizationAccessControlEnabled(); if (query.startsWith(APIConstants.CONTENT_SEARCH_TYPE_PREFIX)) { - result = apiConsumer.searchPaginatedContent(query, orgInfo, offset, limit); + if (isOrganizationSupportEnabled) { + result = apiConsumer.searchPaginatedContent(query, orgInfo, offset, limit); + } else { + result = apiConsumer.searchPaginatedContent(query, superOrganization, offset, limit); + } } else { - result = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, limit, null, null); + if (isOrganizationSupportEnabled) { + result = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, limit, null, null); + } else { + result = apiConsumer.searchPaginatedAPIs(query, superOrganization, offset, limit, null, + null); + } } ArrayList apis; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java index d89ac2392efd..759f913672c6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/utils/RestApiUtil.java @@ -1294,20 +1294,28 @@ public static String resolveOrganization (HashMap message) throws return organization; } - public static boolean isOrganizationVisibilityAllowed(String visibleOrgs, String userOrg) { + public static boolean isOrganizationVisibilityAllowed(String userName, String visibleOrgs, String userOrg) + throws APIManagementException { boolean allowed = false; - if (StringUtils.isEmpty(visibleOrgs) || APIConstants.DEFAULT_VISIBLE_ORG.equals(visibleOrgs)) { - allowed = true; - } else { - List visibleOrgList = Arrays.asList(visibleOrgs.split(",")); - - if(visibleOrgList.contains(userOrg)) { + if (APIUtil.isOrganizationAccessControlEnabled()) { + String[] roles = APIUtil.getListOfRoles(APIUtil.getUserNameWithTenantSuffix(userName)); + if (Arrays.asList(roles).contains("admin")) { + return true; + } + if (StringUtils.isEmpty(visibleOrgs) || APIConstants.DEFAULT_VISIBLE_ORG.equals(visibleOrgs)) { allowed = true; } else { - allowed = false; + List visibleOrgList = Arrays.asList(visibleOrgs.split(",")); + + if (visibleOrgList.contains(userOrg)) { + allowed = true; + } else { + allowed = false; + } } + return allowed; } - return allowed; + return true; } } From a237ec86a90923688bff3c073f610173262e7444 Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Thu, 12 Dec 2024 16:59:54 +0530 Subject: [PATCH 41/74] save visibility value as a property for api artifacts --- .../persistence/RegistryPersistenceImpl.java | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index fb7a5e98a056..ef5d36617dbb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -197,6 +197,7 @@ public PublisherAPI addAPI(Organization org, PublisherAPI publisherAPI) throws A } resource.setContent(api.getSwaggerDefinition()); resource.setMediaType("application/json"); + resource.setProperty(APIConstants.VISIBLE_ORGANIZATIONS, visibleOrgs); registry.put(resourcePath, resource); //Need to set anonymous if the visibility is public RegistryPersistenceUtil.clearResourcePermissions(resourcePath, api.getId(), @@ -217,6 +218,7 @@ public PublisherAPI addAPI(Organization org, PublisherAPI publisherAPI) throws A } resource.setContent(api.getAsyncApiDefinition()); resource.setMediaType(APIConstants.APPLICATION_JSON_MEDIA_TYPE); //add a constant for app.json + resource.setProperty(APIConstants.VISIBLE_ORGANIZATIONS, visibleOrgs); registry.put(resourcePath, resource); RegistryPersistenceUtil.clearResourcePermissions(resourcePath, api.getId(), ((UserRegistry) registry).getTenantId()); @@ -231,6 +233,7 @@ public PublisherAPI addAPI(Organization org, PublisherAPI publisherAPI) throws A ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, docLocation); + updateRegistryResourcesForArtifacts(registry, artifact.getId(), docLocation); registry.commitTransaction(); api.setUuid(artifact.getId()); @@ -606,6 +609,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); } // Update api def file permissions, required for API definition content search functionality @@ -619,6 +623,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); } } else if (api.isAsync()) { String resourcePath = RegistryPersistenceUtil.getOpenAPIDefinitionFilePath(api.getId().getName(), @@ -629,6 +634,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); } } else if (APIConstants.API_TYPE_SOAP.equals(api.getType())) { String resourcePath = RegistryPersistenceUtil.getOpenAPIDefinitionFilePath(api.getId().getName(), @@ -640,6 +646,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); } } @@ -675,6 +682,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw + doc.getName(); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, documentationPath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), documentationPath); if (Documentation.DocumentSourceType.INLINE.equals(doc.getSourceType()) || Documentation.DocumentSourceType.MARKDOWN.equals(doc.getSourceType())) { @@ -683,12 +691,14 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw + RegistryConstants.PATH_SEPARATOR + doc.getName(); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, contentPath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), contentPath); } else if (Documentation.DocumentSourceType.FILE.equals(doc.getSourceType()) && doc.getFilePath() != null) { String filePath = RegistryPersistenceDocUtil.getDocumentationFilePath(api.getId(), doc.getFilePath().split("files" + RegistryConstants.PATH_SEPARATOR)[1]); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, filePath, registry); + updateRegistryResourcesForArtifacts(registry, api.getUuid(), filePath); } } } @@ -1961,6 +1971,7 @@ public void saveWSDL(Organization org, String apiId, ResourceFile wsdlResourceFi if (visibleRolesList != null) { visibleRoles = visibleRolesList.split(","); } + updateRegistryResourcesForArtifacts(registry, apiId, wsdlResourcePath); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, visibleRoles, wsdlResourcePath, registry); @@ -2113,6 +2124,7 @@ public void saveOASDefinition(Organization org, String apiId, String apiDefiniti // Need to set anonymous if the visibility is public RegistryPersistenceUtil.clearResourcePermissions(resourcePath, new APIIdentifier(apiProviderName, apiName, apiVersion), ((UserRegistry) registry).getTenantId()); + updateRegistryResourcesForArtifacts(registry, apiId, resourcePath); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, visibleRolesArr, resourcePath, registry); @@ -2213,7 +2225,7 @@ public void saveAsyncDefinition(Organization org, String apiId, String apiDefini ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, visibleRolesArr, resourcePath , registry); - + updateRegistryResourcesForArtifacts(registry, apiId, resourcePath); } catch (RegistryException | APIPersistenceException | APIManagementException e) { throw new AsyncSpecPersistenceException("Error while adding AsyncApi Definition for " + apiId, e); } finally { @@ -2304,6 +2316,7 @@ public void saveGraphQLSchemaDefinition(Organization org, String apiId, String s ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.apiProvider, api.visibility, api.visibleRoles, saveResourcePath, registry); + updateRegistryResourcesForArtifacts(registry, apiId, saveResourcePath); } catch (RegistryException | APIManagementException | APIPersistenceException e) { throw new GraphQLPersistenceException("Error while adding Graphql Definition for api " + apiId, e); @@ -2369,9 +2382,10 @@ public Documentation addDocumentation(Organization org, String apiId, Documentat GenericArtifactManager docArtifactManager = new GenericArtifactManager(registry, APIConstants.DOCUMENTATION_KEY); GenericArtifact docArtifact = docArtifactManager.newGovernanceArtifact(new QName(documentation.getName())); - docArtifactManager.addGenericArtifact(RegistryPersistenceDocUtil.createDocArtifactContent(docArtifact, - apiName, apiVersion, apiProviderName, documentation)); - + GenericArtifact genericDocArtifact = RegistryPersistenceDocUtil.createDocArtifactContent(docArtifact, + apiName, apiVersion, apiProviderName, documentation); + docArtifactManager.addGenericArtifact(genericDocArtifact); + String docArtifactPath = GovernanceUtils.getArtifactPath(registry, genericDocArtifact.getId()); String apiPath = RegistryPersistenceUtil.getAPIPath(apiName, apiVersion, apiProviderName); String docVisibility = documentation.getVisibility().name(); String[] authorizedRoles = RegistryPersistenceUtil.getAuthorizedRoles(apiPath, tenantDomain); @@ -2385,6 +2399,7 @@ public Documentation addDocumentation(Organization org, String apiId, Documentat visibility = APIConstants.DOC_OWNER_VISIBILITY; } } + updateRegistryResourcesForArtifacts(registry, apiId, docArtifactPath); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, docArtifact .getPath(), registry); String docFilePath = docArtifact.getAttribute(APIConstants.DOC_FILE_PATH); @@ -2398,6 +2413,7 @@ public Documentation addDocumentation(Organization org, String apiId, Documentat String filePath = docFilePath.substring(startIndex, docFilePath.length()); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, filePath, registry); + updateRegistryResourcesForArtifacts(registry, apiId, filePath); } } documentation.setId(docArtifact.getId()); @@ -2457,6 +2473,7 @@ public Documentation updateDocumentation(Organization org, String apiId, Documen RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, artifact.getPath(), registry); + updateRegistryResourcesForArtifacts(registry, apiId, artifact.getPath()); String docFilePath = artifact.getAttribute(APIConstants.DOC_FILE_PATH); if (docFilePath != null && !"".equals(docFilePath)) { @@ -2469,6 +2486,7 @@ public Documentation updateDocumentation(Organization org, String apiId, Documen String filePath = docFilePath.substring(startIndex, docFilePath.length()); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, filePath, registry); + updateRegistryResourcesForArtifacts(registry, apiId, filePath); } return documentation; } catch (RegistryException | APIManagementException | APIPersistenceException e) { @@ -2638,6 +2656,7 @@ public DocumentContent addDocumentationContent(Organization org, String apiId, S RegistryPersistenceUtil.setResourcePermissions( RegistryPersistenceUtil.replaceEmailDomain(apiProviderName), visibility, visibleRoles, filePath, registry); + updateRegistryResourcesForArtifacts(registry, apiId, filePath); //documentation.setFilePath(addResourceFile(apiId, filePath, icon)); String savedFilePath = addResourceFile(filePath, resource, registry, tenantDomain); //doc.setFilePath(savedFilePath); @@ -2677,6 +2696,7 @@ public DocumentContent addDocumentationContent(Organization org, String apiId, S } RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, contentPath, registry); + updateRegistryResourcesForArtifacts(registry, apiId, contentPath); GenericArtifact updateDocArtifact = RegistryPersistenceDocUtil.createDocArtifactContent(docArtifact, apiProviderName, apiName, apiVersion, doc); Boolean toggle = Boolean.parseBoolean(updateDocArtifact.getAttribute("toggle")); @@ -3165,6 +3185,31 @@ private void updateRegistryResources(Registry registry, String artifactPath, Str } } + private void updateRegistryResourcesForArtifacts(Registry registry, String apiId, String artifactResourcePath) + throws RegistryException { + + //get path to API in registry + String artifactPath = GovernanceUtils.getArtifactPath(registry, apiId); + + //get API + Resource apiResource = registry.get(artifactPath); + + //get orgs of the API + String visibleOrgs = apiResource.getProperty(APIConstants.VISIBLE_ORGANIZATIONS); + + //add the org value for api-artifact in the registry + if (registry.resourceExists(artifactResourcePath)) { + Resource artifactResource = registry.get(artifactResourcePath); + if (artifactResource != null) { + if (!StringUtils.isEmpty(visibleOrgs) && visibleOrgs.contains(" ")) { + visibleOrgs = visibleOrgs.replace(" ", "+"); + } + artifactResource.setProperty(APIConstants.VISIBLE_ORGANIZATIONS, visibleOrgs); + registry.put(artifactResourcePath, artifactResource); + } + } + } + protected static int getMaxPaginationLimit() { return Integer.MAX_VALUE; @@ -3411,7 +3456,8 @@ public PublisherAPIProduct addAPIProduct(Organization org, PublisherAPIProduct p String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; // if (StringUtils.isEmpty(apiProduct.getVisibleOrganizations())) { - //visibleOrgs = apiProduct.getVisibleOrganizations(); TODO fix for products + //visibleOrgs = apiProduct.getVisibleOrganizations(); + // TODO fix for products and do needful for unified search // } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), apiProduct.getAdditionalProperties(), visibleOrgs); @@ -3641,7 +3687,8 @@ public PublisherAPIProduct updateAPIProduct(Organization org, PublisherAPIProduc String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; // if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ - //visibleOrgs = apiProduct.getVisibleOrganizations(); TODO fix for products + //visibleOrgs = apiProduct.getVisibleOrganizations(); + // TODO fix for products and do needful for unified search // } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), apiProduct.getAdditionalProperties(), visibleOrgs); From 99ecfb4cfa20f3ea9104af395fee66e2c9bb4e8a Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Fri, 27 Dec 2024 11:36:52 +0530 Subject: [PATCH 42/74] Introduce constants for search attribute fields --- .../apimgt/persistence/utils/RegistrySearchUtil.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java index 8e9022379637..4ebcc39f3b48 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistrySearchUtil.java @@ -51,6 +51,7 @@ public class RegistrySearchUtil { public static final String SEARCH_AND_TAG = "&"; public static final String TAGS_SEARCH_TYPE_PREFIX = "tags"; public static final String NAME_TYPE_PREFIX = "name"; + public static final String AND_WITH_SPACES = " AND "; public static final String API_STATUS = "STATUS"; public static final String API_PROVIDER = "Provider"; public static final String DOCUMENT_INDEXER = "org.wso2.carbon.apimgt.impl.indexing.indexer.DocumentIndexer"; @@ -61,7 +62,9 @@ public class RegistrySearchUtil { public static final String SOAP_DEFINITION_INDEXER = "org.wso2.carbon.apimgt.impl.indexing.indexer" + ".SOAPAPIDefinitionIndexer"; public static final String STORE_VIEW_ROLES = "store_view_roles"; + public static final String STORE_VIEW_ROLES_FIELD = "store_view_roles_ss:"; public static final String VISIBLE_ORGANIZATIONS = "visible_organizations"; + public static final String VISIBLE_ORGANIZATIONS_FIELD = "visible_organizations_ss:"; public static final String PUBLISHER_ROLES = "publisher_roles"; public static final String DOCUMENT_MEDIA_TYPE_KEY = "application/vnd.wso2-document\\+xml"; public static final String API_DEF_MEDIA_TYPE_KEY = "application/json"; @@ -252,7 +255,7 @@ private static Map getSearchAttributes(String searchQuery) { devportalFilterQueryField = STORE_VIEW_ROLES; devportalFilterQuery = keyVal[1]; } else { - devportalFilterQuery += (" AND store_view_roles_ss:" + keyVal[1]); + devportalFilterQuery += (AND_WITH_SPACES + STORE_VIEW_ROLES_FIELD + keyVal[1]); } } } else if (VISIBLE_ORGANIZATIONS.equals(keyVal[0])) { @@ -261,7 +264,7 @@ private static Map getSearchAttributes(String searchQuery) { devportalFilterQueryField = VISIBLE_ORGANIZATIONS; devportalFilterQuery = keyVal[1]; } else { - devportalFilterQuery += (" AND visible_organizations_ss:" + keyVal[1]); + devportalFilterQuery += (AND_WITH_SPACES + VISIBLE_ORGANIZATIONS_FIELD + keyVal[1]); } } } else if (PUBLISHER_ROLES.equals(keyVal[0])) { From 354b156a0c74ab491796a96668cf0db5e34fe02f Mon Sep 17 00:00:00 2001 From: rusirijayodaillesinghe Date: Fri, 27 Dec 2024 13:19:03 +0530 Subject: [PATCH 43/74] Refactor the function which adds org visibility value for API Artifacts --- .../persistence/RegistryPersistenceImpl.java | 82 +++++++++++-------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index ef5d36617dbb..508feb6bb1ad 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -54,7 +54,6 @@ import org.wso2.carbon.governance.api.exception.GovernanceException; import org.wso2.carbon.governance.api.generic.GenericArtifactManager; import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; -import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifactImpl; import org.wso2.carbon.governance.api.util.GovernanceUtils; import org.wso2.carbon.registry.common.ResourceData; import org.wso2.carbon.registry.common.TermData; @@ -233,7 +232,7 @@ public PublisherAPI addAPI(Organization org, PublisherAPI publisherAPI) throws A ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, docLocation); - updateRegistryResourcesForArtifacts(registry, artifact.getId(), docLocation); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, docLocation); registry.commitTransaction(); api.setUuid(artifact.getId()); @@ -609,7 +608,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, resourcePath); } // Update api def file permissions, required for API definition content search functionality @@ -623,7 +622,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, resourcePath); } } else if (api.isAsync()) { String resourcePath = RegistryPersistenceUtil.getOpenAPIDefinitionFilePath(api.getId().getName(), @@ -634,7 +633,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, resourcePath); } } else if (APIConstants.API_TYPE_SOAP.equals(api.getType())) { String resourcePath = RegistryPersistenceUtil.getOpenAPIDefinitionFilePath(api.getId().getName(), @@ -646,7 +645,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, resourcePath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), resourcePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, resourcePath); } } @@ -682,7 +681,7 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw + doc.getName(); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, documentationPath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), documentationPath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, documentationPath); if (Documentation.DocumentSourceType.INLINE.equals(doc.getSourceType()) || Documentation.DocumentSourceType.MARKDOWN.equals(doc.getSourceType())) { @@ -691,14 +690,14 @@ public PublisherAPI updateAPI(Organization org, PublisherAPI publisherAPI) throw + RegistryConstants.PATH_SEPARATOR + doc.getName(); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, contentPath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), contentPath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, contentPath); } else if (Documentation.DocumentSourceType.FILE.equals(doc.getSourceType()) && doc.getFilePath() != null) { String filePath = RegistryPersistenceDocUtil.getDocumentationFilePath(api.getId(), doc.getFilePath().split("files" + RegistryConstants.PATH_SEPARATOR)[1]); RegistryPersistenceUtil.setResourcePermissions(api.getId().getProviderName(), api.getVisibility(), visibleRoles, filePath, registry); - updateRegistryResourcesForArtifacts(registry, api.getUuid(), filePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, filePath); } } } @@ -1971,7 +1970,8 @@ public void saveWSDL(Organization org, String apiId, ResourceFile wsdlResourceFi if (visibleRolesList != null) { visibleRoles = visibleRolesList.split(","); } - updateRegistryResourcesForArtifacts(registry, apiId, wsdlResourcePath); + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, wsdlResourcePath); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, visibleRoles, wsdlResourcePath, registry); @@ -2124,7 +2124,8 @@ public void saveOASDefinition(Organization org, String apiId, String apiDefiniti // Need to set anonymous if the visibility is public RegistryPersistenceUtil.clearResourcePermissions(resourcePath, new APIIdentifier(apiProviderName, apiName, apiVersion), ((UserRegistry) registry).getTenantId()); - updateRegistryResourcesForArtifacts(registry, apiId, resourcePath); + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, resourcePath); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, visibleRolesArr, resourcePath, registry); @@ -2225,7 +2226,8 @@ public void saveAsyncDefinition(Organization org, String apiId, String apiDefini ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, visibleRolesArr, resourcePath , registry); - updateRegistryResourcesForArtifacts(registry, apiId, resourcePath); + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, resourcePath); } catch (RegistryException | APIPersistenceException | APIManagementException e) { throw new AsyncSpecPersistenceException("Error while adding AsyncApi Definition for " + apiId, e); } finally { @@ -2316,7 +2318,8 @@ public void saveGraphQLSchemaDefinition(Organization org, String apiId, String s ((UserRegistry) registry).getTenantId()); RegistryPersistenceUtil.setResourcePermissions(api.apiProvider, api.visibility, api.visibleRoles, saveResourcePath, registry); - updateRegistryResourcesForArtifacts(registry, apiId, saveResourcePath); + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, saveResourcePath); } catch (RegistryException | APIManagementException | APIPersistenceException e) { throw new GraphQLPersistenceException("Error while adding Graphql Definition for api " + apiId, e); @@ -2399,7 +2402,9 @@ public Documentation addDocumentation(Organization org, String apiId, Documentat visibility = APIConstants.DOC_OWNER_VISIBILITY; } } - updateRegistryResourcesForArtifacts(registry, apiId, docArtifactPath); + //Get org visibility value + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, docArtifactPath); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, docArtifact .getPath(), registry); String docFilePath = docArtifact.getAttribute(APIConstants.DOC_FILE_PATH); @@ -2413,7 +2418,7 @@ public Documentation addDocumentation(Organization org, String apiId, Documentat String filePath = docFilePath.substring(startIndex, docFilePath.length()); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, filePath, registry); - updateRegistryResourcesForArtifacts(registry, apiId, filePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, filePath); } } documentation.setId(docArtifact.getId()); @@ -2464,6 +2469,8 @@ public Documentation updateDocumentation(Organization org, String apiId, Documen visibility = APIConstants.DOC_OWNER_VISIBILITY; } } + // Get org visibility value + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); GenericArtifact updateApiArtifact = RegistryPersistenceDocUtil.createDocArtifactContent(artifact, apiProviderName, apiName, apiVersion, documentation); @@ -2473,7 +2480,7 @@ public Documentation updateDocumentation(Organization org, String apiId, Documen RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, artifact.getPath(), registry); - updateRegistryResourcesForArtifacts(registry, apiId, artifact.getPath()); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, artifact.getPath()); String docFilePath = artifact.getAttribute(APIConstants.DOC_FILE_PATH); if (docFilePath != null && !"".equals(docFilePath)) { @@ -2486,7 +2493,7 @@ public Documentation updateDocumentation(Organization org, String apiId, Documen String filePath = docFilePath.substring(startIndex, docFilePath.length()); RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, filePath, registry); - updateRegistryResourcesForArtifacts(registry, apiId, filePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, filePath); } return documentation; } catch (RegistryException | APIManagementException | APIPersistenceException e) { @@ -2642,7 +2649,7 @@ public DocumentContent addDocumentationContent(Organization org, String apiId, S .getDocumentArtifactManager(registry); GenericArtifact docArtifact = docArtifactManager.getGenericArtifact(docId); Documentation doc = RegistryPersistenceDocUtil.getDocumentation(docArtifact); - + String visibleOrgs = getOrganizationVisibilityForApiArtifact(registry, apiId); if (DocumentContent.ContentSourceType.FILE.equals(content.getSourceType())) { ResourceFile resource = content.getResourceFile(); String filePath = RegistryPersistenceDocUtil.getDocumentFilePath(apiProviderName, apiName, apiVersion, @@ -2656,7 +2663,7 @@ public DocumentContent addDocumentationContent(Organization org, String apiId, S RegistryPersistenceUtil.setResourcePermissions( RegistryPersistenceUtil.replaceEmailDomain(apiProviderName), visibility, visibleRoles, filePath, registry); - updateRegistryResourcesForArtifacts(registry, apiId, filePath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, filePath); //documentation.setFilePath(addResourceFile(apiId, filePath, icon)); String savedFilePath = addResourceFile(filePath, resource, registry, tenantDomain); //doc.setFilePath(savedFilePath); @@ -2696,7 +2703,7 @@ public DocumentContent addDocumentationContent(Organization org, String apiId, S } RegistryPersistenceUtil.setResourcePermissions(apiProviderName, visibility, authorizedRoles, contentPath, registry); - updateRegistryResourcesForArtifacts(registry, apiId, contentPath); + updateOrgVisibilityValueInRegistryForArtifacts(visibleOrgs, registry, contentPath); GenericArtifact updateDocArtifact = RegistryPersistenceDocUtil.createDocArtifactContent(docArtifact, apiProviderName, apiName, apiVersion, doc); Boolean toggle = Boolean.parseBoolean(updateDocArtifact.getAttribute("toggle")); @@ -3185,19 +3192,15 @@ private void updateRegistryResources(Registry registry, String artifactPath, Str } } - private void updateRegistryResourcesForArtifacts(Registry registry, String apiId, String artifactResourcePath) - throws RegistryException { - - //get path to API in registry - String artifactPath = GovernanceUtils.getArtifactPath(registry, apiId); - - //get API - Resource apiResource = registry.get(artifactPath); - - //get orgs of the API - String visibleOrgs = apiResource.getProperty(APIConstants.VISIBLE_ORGANIZATIONS); - - //add the org value for api-artifact in the registry + /** + * Adds the organization visibility value to api-artifact in the registry + * @param visibleOrgs Organization that the corresponding API should be visible to + * @param registry + * @param artifactResourcePath + * @throws RegistryException + */ + private void updateOrgVisibilityValueInRegistryForArtifacts(String visibleOrgs, Registry registry, + String artifactResourcePath) throws RegistryException { if (registry.resourceExists(artifactResourcePath)) { Resource artifactResource = registry.get(artifactResourcePath); if (artifactResource != null) { @@ -4334,4 +4337,17 @@ private void setAPITypeForSwagger(String resourcePath, int index, } } } + + private String getOrganizationVisibilityForApiArtifact(Registry registry, String apiId) throws RegistryException { + /*Get org visibility value*/ + String artifactPath = GovernanceUtils.getArtifactPath(registry, apiId); + //get API + Resource apiResource = registry.get(artifactPath); + //get orgs of the API + String visibleOrgs = apiResource.getProperty(APIConstants.VISIBLE_ORGANIZATIONS); + if (StringUtils.isEmpty(visibleOrgs)) { + visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; + } + return visibleOrgs; + } } From 012f9f54ea420713998eccdc52971d17a7997be2 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 7 Jan 2025 15:43:28 +0530 Subject: [PATCH 44/74] Fix NPE in product listing in dev portal --- .../apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 9ad31f4aff42..6206ec43427d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1180,12 +1180,12 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo APIConsumer apiConsumer = RestApiCommonUtil.getLoggedInUserConsumer(); ApiTypeWrapper api = apiConsumer.getAPIorAPIProductByUUID(apiId, organization); String status = api.getStatus(); - String visibleOrgs = api.getApi().getVisibleOrganizations(); String userOrg = userOrgInfo.getOrganizationSelector(); String userName = RestApiCommonUtil.getLoggedInUsername(); - if (!api.isAPIProduct() && !RestApiUtil.isOrganizationVisibilityAllowed(userName,visibleOrgs, userOrg)) { + if (!api.isAPIProduct() && !RestApiUtil.isOrganizationVisibilityAllowed(userName, + api.getApi().getVisibleOrganizations(), userOrg)) { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); } From 336937472407e5685bcf2ddbd9f23d0a863ae5b4 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Wed, 8 Jan 2025 13:43:34 +0530 Subject: [PATCH 45/74] Fix dev portal rest api search --- .../apimgt/persistence/utils/RegistryPersistenceUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index a4da31c5f9d8..3831fbf3b1b9 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -1946,7 +1946,7 @@ public static Map getFields(String query) { break; default: // Add any other cases if needed - outputMap.put("overview_" + key, value); + outputMap.put("overview_" + key, value.toLowerCase()); break; } } From 8a25a7706241edc2434657e69ed34c077d34c1f7 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Fri, 10 Jan 2025 16:06:51 +0530 Subject: [PATCH 46/74] Fix duplicate keymanager name issue --- .../apimgt/impl/dto/OrganizationKeyManagerDto.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java index df279f62ea9c..45a6ca4ee0ff 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrganizationKeyManagerDto.java @@ -23,14 +23,16 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; public class OrganizationKeyManagerDto { private Map keyManagerMap = new LinkedHashMap<>(); - private Map> issuerNameMap = new HashMap<>(); + private Map> issuerNameMap = new HashMap<>(); public Map getKeyManagerMap() { @@ -53,7 +55,7 @@ public void putKeyManagerDto(KeyManagerDto keyManagerDto) { } else { keyManagerMap.put(keyManagerDto.getName(), keyManagerDto); } - issuerNameMap.computeIfAbsent(keyManagerDto.getIssuer(), k -> new ArrayList<>()).add(keyManagerDto.getName()); + issuerNameMap.computeIfAbsent(keyManagerDto.getIssuer(), k -> new HashSet<>()).add(keyManagerDto.getName()); } @@ -71,9 +73,10 @@ public void removeKeyManagerDtoByName(String name) { public JWTValidator getJWTValidatorByIssuer(String issuer) { - List keyManagerNames = issuerNameMap.get(issuer); + Set keyManagerNames = issuerNameMap.get(issuer); if (keyManagerNames != null && !keyManagerNames.isEmpty()) { - KeyManagerDto keyManagerDto = keyManagerMap.get(keyManagerNames.get(0)); + String keyManagerName = keyManagerNames.iterator().next(); + KeyManagerDto keyManagerDto = keyManagerMap.get(keyManagerName); if (keyManagerDto != null) { return keyManagerDto.getJwtValidator(); } @@ -84,7 +87,7 @@ public JWTValidator getJWTValidatorByIssuer(String issuer) { public List getKeyManagerDtoByIssuer(String issuer) { List dtoList = new ArrayList(); - List keyManagerNames = issuerNameMap.get(issuer); + Set keyManagerNames = issuerNameMap.get(issuer); if (keyManagerNames != null && !keyManagerNames.isEmpty()) { for (String keyManagerName : keyManagerNames) { dtoList.add(keyManagerMap.get(keyManagerName)); From b58d3a2ebad64c7ac2aee003a0cbc59b4ddca40a Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Sat, 11 Jan 2025 12:05:01 +0530 Subject: [PATCH 47/74] Fix NPE --- .../impl/jwt/JWTValidationServiceImpl.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java index 52eecbb825c8..6d094179d104 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/jwt/JWTValidationServiceImpl.java @@ -71,13 +71,15 @@ public String getKeyManagerNameIfJwtValidatorExist(SignedJWTInfo signedJWTInfo) String issuer = signedJWTInfo.getJwtClaimsSet().getIssuer(); List keyManagerDtoList = KeyManagerHolder.getKeyManagerByIssuer(tenantDomain, issuer); KeyManagerDto keyManagerDto = null; - if (keyManagerDtoList.size() == 1) { // only one keymanager. no need to check if it can handle token - keyManagerDto = keyManagerDtoList.get(0); - } else { - for (KeyManagerDto kmrDto : keyManagerDtoList) { - if (kmrDto.getKeyManager().canHandleToken(signedJWTInfo.getToken())) { - keyManagerDto = kmrDto; - break; + if (keyManagerDtoList != null) { + if (keyManagerDtoList.size() == 1) { // only one keymanager. no need to check if it can handle token + keyManagerDto = keyManagerDtoList.get(0); + } else { + for (KeyManagerDto kmrDto : keyManagerDtoList) { + if (kmrDto.getKeyManager().canHandleToken(signedJWTInfo.getToken())) { + keyManagerDto = kmrDto; + break; + } } } } From 40ba28584112fe35a265d3834501557f8176a7dc Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 16 Jan 2025 21:09:32 +0530 Subject: [PATCH 48/74] Remove org visibilty in business policy --- .../api/model/policy/SubscriptionPolicy.java | 23 ++------ .../wso2/carbon/apimgt/impl/APIConstants.java | 1 - .../carbon/apimgt/impl/APIConsumerImpl.java | 1 - .../apimgt/impl/ThrottlePolicyConstants.java | 3 +- .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 55 ------------------- .../impl/dao/constants/SQLConstants.java | 15 ----- .../carbon/apimgt/impl/utils/APIUtil.java | 17 ------ .../SubscriptionThrottlePolicyAllOfDTO.java | 24 +------- .../v1/dto/SubscriptionThrottlePolicyDTO.java | 24 +------- ...SubscriptionThrottlePolicyMappingUtil.java | 2 - .../src/main/resources/admin-api.yaml | 4 -- .../src/main/resources/admin-api.yaml | 4 -- .../api/store/v1/impl/ApisApiServiceImpl.java | 7 --- .../src/main/resources/sql/h2.sql | 7 --- 14 files changed, 11 insertions(+), 176 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java index 32c4b046d4cb..7a8d4340d1ce 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/policy/SubscriptionPolicy.java @@ -18,10 +18,8 @@ package org.wso2.carbon.apimgt.api.model.policy; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; public class SubscriptionPolicy extends Policy { @@ -36,7 +34,6 @@ public class SubscriptionPolicy extends Policy { private String tierQuotaType; private int graphQLMaxDepth; private int graphQLMaxComplexity; - private List allowedOrganizations = new ArrayList(); public SubscriptionPolicy(String name) { super(name); @@ -125,11 +122,11 @@ public void setGraphQLMaxComplexity(int graphQLMaxComplexity) { @Override public String toString() { return "SubscriptionPolicy [rateLimitCount=" + rateLimitCount + ", rateLimitTimeUnit=" + rateLimitTimeUnit - + ", subscriberCount=" + subscriberCount + ", customAttributes=" + Arrays.toString(customAttributes) - + ", stopOnQuotaReach=" + stopOnQuotaReach + ", billingPlan=" + billingPlan + ", monetizationPlan=" - + monetizationPlan + ", monetizationPlanProperties=" + monetizationPlanProperties + ", tierQuotaType=" - + tierQuotaType + ", graphQLMaxDepth=" + graphQLMaxDepth + ", graphQLMaxComplexity=" - + graphQLMaxComplexity + ", allowedOrganizations=" + allowedOrganizations + "]"; + + ", customAttributes=" + Arrays.toString(customAttributes) + ", stopOnQuotaReach=" + stopOnQuotaReach + + ", billingPlan=" + billingPlan + ", monetizationPlan=" + monetizationPlan + + ", monetizationPlanProperties=" + monetizationPlanProperties + ", tierQuotaType=" + tierQuotaType + + ", maxDepth=" + graphQLMaxDepth + ", maxComplexity=" + graphQLMaxComplexity + + ", subscriberCount= " + subscriberCount + "]"; } public int getSubscriberCount() { @@ -139,12 +136,4 @@ public int getSubscriberCount() { public void setSubscriberCount(int subscriberCount) { this.subscriberCount = subscriberCount; } - - public List getAllowedOrganizations() { - return allowedOrganizations; - } - - public void setAllowedOrganizations(List allowedOrganizations) { - this.allowedOrganizations = allowedOrganizations; - } -} +} \ No newline at end of file diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index b14730b79a95..a58b8e4117e5 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -2022,7 +2022,6 @@ public enum RegistryResourceTypesForUI { public static final String API_POLICY_API_LEVEL = "apiLevel"; public static final String BILLING_PLAN_FREE = "FREE"; - public static final String ALLOWED_ORGANIZATIONS_DEFAULT = "ALL"; public static final String DEFAULT_VISIBLE_ORG = "all"; public static final String POLICY_RESET = "reset"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 9929ff5f2e75..7bc44a012624 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -4036,7 +4036,6 @@ private API addTiersToAPI(API api, String organization) throws APIManagementExce int tenantId = APIUtil.getInternalIdFromTenantDomainOrOrganization(organization); Set tierNames = api.getAvailableTiers(); - apiMgtDAO.getSubscriptionPolicies(tenantId); Map definedTiers = APIUtil.getTiers(tenantId); Set availableTiers = new HashSet(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java index a7a7a3b1552c..a70101a864ba 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java @@ -131,6 +131,5 @@ public class ThrottlePolicyConstants { public static final String COLUMN_MAX_DEPTH = "MAX_DEPTH"; public static final String COLUMN_MAX_COMPLEXITY = "MAX_COMPLEXITY"; - - public static final String COLUMN_ALLOWED_ORGANIZATIONS = "ALLOWED_ORGANIZATIONS"; + } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 7a7c245992fd..e4ea87d48c28 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -11812,18 +11812,6 @@ public void addSubscriptionPolicy(SubscriptionPolicy policy) throws APIManagemen policyStatement.setInt(26, policy.getSubscriberCount()); } - List allowedOrgs = policy.getAllowedOrganizations(); - if (allowedOrgs != null && !allowedOrgs.isEmpty()) { - try (PreparedStatement addVisibleOrgsStatement = conn - .prepareStatement(SQLConstants.PolicyOrgVisibilitySqlConstants.ADD_POLICY_ORG_VISIBILITY_SQL)) { - for (String org : allowedOrgs) { - addVisibleOrgsStatement.setString(1, policy.getUUID()); - addVisibleOrgsStatement.setString(2, org); - addVisibleOrgsStatement.addBatch(); - } - addVisibleOrgsStatement.executeBatch(); - } - } policyStatement.executeUpdate(); conn.commit(); } catch (SQLIntegrityConstraintViolationException e) { @@ -12537,7 +12525,6 @@ public SubscriptionPolicy[] getSubscriptionPolicies(int tenantID) throws APIMana monetizationPlanProperties.put(APIConstants.Monetization.CURRENCY, rs.getString(ThrottlePolicyConstants.COLUMN_CURRENCY)); subPolicy.setMonetizationPlanProperties(monetizationPlanProperties); - subPolicy.setAllowedOrganizations(getPolicyVisibleOrgs(subPolicy.getUUID())); InputStream binary = rs.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -12965,7 +12952,6 @@ public SubscriptionPolicy getSubscriptionPolicy(String policyName, int tenantId) policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); - policy.setAllowedOrganizations(getPolicyVisibleOrgs(policy.getUUID())); InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -13018,7 +13004,6 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); - policy.setAllowedOrganizations(getPolicyVisibleOrgs(policy.getUUID())); InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { @@ -13050,29 +13035,6 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan return policy; } - public List getPolicyVisibleOrgs(String policyUUID) throws APIManagementException { - List orgList = new ArrayList(); - try (Connection conn = APIMgtDBUtil.getConnection()) { - try { - String getPolicyPermissionQuery = SQLConstants.PolicyOrgVisibilitySqlConstants.GET_POLICY_ORG_VISIBILITY_SQL; - PreparedStatement ps = conn.prepareStatement(getPolicyPermissionQuery); - ps.setString(1, policyUUID); - ResultSet resultSet = ps.executeQuery(); - while (resultSet.next()) { - orgList.add(resultSet.getString(ThrottlePolicyConstants.COLUMN_ALLOWED_ORGANIZATIONS)); - } - } catch (SQLException e) { - conn.rollback(); - handleException("Failed to get policy allowed organizations " + policyUUID, - e); - } - } catch (SQLException e) { - throw new APIManagementException( - "Error while retrieving policy organizations with id " + policyUUID, e); - } - return orgList; - } - /** * Retrieves list of pipelines for the policy with policy Id: policyId * @@ -13558,23 +13520,6 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage } updateStatement.executeUpdate(); - try (PreparedStatement deleteOrgsStatement = connection.prepareStatement(SQLConstants - .PolicyOrgVisibilitySqlConstants.DELETE_ALL_POLICY_ORG_VISIBILITY_SQL)) { - deleteOrgsStatement.setString(1, policy.getUUID()); - deleteOrgsStatement.executeUpdate(); - } - List allowedOrgs = policy.getAllowedOrganizations(); - if (allowedOrgs != null && !allowedOrgs.isEmpty()) { - try (PreparedStatement addOrgsStatement = connection.prepareStatement(SQLConstants - .PolicyOrgVisibilitySqlConstants.ADD_POLICY_ORG_VISIBILITY_SQL)) { - for (String org : allowedOrgs) { - addOrgsStatement.setString(1, policy.getUUID()); - addOrgsStatement.setString(2, org); - addOrgsStatement.addBatch(); - } - addOrgsStatement.executeBatch(); - } - } connection.commit(); } catch (SQLException e) { if (connection != null) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index 13bd5c628263..bffc0777017f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -3867,21 +3867,6 @@ public static class KeyManagerOrgVisibilitySqlConstants { " WHERE KEY_MANAGER_UUID = ?"; } - public static class PolicyOrgVisibilitySqlConstants { - - public static final String ADD_POLICY_ORG_VISIBILITY_SQL = - " INSERT INTO" + - " AM_POLICY_ALLOWED_ORGS (POLICY_UUID, ALLOWED_ORGANIZATIONS)" + - " VALUES(?, ?)"; - - public static final String DELETE_ALL_POLICY_ORG_VISIBILITY_SQL = "DELETE FROM AM_POLICY_ALLOWED_ORGS" + - " WHERE POLICY_UUID = ?"; - - public static final String GET_POLICY_ORG_VISIBILITY_SQL = - "SELECT ALLOWED_ORGANIZATIONS" + - " FROM AM_POLICY_ALLOWED_ORGS " + - " WHERE POLICY_UUID = ?"; - } /** * Static class to hold database queries related to AM_TENANT_THEMES table */ diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index fa832383c99b..de76b54619dd 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -10839,23 +10839,6 @@ public static List getPaginatedApplicationList( return applications.subList(offset, endIndex); } - public static Set getAllowedTiersForTheOrganization(Set tiers, String organization, - String superOrganization) throws APIManagementException { - int tenantId = APIUtil.getInternalIdFromTenantDomainOrOrganization(superOrganization); - SubscriptionPolicy[] policies = ApiMgtDAO.getInstance().getSubscriptionPolicies(tenantId); - Set allowedTiers = new HashSet(); - for (Tier tier : tiers) { - for (SubscriptionPolicy policy : policies) { - if (policy.getPolicyName().equals(tier.getName()) - && (policy.getAllowedOrganizations().isEmpty() - || policy.getAllowedOrganizations().contains(organization))) { - allowedTiers.add(tier); - } - } - } - return allowedTiers; - } - public static String getAPIMVersion() { return CarbonUtils.getServerConfiguration().getFirstProperty("Version"); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java index 61ca35a6af83..d53f65d7e0c0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyAllOfDTO.java @@ -35,7 +35,6 @@ public class SubscriptionThrottlePolicyAllOfDTO { private Boolean stopOnQuotaReach = false; private String billingPlan = null; private SubscriptionThrottlePolicyPermissionDTO permissions = null; - private List allowedOrganizations = new ArrayList(); /** **/ @@ -201,23 +200,6 @@ public void setPermissions(SubscriptionThrottlePolicyPermissionDTO permissions) this.permissions = permissions; } - /** - **/ - public SubscriptionThrottlePolicyAllOfDTO allowedOrganizations(List allowedOrganizations) { - this.allowedOrganizations = allowedOrganizations; - return this; - } - - - @ApiModelProperty(value = "") - @JsonProperty("allowedOrganizations") - public List getAllowedOrganizations() { - return allowedOrganizations; - } - public void setAllowedOrganizations(List allowedOrganizations) { - this.allowedOrganizations = allowedOrganizations; - } - @Override public boolean equals(java.lang.Object o) { @@ -236,13 +218,12 @@ public boolean equals(java.lang.Object o) { Objects.equals(customAttributes, subscriptionThrottlePolicyAllOf.customAttributes) && Objects.equals(stopOnQuotaReach, subscriptionThrottlePolicyAllOf.stopOnQuotaReach) && Objects.equals(billingPlan, subscriptionThrottlePolicyAllOf.billingPlan) && - Objects.equals(permissions, subscriptionThrottlePolicyAllOf.permissions) && - Objects.equals(allowedOrganizations, subscriptionThrottlePolicyAllOf.allowedOrganizations); + Objects.equals(permissions, subscriptionThrottlePolicyAllOf.permissions); } @Override public int hashCode() { - return Objects.hash(defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions, allowedOrganizations); + return Objects.hash(defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions); } @Override @@ -259,7 +240,6 @@ public String toString() { sb.append(" stopOnQuotaReach: ").append(toIndentedString(stopOnQuotaReach)).append("\n"); sb.append(" billingPlan: ").append(toIndentedString(billingPlan)).append("\n"); sb.append(" permissions: ").append(toIndentedString(permissions)).append("\n"); - sb.append(" allowedOrganizations: ").append(toIndentedString(allowedOrganizations)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java index 3bd7155a4abf..24a1552cf6c0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/SubscriptionThrottlePolicyDTO.java @@ -40,7 +40,6 @@ public class SubscriptionThrottlePolicyDTO extends ThrottlePolicyDTO { private Boolean stopOnQuotaReach = false; private String billingPlan = null; private SubscriptionThrottlePolicyPermissionDTO permissions = null; - private List allowedOrganizations = new ArrayList(); /** * Maximum Complexity of the GraphQL query @@ -242,23 +241,6 @@ public void setPermissions(SubscriptionThrottlePolicyPermissionDTO permissions) this.permissions = permissions; } - /** - **/ - public SubscriptionThrottlePolicyDTO allowedOrganizations(List allowedOrganizations) { - this.allowedOrganizations = allowedOrganizations; - return this; - } - - - @ApiModelProperty(value = "") - @JsonProperty("allowedOrganizations") - public List getAllowedOrganizations() { - return allowedOrganizations; - } - public void setAllowedOrganizations(List allowedOrganizations) { - this.allowedOrganizations = allowedOrganizations; - } - @Override public boolean equals(java.lang.Object o) { @@ -279,13 +261,12 @@ public boolean equals(java.lang.Object o) { Objects.equals(customAttributes, subscriptionThrottlePolicy.customAttributes) && Objects.equals(stopOnQuotaReach, subscriptionThrottlePolicy.stopOnQuotaReach) && Objects.equals(billingPlan, subscriptionThrottlePolicy.billingPlan) && - Objects.equals(permissions, subscriptionThrottlePolicy.permissions) && - Objects.equals(allowedOrganizations, subscriptionThrottlePolicy.allowedOrganizations); + Objects.equals(permissions, subscriptionThrottlePolicy.permissions); } @Override public int hashCode() { - return Objects.hash(graphQLMaxComplexity, graphQLMaxDepth, defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions, allowedOrganizations); + return Objects.hash(graphQLMaxComplexity, graphQLMaxDepth, defaultLimit, monetization, rateLimitCount, rateLimitTimeUnit, subscriberCount, customAttributes, stopOnQuotaReach, billingPlan, permissions); } @Override @@ -304,7 +285,6 @@ public String toString() { sb.append(" stopOnQuotaReach: ").append(toIndentedString(stopOnQuotaReach)).append("\n"); sb.append(" billingPlan: ").append(toIndentedString(billingPlan)).append("\n"); sb.append(" permissions: ").append(toIndentedString(permissions)).append("\n"); - sb.append(" allowedOrganizations: ").append(toIndentedString(allowedOrganizations)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java index afbbe47227f4..f7ef5fc03953 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/throttling/SubscriptionThrottlePolicyMappingUtil.java @@ -89,7 +89,6 @@ public static SubscriptionThrottlePolicyDTO fromSubscriptionThrottlePolicyToDTO( policyDTO.setGraphQLMaxComplexity(subscriptionPolicy.getGraphQLMaxComplexity()); policyDTO.setGraphQLMaxDepth(subscriptionPolicy.getGraphQLMaxDepth()); policyDTO.setSubscriberCount(subscriptionPolicy.getSubscriberCount()); - policyDTO.setAllowedOrganizations(subscriptionPolicy.getAllowedOrganizations()); byte[] customAttributes = subscriptionPolicy.getCustomAttributes(); if (customAttributes != null) { @@ -141,7 +140,6 @@ public static SubscriptionPolicy fromSubscriptionThrottlePolicyDTOToModel(Subscr subscriptionPolicy = CommonThrottleMappingUtil.updateFieldsFromDTOToPolicy(dto, subscriptionPolicy); subscriptionPolicy.setBillingPlan(dto.getBillingPlan()); subscriptionPolicy.setStopOnQuotaReach(dto.isStopOnQuotaReach()); - subscriptionPolicy.setAllowedOrganizations(dto.getAllowedOrganizations()); if (!PolicyConstants.AI_API_QUOTA_TYPE_ENUM_VALUE.equals(quotaType)) { subscriptionPolicy.setRateLimitTimeUnit(dto.getRateLimitTimeUnit()); if (dto.getRateLimitCount() != null) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml index dde1815da900..df63ee9d02c1 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml @@ -4061,10 +4061,6 @@ components: example: FREE permissions: $ref: '#/components/schemas/SubscriptionThrottlePolicyPermission' - allowedOrganizations: - type: array - items: - type: string SubscriptionThrottlePolicyPermission: title: SubscriptionThrottlePolicyPermission required: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml index dde1815da900..df63ee9d02c1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml @@ -4061,10 +4061,6 @@ components: example: FREE permissions: $ref: '#/components/schemas/SubscriptionThrottlePolicyPermission' - allowedOrganizations: - type: array - items: - type: string SubscriptionThrottlePolicyPermission: title: SubscriptionThrottlePolicyPermission required: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index c73dcb350e41..9a7d37b1b6ca 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1194,13 +1194,6 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo if (APIConstants.PUBLISHED.equals(status) || APIConstants.PROTOTYPED.equals(status) || APIConstants.DEPRECATED.equals(status)) { - if (!api.isAPIProduct()) { - // Add only organization specific tiers - Set tiers = APIUtil.getAllowedTiersForTheOrganization(api.getApi().getAvailableTiers(), - userOrgInfo.getOrganizationSelector(), userOrgInfo.getSuperOrganization()); - api.getApi().removeAllTiers(); - api.getApi().setAvailableTiers(tiers); - } APIDTO apidto = APIMappingUtil.fromAPItoDTO(api, organization); long subscriptionCountOfAPI = apiConsumer.getSubscriptionCountOfAPI(apiId, organization); diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index 595e4ea45e22..ab3bd2d98b95 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -2146,13 +2146,6 @@ CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_ALLOWED_ORGS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ); -CREATE TABLE IF NOT EXISTS AM_POLICY_ALLOWED_ORGS ( - ALLOWED_ORGS_ID INT NOT NULL AUTO_INCREMENT, - POLICY_UUID VARCHAR(50) NOT NULL, - ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, - PRIMARY KEY (ALLOWED_ORGS_ID) -); - -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- CREATE TABLE IF NOT EXISTS AM_GW_PUBLISHED_API_DETAILS ( From 6aacca75167341ce588252ba32c3b919d07e97e6 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 21 Jan 2025 16:14:51 +0530 Subject: [PATCH 49/74] Backend for managing organization --- .../org/wso2/carbon/apimgt/api/APIAdmin.java | 43 ++++ .../wso2/carbon/apimgt/api/APIProvider.java | 11 + .../carbon/apimgt/api/ExceptionCodes.java | 3 + .../api/dto/OrganizationDetailsDTO.java | 66 ++++++ .../wso2/carbon/apimgt/impl/APIAdminImpl.java | 32 +++ .../carbon/apimgt/impl/APIProviderImpl.java | 7 + .../impl/config/APIMConfigServiceImpl.java | 36 ++- .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 115 ++++++++++ .../impl/dao/constants/SQLConstants.java | 21 ++ .../rest/api/admin/v1/OrganizationsApi.java | 125 +++++++++++ .../api/admin/v1/OrganizationsApiService.java | 30 +++ .../api/admin/v1/dto/OrganizationDTO.java | 144 ++++++++++++ .../api/admin/v1/dto/OrganizationListDTO.java | 106 +++++++++ .../v1/impl/OrganizationsApiServiceImpl.java | 168 ++++++++++++++ .../mappings/OrganizationsMappingUtil.java | 63 ++++++ .../src/main/resources/admin-api.yaml | 206 ++++++++++++++++++ .../src/main/webapp/WEB-INF/web.xml | 3 +- .../rest/api/common/RestApiConstants.java | 1 + .../src/main/resources/admin-api.yaml | 206 ++++++++++++++++++ .../src/main/resources/publisher-api.yaml | 65 ++++++ .../api/publisher/v1/dto/OrganizationDTO.java | 124 +++++++++++ .../publisher/v1/dto/OrganizationListDTO.java | 106 +++++++++ .../api/publisher/v1/OrganizationsApi.java | 56 +++++ .../publisher/v1/OrganizationsApiService.java | 24 ++ .../v1/impl/OrganizationsApiServiceImpl.java | 65 ++++++ .../v1/utils/OrganizationsMappingUtil.java | 43 ++++ .../src/main/resources/publisher-api.yaml | 65 ++++++ .../src/main/webapp/WEB-INF/web.xml | 3 +- .../src/main/resources/sql/h2.sql | 9 + 29 files changed, 1932 insertions(+), 14 deletions(-) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApi.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApiService.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationListDTO.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationDTO.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationListDTO.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApi.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApiService.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIAdmin.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIAdmin.java index 8d06ba4e1ed2..5377dbc803f7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIAdmin.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIAdmin.java @@ -19,6 +19,7 @@ import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.dto.KeyManagerPermissionConfigurationDTO; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; import org.wso2.carbon.apimgt.api.model.APICategory; import org.wso2.carbon.apimgt.api.model.Application; import org.wso2.carbon.apimgt.api.model.ApplicationInfo; @@ -594,4 +595,46 @@ List getGlobalKeyManagerConfigurations(String organi * @throws APIManagementException If retrieval fails. */ LLMProvider getLLMProvider(String organization, String llmProviderId) throws APIManagementException; + + /** + * + * Retrieves list of organizations available for the given parent organization. + * + * @param parentOrgId parent organization id + * @param tenantDomain super domain + * @return organization list + */ + List getOrganizations(String parentOrgId, String tenantDomain) throws APIManagementException; + + /** + * Add new organization + * @param orgDto organization details + * @return added organization + */ + OrganizationDetailsDTO addOrganization(OrganizationDetailsDTO orgDto) throws APIManagementException; + + /** + * Get organization details + * @param organizationId organization id + * @param tenantDomain tenant domain + * @return + * @throws APIManagementException + */ + OrganizationDetailsDTO getOrganizationDetails(String organizationId, String tenantDomain) + throws APIManagementException; + + /** + * Update organization details + * @param organizationInfoDTO request object + * @return updated organization info + * @throws APIManagementException + */ + OrganizationDetailsDTO updateOrganization(OrganizationDetailsDTO organizationInfoDTO) throws APIManagementException; + + /** + * Delete organization + * @param organizationId organization + * @param tenantDomain tenantDomain + */ + void deleteOrganization(String organizationId, String tenantDomain) throws APIManagementException; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java index fcd13d13c6c4..66bc5784ef35 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/APIProvider.java @@ -23,6 +23,7 @@ import org.wso2.carbon.apimgt.api.dto.CertificateMetadataDTO; import org.wso2.carbon.apimgt.api.dto.ClientCertificateDTO; import org.wso2.carbon.apimgt.api.dto.EnvironmentPropertiesDTO; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; import org.wso2.carbon.apimgt.api.dto.UserApplicationAPIUsage; import org.wso2.carbon.apimgt.api.dto.WorkflowDTO; import org.wso2.carbon.apimgt.api.model.*; @@ -2035,4 +2036,14 @@ void updateSoapToRestSequences(String organization, String apiId, List getOrganizations(String orgId, String superOrganization) throws APIManagementException; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java index 5259f06a9d4d..931b0b7bba01 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java @@ -424,6 +424,9 @@ public enum ExceptionCodes implements ErrorHandler { // Tenant related INVALID_TENANT(901300,"Tenant Not Found", 400, "Tenant Not Found"), + + // Tenant related + INVALID_ORGANINATION(901301,"Organization Not Found", 404, "Organization Not Found"), // Key Manager Related INVALID_KEY_MANAGER_TYPE(901400, "Key Manager Type not configured", 400, "Key Manager Type not configured"), REQUIRED_KEY_MANAGER_CONFIGURATION_MISSING(901401,"Required Key Manager configuration missing",400,"Missing " + diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java new file mode 100644 index 000000000000..712bbf0ad8fd --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.wso2.carbon.apimgt.api.dto; + +public class OrganizationDetailsDTO { + + private String organizationId; + private String parentOrganizationId; + private String Name; + private String tenantDomain; + private String description; + public String getOrganizationId() { + return organizationId; + } + public void setOrganizationId(String organizationId) { + this.organizationId = organizationId; + } + public String getParentOrganizationId() { + return parentOrganizationId; + } + public void setParentOrganizationId(String parentOrganizationId) { + this.parentOrganizationId = parentOrganizationId; + } + public String getName() { + return Name; + } + public void setName(String name) { + Name = name; + } + public String getTenantDomain() { + return tenantDomain; + } + public void setTenantDomain(String tenantDomain) { + this.tenantDomain = tenantDomain; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + @Override + public String toString() { + return "OrganizationDTO [organizationId=" + organizationId + ", parentOrganizationId=" + parentOrganizationId + + ", Name=" + Name + ", tenantDomain=" + tenantDomain + ", description=" + description + "]"; + } + + +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java index ca2d09019165..6f9bdf1bb71b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java @@ -42,6 +42,7 @@ import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.dto.KeyManagerPermissionConfigurationDTO; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; import org.wso2.carbon.apimgt.api.model.APICategory; import org.wso2.carbon.apimgt.api.model.APIIdentifier; import org.wso2.carbon.apimgt.api.model.Application; @@ -1826,4 +1827,35 @@ public List getGlobalKeyManagerConfigurations(String setKeyManagerUsageRelatedInformation(keyManagerConfigurations, organization); return keyManagerConfigurations; } + + @Override + public List getOrganizations(String parentOrgId, String tenantDomain) throws APIManagementException { + List organizationsList = apiMgtDAO.getOrganizations(parentOrgId, tenantDomain); + return organizationsList; + } + + @Override + public OrganizationDetailsDTO addOrganization(OrganizationDetailsDTO orgDto) throws APIManagementException { + apiMgtDAO.addOrganization(orgDto); + return orgDto; + } + + @Override + public OrganizationDetailsDTO getOrganizationDetails(String organizationId, String tenantDomain) + throws APIManagementException { + return apiMgtDAO.getOrganizationDetails(organizationId, tenantDomain); + } + + @Override + public OrganizationDetailsDTO updateOrganization(OrganizationDetailsDTO organizationInfoDTO) + throws APIManagementException { + apiMgtDAO.updateOrganizationDetails(organizationInfoDTO); + return apiMgtDAO.getOrganizationDetails(organizationInfoDTO.getOrganizationId(), + organizationInfoDTO.getTenantDomain()); + } + + @Override + public void deleteOrganization(String organizationId, String tenantDomain) throws APIManagementException { + apiMgtDAO.deleteOrganizationDetails(organizationId, tenantDomain); + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java index 4bed9e0e64dc..80114954e099 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java @@ -53,6 +53,7 @@ import org.wso2.carbon.apimgt.api.dto.ClientCertificateDTO; import org.wso2.carbon.apimgt.api.dto.ClonePolicyMetadataDTO; import org.wso2.carbon.apimgt.api.dto.EnvironmentPropertiesDTO; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; import org.wso2.carbon.apimgt.api.dto.UserApplicationAPIUsage; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.APIDefinitionContentSearchResult; @@ -7780,4 +7781,10 @@ public org.wso2.carbon.apimgt.api.dto.WorkflowDTO retrieveWorkflow( } } + @Override + public List getOrganizations(String orgId, String tenantDomain) throws APIManagementException { + List organizationsList = apiMgtDAO.getOrganizations(orgId, tenantDomain); + return organizationsList; + } + } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/config/APIMConfigServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/config/APIMConfigServiceImpl.java index b89696666387..e96346b40db1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/config/APIMConfigServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/config/APIMConfigServiceImpl.java @@ -17,10 +17,15 @@ */ package org.wso2.carbon.apimgt.impl.config; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; + +import javax.cache.Cache; + import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,13 +47,11 @@ import org.wso2.carbon.registry.core.session.UserRegistry; import org.wso2.carbon.registry.core.utils.RegistryUtils; import org.wso2.carbon.user.api.UserStoreException; -import javax.cache.Cache; -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; /** * Config Service Implementation for retrieve configurations. @@ -58,6 +61,10 @@ public class APIMConfigServiceImpl implements APIMConfigService { private static final Log log = LogFactory.getLog(APIMConfigServiceImpl.class); private static final String SUBSCRIPTION_APPROVAL_VIEW_SCOPE = "apim:subscription_approval_view"; private static final String SUBSCRIPTION_APPROVAL_MANAGE_SCOPE = "apim:subscription_approval_manage"; + private static final String PUBLISHER_ORG_READ = "apim:publisher_organization_read"; + private static final String ADMIN_ORG_READ = "apim:organization_read"; + private static final String ADMIN_ORG_MANAGE = "apim:organization_manage"; + protected SystemConfigurationsDAO systemConfigurationsDAO; public APIMConfigServiceImpl() { @@ -199,7 +206,10 @@ private String addMissingScopes(String systemConfig) { "apim:keymanagers_manage", "apim:api_category", SUBSCRIPTION_APPROVAL_VIEW_SCOPE, - SUBSCRIPTION_APPROVAL_MANAGE_SCOPE + SUBSCRIPTION_APPROVAL_MANAGE_SCOPE, + PUBLISHER_ORG_READ, + ADMIN_ORG_MANAGE, + ADMIN_ORG_READ }; ArrayList missingScopesList = new ArrayList<>(Arrays.asList(scopesToCheck)); @@ -234,6 +244,8 @@ private String addMissingScopes(String systemConfig) { if (missingScope.equals(SUBSCRIPTION_APPROVAL_VIEW_SCOPE) || missingScope.equals(SUBSCRIPTION_APPROVAL_MANAGE_SCOPE)) { newScope.addProperty("Roles", "admin,Internal/publisher"); + } else if (missingScope.equals(PUBLISHER_ORG_READ)) { + newScope.addProperty("Roles", "admin,Internal/creator"); } else { newScope.addProperty("Roles", "admin"); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index e4ea87d48c28..37ad6abad9a6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -39,6 +39,7 @@ import org.wso2.carbon.apimgt.api.dto.ConditionGroupDTO; import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.dto.KeyManagerPermissionConfigurationDTO; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; import org.wso2.carbon.apimgt.api.dto.UserApplicationAPIUsage; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.APICategory; @@ -10294,6 +10295,120 @@ public void setDefaultVersion(APIProduct apiProduct) throws APIManagementExcepti } } + + public void addOrganization(OrganizationDetailsDTO organizationDTO) throws APIManagementException { + + try (Connection conn = APIMgtDBUtil.getConnection()) { + conn.setAutoCommit(false); + try (PreparedStatement preparedStatement = conn + .prepareStatement(SQLConstants.OrganizationSqlConstants.ADD_ORGANIZATION)) { + preparedStatement.setString(1, organizationDTO.getOrganizationId()); + preparedStatement.setString(2, organizationDTO.getName()); + preparedStatement.setString(3, organizationDTO.getParentOrganizationId()); + preparedStatement.setString(4, organizationDTO.getDescription()); + preparedStatement.setString(5, organizationDTO.getTenantDomain()); + preparedStatement.executeUpdate(); + conn.commit(); + } + } catch (SQLException e) { + String message = "Error while saving organization " + organizationDTO.getName() + + " in tenant " + organizationDTO.getTenantDomain(); + handleException(message, e); + } + } + + public List getOrganizations(String parentOrganizationId, String tenantDomain) + throws APIManagementException { + + List organizationList = new ArrayList(); + String query; + String param; + if (!StringUtils.isEmpty(parentOrganizationId)) { + query = SQLConstants.OrganizationSqlConstants.GET_ORGANIZATIONS_BY_PARENT_ORG_ID; + param = parentOrganizationId; + } else { + query = SQLConstants.OrganizationSqlConstants.GET_ORGANIZATIONS_BY_TENAND_DOMAIN; + param = tenantDomain; + } + try (Connection connection = APIMgtDBUtil.getConnection(); + PreparedStatement prepStmt = connection + .prepareStatement(query)) { + prepStmt.setString(1, param); + try (ResultSet resultSet = prepStmt.executeQuery()) { + while (resultSet.next()) { + OrganizationDetailsDTO organization = new OrganizationDetailsDTO(); + organization.setOrganizationId(resultSet.getString("ORG_UUID")); + organization.setParentOrganizationId(resultSet.getString("PARENT_ORG_UUID")); + organization.setName(resultSet.getString("DISPLAY_NAME")); + organization.setDescription(resultSet.getString("DESCRIPTION")); + organization.setTenantDomain(resultSet.getString("TENANT_DOMAIN")); + organizationList.add(organization); + } + } + } catch (SQLException e) { + handleException("Failed to get organizations : ", e); + } + return organizationList; + } + + public OrganizationDetailsDTO getOrganizationDetails(String organizationId, String tenantDomain) + throws APIManagementException { + + OrganizationDetailsDTO organization = null; + try (Connection connection = APIMgtDBUtil.getConnection(); + PreparedStatement prepStmt = connection + .prepareStatement(SQLConstants.OrganizationSqlConstants.GET_ORGANIZATION_BY_ORG_ID);) { + prepStmt.setString(1, organizationId); + prepStmt.setString(2, tenantDomain); + try (ResultSet resultSet = prepStmt.executeQuery()) { + if (resultSet.next()) { + organization = new OrganizationDetailsDTO(); + organization.setOrganizationId(resultSet.getString("ORG_UUID")); + organization.setParentOrganizationId(resultSet.getString("PARENT_ORG_UUID")); + organization.setName(resultSet.getString("DISPLAY_NAME")); + organization.setDescription(resultSet.getString("DESCRIPTION")); + organization.setTenantDomain(resultSet.getString("TENANT_DOMAIN")); + } + } + } catch (SQLException e) { + handleException("Failed to get organization for organization Id : " + organizationId, e); + } + return organization; + } + + public void deleteOrganizationDetails(String organizationId, String tenantDomain) + throws APIManagementException { + try (Connection connection = APIMgtDBUtil.getConnection(); + PreparedStatement prepStmt = connection + .prepareStatement(SQLConstants.OrganizationSqlConstants.DELETE_ORGANIZATION);) { + connection.setAutoCommit(false); + prepStmt.setString(1, organizationId); + prepStmt.setString(2, tenantDomain); + prepStmt.executeUpdate(); + connection.commit(); + } catch (SQLException e) { + handleException("Failed to delete organization Id : " + organizationId, e); + } + } + + public void updateOrganizationDetails(OrganizationDetailsDTO organizationDetailsDTO) throws APIManagementException { + + try (Connection conn = APIMgtDBUtil.getConnection()) { + conn.setAutoCommit(false); + try (PreparedStatement preparedStatement = conn + .prepareStatement(SQLConstants.OrganizationSqlConstants.UPDATE_ORGANIZATION)) { + preparedStatement.setString(1, organizationDetailsDTO.getName()); + preparedStatement.setString(2, organizationDetailsDTO.getDescription()); + preparedStatement.setString(3, organizationDetailsDTO.getOrganizationId()); + preparedStatement.executeUpdate(); + conn.commit(); + } + } catch (SQLException e) { + handleException("Failed to delete organization Id : " + "Error while Updating organization details for " + + organizationDetailsDTO.getOrganizationId(), e); + } + } + public API getLightWeightAPIInfoByAPIIdentifier(APIIdentifier apiIdentifier, String organization) throws APIManagementException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index bffc0777017f..465fb07b7461 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -3828,6 +3828,27 @@ public static class KeyManagerSqlConstants { "AM_APPLICATION_KEY_MAPPING AAKM WHERE APPLICATION_ID=? AND AAKM.UUID = ? " + "AND AKM.UUID=AAKM.KEY_MANAGER"; } + + public static class OrganizationSqlConstants { + public static final String ADD_ORGANIZATION = + " INSERT INTO AM_ORGANIZATION_MAPPING (ORG_UUID,DISPLAY_NAME,PARENT_ORG_UUID,DESCRIPTION,TENANT_DOMAIN) " + + "VALUES (?,?,?,?,?)"; + + public static final String UPDATE_ORGANIZATION = + "UPDATE AM_ORGANIZATION_MAPPING SET DISPLAY_NAME = ?, DESCRIPTION = ? WHERE ORG_UUID = ?"; + + public static final String DELETE_ORGANIZATION = + "DELETE FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID = ? AND TENANT_DOMAIN=?"; + + public static final String GET_ORGANIZATIONS_BY_PARENT_ORG_ID = + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE PARENT_ORG_UUID=?"; + + public static final String GET_ORGANIZATION_BY_ORG_ID = + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID=? AND TENANT_DOMAIN=?"; + + public static final String GET_ORGANIZATIONS_BY_TENAND_DOMAIN = + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE TENANT_DOMAIN=?"; + } /** * Static class to hold database queries related to AM_KEY_MANAGER_PERMISSIONS table diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApi.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApi.java new file mode 100644 index 000000000000..8873667ecdea --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApi.java @@ -0,0 +1,125 @@ +package org.wso2.carbon.apimgt.rest.api.admin.v1; + +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.ErrorDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationListDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.OrganizationsApiService; +import org.wso2.carbon.apimgt.rest.api.admin.v1.impl.OrganizationsApiServiceImpl; +import org.wso2.carbon.apimgt.api.APIManagementException; + +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.inject.Inject; + +import io.swagger.annotations.*; +import java.io.InputStream; + +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; + +import java.util.Map; +import java.util.List; +import javax.validation.constraints.*; +@Path("/organizations") + +@Api(description = "the organizations API") + + + + +public class OrganizationsApi { + + @Context MessageContext securityContext; + +OrganizationsApiService delegate = new OrganizationsApiServiceImpl(); + + + @GET + + + @Produces({ "application/json" }) + @ApiOperation(value = "Get all registered Organizations", notes = "Get all Registered Organizations ", response = OrganizationListDTO.class, authorizations = { + @Authorization(value = "OAuth2Security", scopes = { + @AuthorizationScope(scope = "apim:admin", description = "Manage all admin operations"), + @AuthorizationScope(scope = "apim:organization_read", description = "Read Organizations") + }) + }, tags={ "Organizations", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. Organizations returned ", response = OrganizationListDTO.class) }) + public Response organizationsGet() throws APIManagementException{ + return delegate.organizationsGet(securityContext); + } + + @DELETE + @Path("/{organizationId}") + + @Produces({ "application/json" }) + @ApiOperation(value = "Delete an Organization", notes = "Delete an organization by organization Id ", response = Void.class, authorizations = { + @Authorization(value = "OAuth2Security", scopes = { + @AuthorizationScope(scope = "apim:admin", description = "Manage all admin operations"), + @AuthorizationScope(scope = "apim:organization_manage", description = "Manage Organizations") + }) + }, tags={ "Organizations", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. Organization successfully deleted. ", response = Void.class), + @ApiResponse(code = 404, message = "Not Found. The specified resource does not exist.", response = ErrorDTO.class) }) + public Response organizationsOrganizationIdDelete(@ApiParam(value = "Organization UUID ",required=true) @PathParam("organizationId") String organizationId) throws APIManagementException{ + return delegate.organizationsOrganizationIdDelete(organizationId, securityContext); + } + + @GET + @Path("/{organizationId}") + + @Produces({ "application/json" }) + @ApiOperation(value = "Get an Organization", notes = "Get an organization by organization Id ", response = OrganizationDTO.class, authorizations = { + @Authorization(value = "OAuth2Security", scopes = { + @AuthorizationScope(scope = "apim:admin", description = "Manage all admin operations"), + @AuthorizationScope(scope = "apim:organization_read", description = "Read Organizations") + }) + }, tags={ "Organizations", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. Organization. ", response = OrganizationDTO.class), + @ApiResponse(code = 400, message = "Bad Request. Invalid request or validation error.", response = ErrorDTO.class), + @ApiResponse(code = 404, message = "Not Found. The specified resource does not exist.", response = ErrorDTO.class) }) + public Response organizationsOrganizationIdGet(@ApiParam(value = "Organization UUID ",required=true) @PathParam("organizationId") String organizationId) throws APIManagementException{ + return delegate.organizationsOrganizationIdGet(organizationId, securityContext); + } + + @PUT + @Path("/{organizationId}") + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Update an Organization", notes = "Update an organization by organization Id ", response = OrganizationDTO.class, authorizations = { + @Authorization(value = "OAuth2Security", scopes = { + @AuthorizationScope(scope = "apim:admin", description = "Manage all admin operations"), + @AuthorizationScope(scope = "apim:organization_manage", description = "Manage Organizations") + }) + }, tags={ "Organizations", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. Organization updated. ", response = OrganizationDTO.class), + @ApiResponse(code = 400, message = "Bad Request. Invalid request or validation error.", response = ErrorDTO.class), + @ApiResponse(code = 404, message = "Not Found. The specified resource does not exist.", response = ErrorDTO.class) }) + public Response organizationsOrganizationIdPut(@ApiParam(value = "Organization UUID ",required=true) @PathParam("organizationId") String organizationId, @ApiParam(value = "Organization object with updated information " ,required=true) OrganizationDTO organizationDTO) throws APIManagementException{ + return delegate.organizationsOrganizationIdPut(organizationId, organizationDTO, securityContext); + } + + @POST + + @Consumes({ "application/json" }) + @Produces({ "application/json" }) + @ApiOperation(value = "Add an Organizations", notes = "Add a new organization ", response = OrganizationDTO.class, authorizations = { + @Authorization(value = "OAuth2Security", scopes = { + @AuthorizationScope(scope = "apim:admin", description = "Manage all admin operations"), + @AuthorizationScope(scope = "apim:organization_manage", description = "Manage Organizations") + }) + }, tags={ "Organizations" }) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created. Successful response with the newly created organization as entity in the body. ", response = OrganizationDTO.class), + @ApiResponse(code = 400, message = "Bad Request. Invalid request or validation error.", response = ErrorDTO.class) }) + public Response organizationsPost(@ApiParam(value = "Organization object that should to be added " ,required=true) OrganizationDTO organizationDTO) throws APIManagementException{ + return delegate.organizationsPost(organizationDTO, securityContext); + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApiService.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApiService.java new file mode 100644 index 000000000000..2359c96177f8 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/OrganizationsApiService.java @@ -0,0 +1,30 @@ +package org.wso2.carbon.apimgt.rest.api.admin.v1; + +import org.wso2.carbon.apimgt.rest.api.admin.v1.*; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.*; + +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; + +import org.wso2.carbon.apimgt.api.APIManagementException; + +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.ErrorDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationListDTO; + +import java.util.List; + +import java.io.InputStream; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; + + +public interface OrganizationsApiService { + public Response organizationsGet(MessageContext messageContext) throws APIManagementException; + public Response organizationsOrganizationIdDelete(String organizationId, MessageContext messageContext) throws APIManagementException; + public Response organizationsOrganizationIdGet(String organizationId, MessageContext messageContext) throws APIManagementException; + public Response organizationsOrganizationIdPut(String organizationId, OrganizationDTO organizationDTO, MessageContext messageContext) throws APIManagementException; + public Response organizationsPost(OrganizationDTO organizationDTO, MessageContext messageContext) throws APIManagementException; +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java new file mode 100644 index 000000000000..3d5d16c7bb7c --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java @@ -0,0 +1,144 @@ +package org.wso2.carbon.apimgt.rest.api.admin.v1.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; + +import javax.xml.bind.annotation.*; +import org.wso2.carbon.apimgt.rest.api.common.annotations.Scope; +import com.fasterxml.jackson.annotation.JsonCreator; + +import javax.validation.Valid; + + + +public class OrganizationDTO { + + private String organizationId = null; + private String parentId = null; + private String displayName = null; + private String description = null; + + /** + * UUID of the organizatoin. + **/ + public OrganizationDTO organizationId(String organizationId) { + this.organizationId = organizationId; + return this; + } + + + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", required = true, value = "UUID of the organizatoin. ") + @JsonProperty("organizationId") + @NotNull + public String getOrganizationId() { + return organizationId; + } + public void setOrganizationId(String organizationId) { + this.organizationId = organizationId; + } + + /** + * UUID of the parent organization if there is any. + **/ + public OrganizationDTO parentId(String parentId) { + this.parentId = parentId; + return this; + } + + + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", value = "UUID of the parent organization if there is any. ") + @JsonProperty("parentId") + public String getParentId() { + return parentId; + } + public void setParentId(String parentId) { + this.parentId = parentId; + } + + /** + **/ + public OrganizationDTO displayName(String displayName) { + this.displayName = displayName; + return this; + } + + + @ApiModelProperty(example = "My Organization", value = "") + @JsonProperty("displayName") + @Size(min=1,max=255) public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + **/ + public OrganizationDTO description(String description) { + this.description = description; + return this; + } + + + @ApiModelProperty(example = "My Organization Description", value = "") + @JsonProperty("description") + @Size(max=1023) public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrganizationDTO organization = (OrganizationDTO) o; + return Objects.equals(organizationId, organization.organizationId) && + Objects.equals(parentId, organization.parentId) && + Objects.equals(displayName, organization.displayName) && + Objects.equals(description, organization.description); + } + + @Override + public int hashCode() { + return Objects.hash(organizationId, parentId, displayName, description); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OrganizationDTO {\n"); + + sb.append(" organizationId: ").append(toIndentedString(organizationId)).append("\n"); + sb.append(" parentId: ").append(toIndentedString(parentId)).append("\n"); + sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); + sb.append(" description: ").append(toIndentedString(description)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationListDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationListDTO.java new file mode 100644 index 000000000000..ec8f4aea3b55 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationListDTO.java @@ -0,0 +1,106 @@ +package org.wso2.carbon.apimgt.rest.api.admin.v1.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationDTO; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; + +import javax.xml.bind.annotation.*; +import org.wso2.carbon.apimgt.rest.api.common.annotations.Scope; +import com.fasterxml.jackson.annotation.JsonCreator; + +import javax.validation.Valid; + + + +public class OrganizationListDTO { + + private Integer count = null; + private List list = new ArrayList(); + + /** + * Number of Organizationa returned. + **/ + public OrganizationListDTO count(Integer count) { + this.count = count; + return this; + } + + + @ApiModelProperty(example = "1", value = "Number of Organizationa returned. ") + @JsonProperty("count") + public Integer getCount() { + return count; + } + public void setCount(Integer count) { + this.count = count; + } + + /** + **/ + public OrganizationListDTO list(List list) { + this.list = list; + return this; + } + + + @ApiModelProperty(value = "") + @Valid + @JsonProperty("list") + public List getList() { + return list; + } + public void setList(List list) { + this.list = list; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrganizationListDTO organizationList = (OrganizationListDTO) o; + return Objects.equals(count, organizationList.count) && + Objects.equals(list, organizationList.list); + } + + @Override + public int hashCode() { + return Objects.hash(count, list); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OrganizationListDTO {\n"); + + sb.append(" count: ").append(toIndentedString(count)).append("\n"); + sb.append(" list: ").append(toIndentedString(list)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java new file mode 100644 index 000000000000..70a07ff7f0fe --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.apimgt.rest.api.admin.v1.impl; + +import org.wso2.carbon.apimgt.api.APIAdmin; +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.api.ExceptionCodes; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; +import org.wso2.carbon.apimgt.impl.APIAdminImpl; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.rest.api.admin.v1.*; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.*; +import org.wso2.carbon.apimgt.rest.api.admin.v1.utils.mappings.OrganizationsMappingUtil; +import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; +import org.wso2.carbon.apimgt.rest.api.common.RestApiConstants; +import org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil; + +import com.google.gson.Gson; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.cxf.jaxrs.ext.MessageContext; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +import javax.ws.rs.core.Response; + + +public class OrganizationsApiServiceImpl implements OrganizationsApiService { + + private static final Log log = LogFactory.getLog(OrganizationsApiServiceImpl.class); + + public Response organizationsGet(MessageContext messageContext) throws APIManagementException { + + APIAdmin apiAdmin = new APIAdminImpl(); + try { + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + String orgId = null; + if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { + orgId = orgInfo.getOrganizationSelector(); + } + List orgList = apiAdmin.getOrganizations(orgId, + superOrganization); + + OrganizationListDTO organizationsListDTO = OrganizationsMappingUtil.toOrganizationsListDTO(orgList); + return Response.ok().entity(organizationsListDTO).build(); + } catch (APIManagementException e) { + String errorMessage = "Error while retrieving Organizations"; + throw new APIManagementException(errorMessage, e, ExceptionCodes.INTERNAL_ERROR); + } + } + + public Response organizationsOrganizationIdDelete(String organizationId, MessageContext messageContext) + throws APIManagementException { + APIAdmin apiAdmin = new APIAdminImpl(); + try { + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationDetailsDTO organizationInfoDTO = apiAdmin.getOrganizationDetails(organizationId, + superOrganization); + if (organizationInfoDTO == null) { + throw new APIManagementException("Requested Organization not found", + ExceptionCodes.INVALID_ORGANINATION); + } + apiAdmin.deleteOrganization(organizationId, superOrganization); + + APIUtil.logAuditMessage(APIConstants.AuditLogConstants.ORGANIZATION, new Gson().toJson(organizationInfoDTO), + APIConstants.AuditLogConstants.DELETED, RestApiCommonUtil.getLoggedInUsername()); + return Response.ok().build(); + } catch (APIManagementException e) { + String errorMessage = "Error while deleting Organizations"; + throw new APIManagementException(errorMessage, e, ExceptionCodes.INTERNAL_ERROR); + } + } + + public Response organizationsOrganizationIdPut(String organizationId, OrganizationDTO organizationDTO, + MessageContext messageContext) throws APIManagementException { + APIAdmin apiAdmin = new APIAdminImpl(); + try { + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationDetailsDTO organizationInfoDTO = apiAdmin.getOrganizationDetails(organizationId, + superOrganization); + if (organizationInfoDTO == null) { + throw new APIManagementException("Requested Organization not found", + ExceptionCodes.INVALID_ORGANINATION); + } + organizationInfoDTO.setName(organizationDTO.getDisplayName()); // only allow to change the name and desc + organizationInfoDTO.setDescription(organizationDTO.getDescription()); + OrganizationDetailsDTO updatedOrganizationInfoDTO = apiAdmin.updateOrganization(organizationInfoDTO); + APIUtil.logAuditMessage(APIConstants.AuditLogConstants.ORGANIZATION, + new Gson().toJson(updatedOrganizationInfoDTO), APIConstants.AuditLogConstants.UPDATED, + RestApiCommonUtil.getLoggedInUsername()); + OrganizationDTO returnedorganizationDTO = OrganizationsMappingUtil + .toOrganizationsDTO(updatedOrganizationInfoDTO); + return Response.ok().entity(returnedorganizationDTO).build(); + } catch (APIManagementException e) { + String errorMessage = "Error while updating Organization"; + throw new APIManagementException(errorMessage, e, ExceptionCodes.INTERNAL_ERROR); + } + } + + public Response organizationsPost(OrganizationDTO organizationDTO, MessageContext messageContext) + throws APIManagementException { + APIAdmin apiAdmin = new APIAdminImpl(); + try { + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + String orgId = null; + if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { + orgId = orgInfo.getOrganizationSelector(); + organizationDTO.setParentId(orgId); // set current users organization as parent id if available. + } + OrganizationDetailsDTO orgDto = OrganizationsMappingUtil.toOrganizationDetailsDTO(organizationDTO); + orgDto.setTenantDomain(superOrganization); + orgDto = apiAdmin.addOrganization(orgDto); + APIUtil.logAuditMessage(APIConstants.AuditLogConstants.ORGANIZATION, + new Gson().toJson(orgDto), + APIConstants.AuditLogConstants.CREATED, RestApiCommonUtil.getLoggedInUsername()); + URI location = new URI(RestApiConstants.ORGANIZATIONS_PATH + "/" + orgInfo.getId()); + OrganizationDTO returnedorganizationDTO = OrganizationsMappingUtil.toOrganizationsDTO(orgDto); + return Response.created(location).entity(returnedorganizationDTO).build(); + } catch (APIManagementException | URISyntaxException e) { + String errorMessage = "Error while creating Organization"; + throw new APIManagementException(errorMessage, e, ExceptionCodes.INTERNAL_ERROR); + } + } + + @Override + public Response organizationsOrganizationIdGet(String organizationId, MessageContext messageContext) + throws APIManagementException { + APIAdmin apiAdmin = new APIAdminImpl(); + try { + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationDetailsDTO organizationInfoDTO = apiAdmin.getOrganizationDetails(organizationId, + superOrganization); + if (organizationInfoDTO == null) { + throw new APIManagementException("Requested Organization not found", + ExceptionCodes.INVALID_ORGANINATION); + } + OrganizationDTO returnedorganizationDTO = OrganizationsMappingUtil + .toOrganizationsDTO(organizationInfoDTO); + return Response.ok().entity(returnedorganizationDTO).build(); + } catch (APIManagementException e) { + String errorMessage = "Error while retrieving Organizations"; + throw new APIManagementException(errorMessage, e, ExceptionCodes.INTERNAL_ERROR); + } + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java new file mode 100644 index 000000000000..cebf67b5725e --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.wso2.carbon.apimgt.rest.api.admin.v1.utils.mappings; + +import java.util.ArrayList; +import java.util.List; + +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationDTO; +import org.wso2.carbon.apimgt.rest.api.admin.v1.dto.OrganizationListDTO; + +public class OrganizationsMappingUtil { + + public static OrganizationListDTO toOrganizationsListDTO(List orgList) { + OrganizationListDTO listDto = new OrganizationListDTO(); + listDto.setCount(orgList.size()); + List list = new ArrayList(); + for (OrganizationDetailsDTO organizationDTO : orgList) { + OrganizationDTO dto = new OrganizationDTO(); + dto.displayName(organizationDTO.getName()); + dto.setOrganizationId(organizationDTO.getOrganizationId()); + dto.setParentId(organizationDTO.getParentOrganizationId()); + dto.setDescription(organizationDTO.getDescription()); + list.add(dto); + } + listDto.setList(list); + return listDto; + } + + public static OrganizationDetailsDTO toOrganizationDetailsDTO(OrganizationDTO organizationDTO) { + OrganizationDetailsDTO orgDetailsDto = new OrganizationDetailsDTO(); + orgDetailsDto.setName(organizationDTO.getDisplayName()); + orgDetailsDto.setOrganizationId(organizationDTO.getOrganizationId()); + orgDetailsDto.setParentOrganizationId(organizationDTO.getParentId()); + orgDetailsDto.setDescription(organizationDTO.getDescription()); + return orgDetailsDto; + } + + public static OrganizationDTO toOrganizationsDTO(OrganizationDetailsDTO organizationDetailsDto) { + OrganizationDTO orgDto = new OrganizationDTO(); + orgDto.setDisplayName(organizationDetailsDto.getName()); + orgDto.setOrganizationId(organizationDetailsDto.getOrganizationId()); + orgDto.setParentId(organizationDetailsDto.getParentOrganizationId()); + orgDto.setDescription(organizationDetailsDto.getDescription()); + return orgDto; + } + +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml index df63ee9d02c1..33ca9667af62 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml @@ -2006,6 +2006,164 @@ paths: source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" "https://127.0.0.1:9443/api/am/admin/v4/environments/d7cf8523-9180-4255-84fa-6cb171c1f779"' + ###################################################### + # The "Organizations" resource API + ###################################################### + /organizations: + get: + tags: + - Organizations + summary: Get all registered Organizations + description: | + Get all Registered Organizations + responses: + 200: + description: | + OK. + Organizations returned + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationList' + security: + - OAuth2Security: + - apim:admin + - apim:organization_read + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/admin/v4/organizations"' + + post: + tags: + - Organizations + summary: Add an Organizations + description: | + Add a new organization + requestBody: + description: | + Organization object that should to be added + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + required: true + responses: + 201: + description: | + Created. + Successful response with the newly created organization as entity in the body. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + 400: + $ref: '#/components/responses/BadRequest' + security: + - OAuth2Security: + - apim:admin + - apim:organization_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X POST -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/organizations"' + + ###################################################### + # The "Individual Environment" resource APIs + ###################################################### + /organizations/{organizationId}: + get: + tags: + - Organizations + summary: Get an Organization + description: | + Get an organization by organization Id + parameters: + - $ref: '#/components/parameters/organizationId' + responses: + 200: + description: | + OK. + Organization. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + 400: + $ref: '#/components/responses/BadRequest' + 404: + $ref: '#/components/responses/NotFound' + security: + - OAuth2Security: + - apim:admin + - apim:organization_read + x-code-samples: + - lang: Curl + source: 'curl -k -X GET -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/organizations/d7cf8523-9180-4255-84fa-6cb171c1f779"' + put: + tags: + - Organizations + summary: Update an Organization + description: | + Update an organization by organization Id + parameters: + - $ref: '#/components/parameters/organizationId' + requestBody: + description: | + Organization object with updated information + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + required: true + responses: + 200: + description: | + OK. + Organization updated. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + 400: + $ref: '#/components/responses/BadRequest' + 404: + $ref: '#/components/responses/NotFound' + security: + - OAuth2Security: + - apim:admin + - apim:organization_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X PUT -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/organizations/d7cf8523-9180-4255-84fa-6cb171c1f779"' + + delete: + tags: + - Organizations + summary: Delete an Organization + description: | + Delete an organization by organization Id + parameters: + - $ref: '#/components/parameters/organizationId' + responses: + 200: + description: | + OK. + Organization successfully deleted. + content: {} + 404: + $ref: '#/components/responses/NotFound' + security: + - OAuth2Security: + - apim:admin + - apim:organization_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/admin/v4/organizations/d7cf8523-9180-4255-84fa-6cb171c1f779"' + ###################################################### # The Bot Detection Data API resources ###################################################### @@ -4712,6 +4870,44 @@ components: type: array items: $ref: '#/components/schemas/Environment' + Organization: + title: Organization + required: + - organizationId + type: object + properties: + organizationId: + type: string + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the organizatoin. + parentId: + type: string + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the parent organization if there is any. + displayName: + maxLength: 255 + minLength: 1 + type: string + example: My Organization + description: + maxLength: 1023 + type: string + example: My Organization Description + OrganizationList: + title: Organization List + type: object + properties: + count: + type: integer + description: | + Number of Organizationa returned. + example: 1 + list: + type: array + items: + $ref: '#/components/schemas/Organization' LLMProviderRequest: title: LLMProvider type: object @@ -6034,6 +6230,14 @@ components: required: true schema: type: string + organizationId: + name: organizationId + in: path + description: | + Organization UUID + required: true + schema: + type: string llmProviderId: name: llmProviderId in: path @@ -6199,3 +6403,5 @@ components: apim:keymanagers_manage: Manage Key Managers apim:api_provider_change: Retrieve and manage applications apim:llm_provider_manage: Manage LLM Providers + apim:organization_manage: Manage Organizations + apim:organization_read: Read Organizations diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/webapp/WEB-INF/web.xml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/webapp/WEB-INF/web.xml index 39e0f1e4fbba..806c4d8ccfd7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/webapp/WEB-INF/web.xml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/webapp/WEB-INF/web.xml @@ -56,7 +56,8 @@ org.wso2.carbon.apimgt.rest.api.admin.v1.TenantConfigSchemaApi, org.wso2.carbon.apimgt.rest.api.admin.v1.GlobalKeyManagersApi, org.wso2.carbon.apimgt.rest.api.admin.v1.ApisApi, - org.wso2.carbon.apimgt.rest.api.admin.v1.TransactionCountApi + org.wso2.carbon.apimgt.rest.api.admin.v1.TransactionCountApi, + org.wso2.carbon.apimgt.rest.api.admin.v1.OrganizationsApi diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java index 7b439cc69280..2740cd5a184a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/java/org/wso2/carbon/apimgt/rest/api/common/RestApiConstants.java @@ -135,6 +135,7 @@ public final class RestApiConstants { public static final String RESOURCE_PATH_CATEGORY = "/categories"; public static final String RESOURCE_PATH_LLM_PROVIDER = "/llm-providers"; public static final String KEY_MANAGERS = "/key-managers"; + public static final String ORGANIZATIONS_PATH= "/organizations"; // Used in XACML authentication interceptor: Deprecated public static final String SERVER_URL = "server_url"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml index df63ee9d02c1..33ca9667af62 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml @@ -2006,6 +2006,164 @@ paths: source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" "https://127.0.0.1:9443/api/am/admin/v4/environments/d7cf8523-9180-4255-84fa-6cb171c1f779"' + ###################################################### + # The "Organizations" resource API + ###################################################### + /organizations: + get: + tags: + - Organizations + summary: Get all registered Organizations + description: | + Get all Registered Organizations + responses: + 200: + description: | + OK. + Organizations returned + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationList' + security: + - OAuth2Security: + - apim:admin + - apim:organization_read + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/admin/v4/organizations"' + + post: + tags: + - Organizations + summary: Add an Organizations + description: | + Add a new organization + requestBody: + description: | + Organization object that should to be added + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + required: true + responses: + 201: + description: | + Created. + Successful response with the newly created organization as entity in the body. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + 400: + $ref: '#/components/responses/BadRequest' + security: + - OAuth2Security: + - apim:admin + - apim:organization_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X POST -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/organizations"' + + ###################################################### + # The "Individual Environment" resource APIs + ###################################################### + /organizations/{organizationId}: + get: + tags: + - Organizations + summary: Get an Organization + description: | + Get an organization by organization Id + parameters: + - $ref: '#/components/parameters/organizationId' + responses: + 200: + description: | + OK. + Organization. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + 400: + $ref: '#/components/responses/BadRequest' + 404: + $ref: '#/components/responses/NotFound' + security: + - OAuth2Security: + - apim:admin + - apim:organization_read + x-code-samples: + - lang: Curl + source: 'curl -k -X GET -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/organizations/d7cf8523-9180-4255-84fa-6cb171c1f779"' + put: + tags: + - Organizations + summary: Update an Organization + description: | + Update an organization by organization Id + parameters: + - $ref: '#/components/parameters/organizationId' + requestBody: + description: | + Organization object with updated information + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + required: true + responses: + 200: + description: | + OK. + Organization updated. + content: + application/json: + schema: + $ref: '#/components/schemas/Organization' + 400: + $ref: '#/components/responses/BadRequest' + 404: + $ref: '#/components/responses/NotFound' + security: + - OAuth2Security: + - apim:admin + - apim:organization_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X PUT -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + -H "Content-Type: application/json" -d @data.json "https://127.0.0.1:9443/api/am/admin/v4/organizations/d7cf8523-9180-4255-84fa-6cb171c1f779"' + + delete: + tags: + - Organizations + summary: Delete an Organization + description: | + Delete an organization by organization Id + parameters: + - $ref: '#/components/parameters/organizationId' + responses: + 200: + description: | + OK. + Organization successfully deleted. + content: {} + 404: + $ref: '#/components/responses/NotFound' + security: + - OAuth2Security: + - apim:admin + - apim:organization_manage + x-code-samples: + - lang: Curl + source: 'curl -k -X DELETE -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/admin/v4/organizations/d7cf8523-9180-4255-84fa-6cb171c1f779"' + ###################################################### # The Bot Detection Data API resources ###################################################### @@ -4712,6 +4870,44 @@ components: type: array items: $ref: '#/components/schemas/Environment' + Organization: + title: Organization + required: + - organizationId + type: object + properties: + organizationId: + type: string + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the organizatoin. + parentId: + type: string + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the parent organization if there is any. + displayName: + maxLength: 255 + minLength: 1 + type: string + example: My Organization + description: + maxLength: 1023 + type: string + example: My Organization Description + OrganizationList: + title: Organization List + type: object + properties: + count: + type: integer + description: | + Number of Organizationa returned. + example: 1 + list: + type: array + items: + $ref: '#/components/schemas/Organization' LLMProviderRequest: title: LLMProvider type: object @@ -6034,6 +6230,14 @@ components: required: true schema: type: string + organizationId: + name: organizationId + in: path + description: | + Organization UUID + required: true + schema: + type: string llmProviderId: name: llmProviderId in: path @@ -6199,3 +6403,5 @@ components: apim:keymanagers_manage: Manage Key Managers apim:api_provider_change: Retrieve and manage applications apim:llm_provider_manage: Manage LLM Providers + apim:organization_manage: Manage Organizations + apim:organization_read: Read Organizations diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index 2294342a6f28..f244c2ff302e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -3977,6 +3977,34 @@ paths: "https://127.0.0.1:9443/api/am/publisher/v4/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/resource-paths"' operationId: getAPIResourcePaths + /organizations: + get: + tags: + - Organizations + summary: Get all registered Organizations + description: | + Get all Registered Organizations + responses: + 200: + description: | + OK. + Organizations returned + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationList' + security: + - OAuth2Security: + - apim:api_view + - apim:api_manage + - apim:api_import_export + - apim:api_product_import_export + - apim:publisher_organization_read + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/organizations"' + /apis/{apiId}/auditapi: get: tags: @@ -12210,6 +12238,42 @@ components: type: array items: $ref: '#/components/schemas/Endpoint' + Organization: + title: Organization + required: + - organizationId + type: object + properties: + organizationId: + type: string + readOnly: true + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the organizatoin. + parentId: + type: string + readOnly: true + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the parent organization if there is any. + displayName: + maxLength: 255 + minLength: 1 + type: string + example: My Organization + OrganizationList: + title: Organization List + type: object + properties: + count: + type: integer + description: | + Number of Organizationa returned. + example: 1 + list: + type: array + items: + $ref: '#/components/schemas/Organization' Scope: title: Scope required: @@ -14381,3 +14445,4 @@ components: apim:subscription_approval_view: Approve subscription creation requests apim:subscription_approval_manage: Approve subscription update requests apim:llm_provider_read: Read LLM Providers + apim:publisher_organization_read: Read organization diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationDTO.java new file mode 100644 index 000000000000..deca49cb60eb --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationDTO.java @@ -0,0 +1,124 @@ +package org.wso2.carbon.apimgt.rest.api.publisher.v1.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; + +import javax.xml.bind.annotation.*; +import org.wso2.carbon.apimgt.rest.api.common.annotations.Scope; +import com.fasterxml.jackson.annotation.JsonCreator; + +import javax.validation.Valid; + + + +public class OrganizationDTO { + + private String organizationId = null; + private String parentId = null; + private String displayName = null; + + /** + * UUID of the organizatoin. + **/ + public OrganizationDTO organizationId(String organizationId) { + this.organizationId = organizationId; + return this; + } + + + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", required = true, value = "UUID of the organizatoin. ") + @JsonProperty("organizationId") + @NotNull + public String getOrganizationId() { + return organizationId; + } + public void setOrganizationId(String organizationId) { + this.organizationId = organizationId; + } + + /** + * UUID of the parent organization if there is any. + **/ + public OrganizationDTO parentId(String parentId) { + this.parentId = parentId; + return this; + } + + + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", value = "UUID of the parent organization if there is any. ") + @JsonProperty("parentId") + public String getParentId() { + return parentId; + } + public void setParentId(String parentId) { + this.parentId = parentId; + } + + /** + **/ + public OrganizationDTO displayName(String displayName) { + this.displayName = displayName; + return this; + } + + + @ApiModelProperty(example = "My Organization", value = "") + @JsonProperty("displayName") + @Size(min=1,max=255) public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrganizationDTO organization = (OrganizationDTO) o; + return Objects.equals(organizationId, organization.organizationId) && + Objects.equals(parentId, organization.parentId) && + Objects.equals(displayName, organization.displayName); + } + + @Override + public int hashCode() { + return Objects.hash(organizationId, parentId, displayName); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OrganizationDTO {\n"); + + sb.append(" organizationId: ").append(toIndentedString(organizationId)).append("\n"); + sb.append(" parentId: ").append(toIndentedString(parentId)).append("\n"); + sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationListDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationListDTO.java new file mode 100644 index 000000000000..a326e7736c29 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationListDTO.java @@ -0,0 +1,106 @@ +package org.wso2.carbon.apimgt.rest.api.publisher.v1.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationDTO; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; + +import javax.xml.bind.annotation.*; +import org.wso2.carbon.apimgt.rest.api.common.annotations.Scope; +import com.fasterxml.jackson.annotation.JsonCreator; + +import javax.validation.Valid; + + + +public class OrganizationListDTO { + + private Integer count = null; + private List list = new ArrayList(); + + /** + * Number of Organizationa returned. + **/ + public OrganizationListDTO count(Integer count) { + this.count = count; + return this; + } + + + @ApiModelProperty(example = "1", value = "Number of Organizationa returned. ") + @JsonProperty("count") + public Integer getCount() { + return count; + } + public void setCount(Integer count) { + this.count = count; + } + + /** + **/ + public OrganizationListDTO list(List list) { + this.list = list; + return this; + } + + + @ApiModelProperty(value = "") + @Valid + @JsonProperty("list") + public List getList() { + return list; + } + public void setList(List list) { + this.list = list; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrganizationListDTO organizationList = (OrganizationListDTO) o; + return Objects.equals(count, organizationList.count) && + Objects.equals(list, organizationList.list); + } + + @Override + public int hashCode() { + return Objects.hash(count, list); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OrganizationListDTO {\n"); + + sb.append(" count: ").append(toIndentedString(count)).append("\n"); + sb.append(" list: ").append(toIndentedString(list)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApi.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApi.java new file mode 100644 index 000000000000..30757e5f9f2d --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApi.java @@ -0,0 +1,56 @@ +package org.wso2.carbon.apimgt.rest.api.publisher.v1; + +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationListDTO; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.OrganizationsApiService; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.impl.OrganizationsApiServiceImpl; +import org.wso2.carbon.apimgt.api.APIManagementException; + +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; +import javax.inject.Inject; + +import io.swagger.annotations.*; +import java.io.InputStream; + +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; + +import java.util.Map; +import java.util.List; +import javax.validation.constraints.*; +@Path("/organizations") + +@Api(description = "the organizations API") + + + + +public class OrganizationsApi { + + @Context MessageContext securityContext; + +OrganizationsApiService delegate = new OrganizationsApiServiceImpl(); + + + @GET + + + @Produces({ "application/json" }) + @ApiOperation(value = "Get all registered Organizations", notes = "Get all Registered Organizations ", response = OrganizationListDTO.class, authorizations = { + @Authorization(value = "OAuth2Security", scopes = { + @AuthorizationScope(scope = "apim:api_view", description = "View API"), + @AuthorizationScope(scope = "apim:api_manage", description = "Manage all API related operations"), + @AuthorizationScope(scope = "apim:api_import_export", description = "Import and export APIs related operations"), + @AuthorizationScope(scope = "apim:api_product_import_export", description = "Import and export API Products related operations"), + @AuthorizationScope(scope = "apim:publisher_organization_read", description = "Read organization") + }) + }, tags={ "Organizations" }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. Organizations returned ", response = OrganizationListDTO.class) }) + public Response organizationsGet() throws APIManagementException{ + return delegate.organizationsGet(securityContext); + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApiService.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApiService.java new file mode 100644 index 000000000000..99d63e265d95 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/OrganizationsApiService.java @@ -0,0 +1,24 @@ +package org.wso2.carbon.apimgt.rest.api.publisher.v1; + +import org.wso2.carbon.apimgt.rest.api.publisher.v1.*; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.*; + +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; + +import org.wso2.carbon.apimgt.api.APIManagementException; + +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationListDTO; + +import java.util.List; + +import java.io.InputStream; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; + + +public interface OrganizationsApiService { + public Response organizationsGet(MessageContext messageContext) throws APIManagementException; +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java new file mode 100644 index 000000000000..8e4d5cee029b --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.wso2.carbon.apimgt.rest.api.publisher.v1.impl; + +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.api.APIProvider; +import org.wso2.carbon.apimgt.api.ExceptionCodes; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; +import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.*; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.utils.OrganizationsMappingUtil; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.*; + +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.MessageContext; + +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationListDTO; +import org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil; + +import java.util.ArrayList; +import java.util.List; + +import java.io.InputStream; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.SecurityContext; + + +public class OrganizationsApiServiceImpl implements OrganizationsApiService { + + public Response organizationsGet(MessageContext messageContext) throws APIManagementException { + + try { + APIProvider apiProvider = RestApiCommonUtil.getLoggedInUserProvider(); + String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); + String orgId = null; + if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { + orgId = orgInfo.getOrganizationSelector(); + } + List orgList = apiProvider.getOrganizations(orgId, superOrganization); + + OrganizationListDTO organizationsListDTO = OrganizationsMappingUtil.toOrganizationsListDTO(orgList); + return Response.ok().entity(organizationsListDTO).build(); + } catch (APIManagementException e) { + String errorMessage = "Error while retrieving Organizations"; + throw new APIManagementException(errorMessage, e, ExceptionCodes.INTERNAL_ERROR); + } + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java new file mode 100644 index 000000000000..acf81ac93158 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.wso2.carbon.apimgt.rest.api.publisher.v1.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.*; + + +public class OrganizationsMappingUtil { + + public static OrganizationListDTO toOrganizationsListDTO(List orgList) { + OrganizationListDTO listDto = new OrganizationListDTO(); + listDto.setCount(orgList.size()); + List list = new ArrayList(); + for (OrganizationDetailsDTO organizationDTO : orgList) { + OrganizationDTO dto = new OrganizationDTO(); + dto.displayName(organizationDTO.getName()); + dto.setOrganizationId(organizationDTO.getOrganizationId()); + dto.setParentId(organizationDTO.getParentOrganizationId()); + list.add(dto); + } + listDto.setList(list); + return listDto; + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index 2294342a6f28..f244c2ff302e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -3977,6 +3977,34 @@ paths: "https://127.0.0.1:9443/api/am/publisher/v4/apis/96077508-fd01-4fae-bc64-5de0e2baf43c/resource-paths"' operationId: getAPIResourcePaths + /organizations: + get: + tags: + - Organizations + summary: Get all registered Organizations + description: | + Get all Registered Organizations + responses: + 200: + description: | + OK. + Organizations returned + content: + application/json: + schema: + $ref: '#/components/schemas/OrganizationList' + security: + - OAuth2Security: + - apim:api_view + - apim:api_manage + - apim:api_import_export + - apim:api_product_import_export + - apim:publisher_organization_read + x-code-samples: + - lang: Curl + source: 'curl -k -H "Authorization: Bearer ae4eae22-3f65-387b-a171-d37eaa366fa8" + "https://127.0.0.1:9443/api/am/publisher/v4/organizations"' + /apis/{apiId}/auditapi: get: tags: @@ -12210,6 +12238,42 @@ components: type: array items: $ref: '#/components/schemas/Endpoint' + Organization: + title: Organization + required: + - organizationId + type: object + properties: + organizationId: + type: string + readOnly: true + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the organizatoin. + parentId: + type: string + readOnly: true + example: ece92bdc-e1e6-325c-b6f4-656208a041e9 + description: | + UUID of the parent organization if there is any. + displayName: + maxLength: 255 + minLength: 1 + type: string + example: My Organization + OrganizationList: + title: Organization List + type: object + properties: + count: + type: integer + description: | + Number of Organizationa returned. + example: 1 + list: + type: array + items: + $ref: '#/components/schemas/Organization' Scope: title: Scope required: @@ -14381,3 +14445,4 @@ components: apim:subscription_approval_view: Approve subscription creation requests apim:subscription_approval_manage: Approve subscription update requests apim:llm_provider_read: Read LLM Providers + apim:publisher_organization_read: Read organization diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/webapp/WEB-INF/web.xml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/webapp/WEB-INF/web.xml index 329abcfaff47..696afb3e7fa0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/webapp/WEB-INF/web.xml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/webapp/WEB-INF/web.xml @@ -54,7 +54,8 @@ org.wso2.carbon.apimgt.rest.api.publisher.v1.LinterCustomRulesApi, org.wso2.carbon.apimgt.rest.api.publisher.v1.GatewayPoliciesApi, org.wso2.carbon.apimgt.rest.api.publisher.v1.WorkflowsApi, - org.wso2.carbon.apimgt.rest.api.publisher.v1.LlmProvidersApi + org.wso2.carbon.apimgt.rest.api.publisher.v1.LlmProvidersApi, + org.wso2.carbon.apimgt.rest.api.publisher.v1.OrganizationsApi diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index ab3bd2d98b95..db5c26cccdc6 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -1998,6 +1998,15 @@ CREATE TABLE IF NOT EXISTS AM_POLICY_GLOBAL ( UNIQUE (UUID) ); +CREATE TABLE IF NOT EXISTS AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50) NOT NULL, + DESCRIPTION VARCHAR(256) NULL, + TENANT_DOMAIN VARCHAR(255), + PRIMARY KEY (ORG_UUID) + ); + CREATE TABLE IF NOT EXISTS AM_THROTTLE_TIER_PERMISSIONS ( THROTTLE_TIER_PERMISSIONS_ID INT NOT NULL AUTO_INCREMENT, TIER VARCHAR(50) NULL, From 0a545c74de382d6deac92e0d049504021019193d Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 23 Jan 2025 17:19:04 +0530 Subject: [PATCH 50/74] Restructure org persistance --- .../carbon/apimgt/api/ExceptionCodes.java | 3 +- .../api/dto/OrganizationDetailsDTO.java | 13 +++- .../wso2/carbon/apimgt/impl/APIAdminImpl.java | 15 +++- .../carbon/apimgt/impl/APIProviderImpl.java | 2 +- .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 72 ++++++++++++------- .../impl/dao/constants/SQLConstants.java | 17 +++-- .../api/admin/v1/dto/OrganizationDTO.java | 47 ++++++++---- .../v1/impl/OrganizationsApiServiceImpl.java | 2 +- .../mappings/OrganizationsMappingUtil.java | 9 ++- .../src/main/resources/admin-api.yaml | 11 ++- .../src/main/resources/admin-api.yaml | 11 ++- .../src/main/resources/publisher-api.yaml | 13 +++- .../api/publisher/v1/dto/OrganizationDTO.java | 69 ++++++++++++++---- .../v1/impl/OrganizationsApiServiceImpl.java | 3 + .../v1/utils/OrganizationsMappingUtil.java | 4 +- .../src/main/resources/publisher-api.yaml | 13 +++- .../src/main/resources/sql/h2.sql | 5 +- 17 files changed, 228 insertions(+), 81 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java index 931b0b7bba01..9b51c2eebf25 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/ExceptionCodes.java @@ -425,8 +425,9 @@ public enum ExceptionCodes implements ErrorHandler { // Tenant related INVALID_TENANT(901300,"Tenant Not Found", 400, "Tenant Not Found"), - // Tenant related + // Organization related INVALID_ORGANINATION(901301,"Organization Not Found", 404, "Organization Not Found"), + MISSING_ORGANINATION(901302,"Organization Not Found", 403, "User does not belong to any organization"), // Key Manager Related INVALID_KEY_MANAGER_TYPE(901400, "Key Manager Type not configured", 400, "Key Manager Type not configured"), REQUIRED_KEY_MANAGER_CONFIGURATION_MISSING(901401,"Required Key Manager configuration missing",400,"Missing " + diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java index 712bbf0ad8fd..ea4856dee27b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java @@ -23,6 +23,7 @@ public class OrganizationDetailsDTO { private String organizationId; private String parentOrganizationId; + private String externalOrganizationReference; private String Name; private String tenantDomain; private String description; @@ -56,11 +57,17 @@ public String getDescription() { public void setDescription(String description) { this.description = description; } + public String getExternalOrganizationReference() { + return externalOrganizationReference; + } + public void setExternalOrganizationReference(String externalOrganizationReference) { + this.externalOrganizationReference = externalOrganizationReference; + } @Override public String toString() { - return "OrganizationDTO [organizationId=" + organizationId + ", parentOrganizationId=" + parentOrganizationId - + ", Name=" + Name + ", tenantDomain=" + tenantDomain + ", description=" + description + "]"; + return "OrganizationDetailsDTO [organizationId=" + organizationId + ", parentOrganizationId=" + + parentOrganizationId + ", externalOrganizationReference=" + externalOrganizationReference + ", Name=" + + Name + ", tenantDomain=" + tenantDomain + ", description=" + description + "]"; } - } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java index 6f9bdf1bb71b..d64f8d4eb605 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java @@ -1830,13 +1830,24 @@ public List getGlobalKeyManagerConfigurations(String @Override public List getOrganizations(String parentOrgId, String tenantDomain) throws APIManagementException { - List organizationsList = apiMgtDAO.getOrganizations(parentOrgId, tenantDomain); + List organizationsList = apiMgtDAO.getChildOrganizations(parentOrgId, tenantDomain); return organizationsList; } @Override public OrganizationDetailsDTO addOrganization(OrganizationDetailsDTO orgDto) throws APIManagementException { - apiMgtDAO.addOrganization(orgDto); + + //If there is an organization entry already available for external reference, update it + OrganizationDetailsDTO savedOrgInfo = apiMgtDAO.getOrganizationDetalsByExternalOrgId( + orgDto.getExternalOrganizationReference(), orgDto.getTenantDomain()); + if (savedOrgInfo != null) { + orgDto.setOrganizationId(savedOrgInfo.getOrganizationId()); + apiMgtDAO.updateOrganizationDetails(orgDto); + } else { + savedOrgInfo = apiMgtDAO.addOrganization(orgDto); + orgDto.setOrganizationId(savedOrgInfo.getOrganizationId()); + } + return orgDto; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java index 80114954e099..4b6bebe81d71 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIProviderImpl.java @@ -7783,7 +7783,7 @@ public org.wso2.carbon.apimgt.api.dto.WorkflowDTO retrieveWorkflow( @Override public List getOrganizations(String orgId, String tenantDomain) throws APIManagementException { - List organizationsList = apiMgtDAO.getOrganizations(orgId, tenantDomain); + List organizationsList = apiMgtDAO.getChildOrganizations(orgId, tenantDomain); return organizationsList; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index 37ad6abad9a6..9c6ce0169667 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -10296,17 +10296,18 @@ public void setDefaultVersion(APIProduct apiProduct) throws APIManagementExcepti } - public void addOrganization(OrganizationDetailsDTO organizationDTO) throws APIManagementException { - + public OrganizationDetailsDTO addOrganization(OrganizationDetailsDTO organizationDTO) throws APIManagementException { try (Connection conn = APIMgtDBUtil.getConnection()) { conn.setAutoCommit(false); try (PreparedStatement preparedStatement = conn .prepareStatement(SQLConstants.OrganizationSqlConstants.ADD_ORGANIZATION)) { + organizationDTO.setOrganizationId(UUID.randomUUID().toString()); preparedStatement.setString(1, organizationDTO.getOrganizationId()); - preparedStatement.setString(2, organizationDTO.getName()); - preparedStatement.setString(3, organizationDTO.getParentOrganizationId()); - preparedStatement.setString(4, organizationDTO.getDescription()); - preparedStatement.setString(5, organizationDTO.getTenantDomain()); + preparedStatement.setString(2, organizationDTO.getExternalOrganizationReference()); + preparedStatement.setString(3, organizationDTO.getName()); + preparedStatement.setString(4, organizationDTO.getParentOrganizationId()); + preparedStatement.setString(5, organizationDTO.getDescription()); + preparedStatement.setString(6, organizationDTO.getTenantDomain()); preparedStatement.executeUpdate(); conn.commit(); } @@ -10315,33 +10316,27 @@ public void addOrganization(OrganizationDetailsDTO organizationDTO) throws APIMa + " in tenant " + organizationDTO.getTenantDomain(); handleException(message, e); } + return organizationDTO; } - public List getOrganizations(String parentOrganizationId, String tenantDomain) + public List getChildOrganizations(String parentOrganizationId, String rootOrg) throws APIManagementException { List organizationList = new ArrayList(); - String query; - String param; - if (!StringUtils.isEmpty(parentOrganizationId)) { - query = SQLConstants.OrganizationSqlConstants.GET_ORGANIZATIONS_BY_PARENT_ORG_ID; - param = parentOrganizationId; - } else { - query = SQLConstants.OrganizationSqlConstants.GET_ORGANIZATIONS_BY_TENAND_DOMAIN; - param = tenantDomain; - } try (Connection connection = APIMgtDBUtil.getConnection(); PreparedStatement prepStmt = connection - .prepareStatement(query)) { - prepStmt.setString(1, param); + .prepareStatement(SQLConstants.OrganizationSqlConstants.GET_ORGANIZATIONS_BY_PARENT_ORG_ID)) { + prepStmt.setString(1, parentOrganizationId); + prepStmt.setString(2, rootOrg); try (ResultSet resultSet = prepStmt.executeQuery()) { while (resultSet.next()) { OrganizationDetailsDTO organization = new OrganizationDetailsDTO(); organization.setOrganizationId(resultSet.getString("ORG_UUID")); organization.setParentOrganizationId(resultSet.getString("PARENT_ORG_UUID")); + organization.setExternalOrganizationReference(resultSet.getString("EXT_ORG_ID")); organization.setName(resultSet.getString("DISPLAY_NAME")); organization.setDescription(resultSet.getString("DESCRIPTION")); - organization.setTenantDomain(resultSet.getString("TENANT_DOMAIN")); + organization.setTenantDomain(resultSet.getString("ROOT_ORGANIZATION")); organizationList.add(organization); } } @@ -10351,7 +10346,7 @@ public List getOrganizations(String parentOrganizationId return organizationList; } - public OrganizationDetailsDTO getOrganizationDetails(String organizationId, String tenantDomain) + public OrganizationDetailsDTO getOrganizationDetails(String organizationId, String rootOrg) throws APIManagementException { OrganizationDetailsDTO organization = null; @@ -10359,15 +10354,16 @@ public OrganizationDetailsDTO getOrganizationDetails(String organizationId, Stri PreparedStatement prepStmt = connection .prepareStatement(SQLConstants.OrganizationSqlConstants.GET_ORGANIZATION_BY_ORG_ID);) { prepStmt.setString(1, organizationId); - prepStmt.setString(2, tenantDomain); + prepStmt.setString(2, rootOrg); try (ResultSet resultSet = prepStmt.executeQuery()) { if (resultSet.next()) { organization = new OrganizationDetailsDTO(); organization.setOrganizationId(resultSet.getString("ORG_UUID")); organization.setParentOrganizationId(resultSet.getString("PARENT_ORG_UUID")); + organization.setExternalOrganizationReference(resultSet.getString("EXT_ORG_ID")); organization.setName(resultSet.getString("DISPLAY_NAME")); organization.setDescription(resultSet.getString("DESCRIPTION")); - organization.setTenantDomain(resultSet.getString("TENANT_DOMAIN")); + organization.setTenantDomain(resultSet.getString("ROOT_ORGANIZATION")); } } } catch (SQLException e) { @@ -10376,14 +10372,14 @@ public OrganizationDetailsDTO getOrganizationDetails(String organizationId, Stri return organization; } - public void deleteOrganizationDetails(String organizationId, String tenantDomain) + public void deleteOrganizationDetails(String organizationId, String rootOrg) throws APIManagementException { try (Connection connection = APIMgtDBUtil.getConnection(); PreparedStatement prepStmt = connection .prepareStatement(SQLConstants.OrganizationSqlConstants.DELETE_ORGANIZATION);) { connection.setAutoCommit(false); prepStmt.setString(1, organizationId); - prepStmt.setString(2, tenantDomain); + prepStmt.setString(2, rootOrg); prepStmt.executeUpdate(); connection.commit(); } catch (SQLException e) { @@ -10399,7 +10395,8 @@ public void updateOrganizationDetails(OrganizationDetailsDTO organizationDetails .prepareStatement(SQLConstants.OrganizationSqlConstants.UPDATE_ORGANIZATION)) { preparedStatement.setString(1, organizationDetailsDTO.getName()); preparedStatement.setString(2, organizationDetailsDTO.getDescription()); - preparedStatement.setString(3, organizationDetailsDTO.getOrganizationId()); + preparedStatement.setString(3, organizationDetailsDTO.getExternalOrganizationReference()); + preparedStatement.setString(4, organizationDetailsDTO.getOrganizationId()); preparedStatement.executeUpdate(); conn.commit(); } @@ -10409,6 +10406,31 @@ public void updateOrganizationDetails(OrganizationDetailsDTO organizationDetails } } + public OrganizationDetailsDTO getOrganizationDetalsByExternalOrgId(String externalOrgId, String rootOrg) + throws APIManagementException { + OrganizationDetailsDTO organization = null; + try (Connection connection = APIMgtDBUtil.getConnection(); + PreparedStatement prepStmt = connection + .prepareStatement(SQLConstants.OrganizationSqlConstants.GET_ORGANIZATION_BY_EXTERNAL_ORG_ID);) { + prepStmt.setString(1, externalOrgId); + prepStmt.setString(2, rootOrg); + try (ResultSet resultSet = prepStmt.executeQuery()) { + if (resultSet.next()) { + organization = new OrganizationDetailsDTO(); + organization.setOrganizationId(resultSet.getString("ORG_UUID")); + organization.setParentOrganizationId(resultSet.getString("PARENT_ORG_UUID")); + organization.setExternalOrganizationReference(resultSet.getString("EXT_ORG_ID")); + organization.setName(resultSet.getString("DISPLAY_NAME")); + organization.setDescription(resultSet.getString("DESCRIPTION")); + organization.setTenantDomain(resultSet.getString("ROOT_ORGANIZATION")); + } + } + } catch (SQLException e) { + handleException("Failed to get organization for organization Id : " + externalOrgId, e); + } + return organization; + } + public API getLightWeightAPIInfoByAPIIdentifier(APIIdentifier apiIdentifier, String organization) throws APIManagementException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index 465fb07b7461..4f01d12a7487 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -3831,23 +3831,26 @@ public static class KeyManagerSqlConstants { public static class OrganizationSqlConstants { public static final String ADD_ORGANIZATION = - " INSERT INTO AM_ORGANIZATION_MAPPING (ORG_UUID,DISPLAY_NAME,PARENT_ORG_UUID,DESCRIPTION,TENANT_DOMAIN) " + - "VALUES (?,?,?,?,?)"; + " INSERT INTO AM_ORGANIZATION_MAPPING (ORG_UUID,EXT_ORG_ID,DISPLAY_NAME,PARENT_ORG_UUID,DESCRIPTION,ROOT_ORGANIZATION) " + + "VALUES (?,?,?,?,?,?)"; public static final String UPDATE_ORGANIZATION = - "UPDATE AM_ORGANIZATION_MAPPING SET DISPLAY_NAME = ?, DESCRIPTION = ? WHERE ORG_UUID = ?"; + "UPDATE AM_ORGANIZATION_MAPPING SET DISPLAY_NAME = ?, DESCRIPTION = ?, EXT_ORG_ID=? WHERE ORG_UUID = ?"; public static final String DELETE_ORGANIZATION = - "DELETE FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID = ? AND TENANT_DOMAIN=?"; + "DELETE FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID = ? AND ROOT_ORGANIZATION=?"; public static final String GET_ORGANIZATIONS_BY_PARENT_ORG_ID = - "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE PARENT_ORG_UUID=?"; + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE PARENT_ORG_UUID=? AND ROOT_ORGANIZATION=?"; public static final String GET_ORGANIZATION_BY_ORG_ID = - "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID=? AND TENANT_DOMAIN=?"; + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID=? AND ROOT_ORGANIZATION=?"; + + public static final String GET_ORGANIZATION_BY_EXTERNAL_ORG_ID = + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE EXT_ORG_ID=? AND ROOT_ORGANIZATION=?"; public static final String GET_ORGANIZATIONS_BY_TENAND_DOMAIN = - "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE TENANT_DOMAIN=?"; + "SELECT * FROM AM_ORGANIZATION_MAPPING WHERE ROOT_ORGANIZATION=?"; } /** diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java index 3d5d16c7bb7c..b9a59adb879c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java @@ -21,12 +21,13 @@ public class OrganizationDTO { private String organizationId = null; - private String parentId = null; + private String externalOrganizationId = null; + private String parentOrganizationId = null; private String displayName = null; private String description = null; /** - * UUID of the organizatoin. + * UUID of the organization. **/ public OrganizationDTO organizationId(String organizationId) { this.organizationId = organizationId; @@ -34,7 +35,7 @@ public OrganizationDTO organizationId(String organizationId) { } - @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", required = true, value = "UUID of the organizatoin. ") + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", required = true, value = "UUID of the organization. ") @JsonProperty("organizationId") @NotNull public String getOrganizationId() { @@ -44,22 +45,40 @@ public void setOrganizationId(String organizationId) { this.organizationId = organizationId; } + /** + * External id of the organization. + **/ + public OrganizationDTO externalOrganizationId(String externalOrganizationId) { + this.externalOrganizationId = externalOrganizationId; + return this; + } + + + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", value = "External id of the organization. ") + @JsonProperty("externalOrganizationId") + public String getExternalOrganizationId() { + return externalOrganizationId; + } + public void setExternalOrganizationId(String externalOrganizationId) { + this.externalOrganizationId = externalOrganizationId; + } + /** * UUID of the parent organization if there is any. **/ - public OrganizationDTO parentId(String parentId) { - this.parentId = parentId; + public OrganizationDTO parentOrganizationId(String parentOrganizationId) { + this.parentOrganizationId = parentOrganizationId; return this; } @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", value = "UUID of the parent organization if there is any. ") - @JsonProperty("parentId") - public String getParentId() { - return parentId; + @JsonProperty("parentOrganizationId") + public String getParentOrganizationId() { + return parentOrganizationId; } - public void setParentId(String parentId) { - this.parentId = parentId; + public void setParentOrganizationId(String parentOrganizationId) { + this.parentOrganizationId = parentOrganizationId; } /** @@ -107,14 +126,15 @@ public boolean equals(java.lang.Object o) { } OrganizationDTO organization = (OrganizationDTO) o; return Objects.equals(organizationId, organization.organizationId) && - Objects.equals(parentId, organization.parentId) && + Objects.equals(externalOrganizationId, organization.externalOrganizationId) && + Objects.equals(parentOrganizationId, organization.parentOrganizationId) && Objects.equals(displayName, organization.displayName) && Objects.equals(description, organization.description); } @Override public int hashCode() { - return Objects.hash(organizationId, parentId, displayName, description); + return Objects.hash(organizationId, externalOrganizationId, parentOrganizationId, displayName, description); } @Override @@ -123,7 +143,8 @@ public String toString() { sb.append("class OrganizationDTO {\n"); sb.append(" organizationId: ").append(toIndentedString(organizationId)).append("\n"); - sb.append(" parentId: ").append(toIndentedString(parentId)).append("\n"); + sb.append(" externalOrganizationId: ").append(toIndentedString(externalOrganizationId)).append("\n"); + sb.append(" parentOrganizationId: ").append(toIndentedString(parentOrganizationId)).append("\n"); sb.append(" displayName: ").append(toIndentedString(displayName)).append("\n"); sb.append(" description: ").append(toIndentedString(description)).append("\n"); sb.append("}"); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java index 70a07ff7f0fe..fa1d1d965fb9 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java @@ -128,7 +128,7 @@ public Response organizationsPost(OrganizationDTO organizationDTO, MessageContex String orgId = null; if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { orgId = orgInfo.getOrganizationSelector(); - organizationDTO.setParentId(orgId); // set current users organization as parent id if available. + organizationDTO.setParentOrganizationId(orgId); // set current users organization as parent id if available. } OrganizationDetailsDTO orgDto = OrganizationsMappingUtil.toOrganizationDetailsDTO(organizationDTO); orgDto.setTenantDomain(superOrganization); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java index cebf67b5725e..b21ab3cbb25c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/utils/mappings/OrganizationsMappingUtil.java @@ -34,7 +34,8 @@ public static OrganizationListDTO toOrganizationsListDTO(List orgList = apiProvider.getOrganizations(orgId, superOrganization); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java index acf81ac93158..e407d58fd922 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/OrganizationsMappingUtil.java @@ -34,7 +34,9 @@ public static OrganizationListDTO toOrganizationsListDTO(List Date: Thu, 23 Jan 2025 21:48:39 +0530 Subject: [PATCH 51/74] Add improvement to login flow --- .../carbon/apimgt/api/OAuthTokenInfo.java | 12 +++++ .../apimgt/api/model/OrganizationInfo.java | 10 ++-- .../carbon/apimgt/impl/APIConsumerImpl.java | 4 +- .../v1/impl/OrganizationsApiServiceImpl.java | 8 +-- .../v1/impl/OrganizationsApiServiceImpl.java | 4 +- .../api/store/v1/impl/ApisApiServiceImpl.java | 2 +- .../v1/impl/ApplicationsApiServiceImpl.java | 22 ++++---- .../rest/api/store/v1/utils/APIUtils.java | 2 +- .../impl/OAuthOpaqueAuthenticatorImpl.java | 54 +++++++++---------- 9 files changed, 64 insertions(+), 54 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/OAuthTokenInfo.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/OAuthTokenInfo.java index 5bafe0a9d328..95c39784edb5 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/OAuthTokenInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/OAuthTokenInfo.java @@ -17,6 +17,8 @@ package org.wso2.carbon.apimgt.api; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; + /** * Details about an oauth Access Token. */ @@ -33,6 +35,8 @@ public class OAuthTokenInfo { private long validityPeriod; private String endUserName; + + private OrganizationInfo userOrganizationInfo; public boolean isTokenValid() { return isTokenValid; @@ -92,5 +96,13 @@ public String getConsumerKey() { public void setConsumerKey(String consumerKey) { this.consumerKey = consumerKey; } + + public OrganizationInfo getUserOrganizationInfo() { + return userOrganizationInfo; + } + + public void setUserOrganizationInfo(OrganizationInfo userOrganizationInfo) { + this.userOrganizationInfo = userOrganizationInfo; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java index ba05a3a9705a..4ea772b91a53 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java @@ -23,7 +23,7 @@ public class OrganizationInfo { String superOrganization; String name; String id; - String organizationSelector; + String organizationId; OrganizationInfo parentOrganization; OrganizationInfo[] childOrganizations; @@ -57,10 +57,10 @@ public OrganizationInfo[] getChildOrganizations() { public void setChildOrganizations(OrganizationInfo[] childOrganizations) { this.childOrganizations = childOrganizations; } - public String getOrganizationSelector() { - return organizationSelector; + public String getOrganizationId() { + return organizationId; } - public void setOrganizationSelector(String organizationSelector) { - this.organizationSelector = organizationSelector; + public void setOrganizationId(String organizationId) { + this.organizationId = organizationId; } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 7bc44a012624..4f922d4011fa 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -3868,7 +3868,7 @@ public Map searchPaginatedAPIs(String searchQuery, OrganizationI String[] roles = APIUtil.getListOfRoles(userName); Map properties = APIUtil.getUserProperties(userName); UserContext userCtx = new UserContext(userNameWithoutChange, - new Organization(organizationInfo.getOrganizationSelector()), properties, roles); + new Organization(organizationInfo.getOrganizationId()), properties, roles); return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); } @@ -4242,7 +4242,7 @@ public Map searchPaginatedContent(String searchQuery, Organizati Map properties = APIUtil.getUserProperties(userName); String[] roles = APIUtil.getFilteredUserRoles(userName); - UserContext ctx = new UserContext(userName, new Organization(organizationInfo.getOrganizationSelector()), + UserContext ctx = new UserContext(userName, new Organization(organizationInfo.getOrganizationId()), properties, roles); return searchPaginatedContent(org, searchQuery, start, end, ctx); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java index fa1d1d965fb9..625b96458797 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java @@ -57,8 +57,8 @@ public Response organizationsGet(MessageContext messageContext) throws APIManage String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); String orgId = null; - if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { - orgId = orgInfo.getOrganizationSelector(); + if (orgInfo != null && orgInfo.getOrganizationId() != null) { + orgId = orgInfo.getOrganizationId(); } List orgList = apiAdmin.getOrganizations(orgId, superOrganization); @@ -126,8 +126,8 @@ public Response organizationsPost(OrganizationDTO organizationDTO, MessageContex OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); String orgId = null; - if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { - orgId = orgInfo.getOrganizationSelector(); + if (orgInfo != null && orgInfo.getOrganizationId() != null) { + orgId = orgInfo.getOrganizationId(); organizationDTO.setParentOrganizationId(orgId); // set current users organization as parent id if available. } OrganizationDetailsDTO orgDto = OrganizationsMappingUtil.toOrganizationDetailsDTO(organizationDTO); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java index 2b2cf424eb94..76b988fac8e6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/OrganizationsApiServiceImpl.java @@ -50,8 +50,8 @@ public Response organizationsGet(MessageContext messageContext) throws APIManage String superOrganization = RestApiUtil.getValidatedOrganization(messageContext); OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); String orgId = null; - if (orgInfo != null && orgInfo.getOrganizationSelector() != null) { - orgId = orgInfo.getOrganizationSelector(); + if (orgInfo != null && orgInfo.getOrganizationId() != null) { + orgId = orgInfo.getOrganizationId(); } else { String errorMessage = "User does not belong to any organization."; throw new APIManagementException(errorMessage, ExceptionCodes.MISSING_ORGANINATION); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 9a7d37b1b6ca..7fe07b6e8063 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1180,7 +1180,7 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo APIConsumer apiConsumer = RestApiCommonUtil.getLoggedInUserConsumer(); ApiTypeWrapper api = apiConsumer.getAPIorAPIProductByUUID(apiId, organization); String status = api.getStatus(); - String userOrg = userOrgInfo.getOrganizationSelector(); + String userOrg = userOrgInfo.getOrganizationId(); String userName = RestApiCommonUtil.getLoggedInUsername(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java index fe162a4c1c04..c5fa436fa2f4 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApplicationsApiServiceImpl.java @@ -144,7 +144,7 @@ public Response applicationsGet(String groupId, String query, String sortBy, Str APIConsumer apiConsumer = RestApiCommonUtil.getConsumer(username); Subscriber subscriber = new Subscriber(username); Application[] applications; - String sharedOrganization = orgInfo.getOrganizationSelector(); + String sharedOrganization = orgInfo.getOrganizationId(); applications = apiConsumer .getApplicationsWithPagination(new Subscriber(username), groupId, offset, limit, query, sortBy, sortOrder, organization, sharedOrganization); @@ -255,9 +255,9 @@ public Response applicationsGet(String groupId, String query, String sortBy, Str int appId = APIUtil.getApplicationId(applicationDTO.getName(), ownerId); Application oldApplication = apiConsumer.getApplicationById(appId); application = preProcessAndUpdateApplication(ownerId, applicationDTO, oldApplication, - oldApplication.getUUID(), orgInfo.getOrganizationSelector()); + oldApplication.getUUID(), orgInfo.getOrganizationId()); } else { - application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getOrganizationSelector()); + application = preProcessAndAddApplication(ownerId, applicationDTO, organization, orgInfo.getOrganizationId()); update = Boolean.FALSE; } @@ -331,7 +331,7 @@ public Response applicationsPost(ApplicationDTO body, MessageContext messageCont String organization = RestApiUtil.getValidatedOrganization(messageContext); OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); Application createdApplication = preProcessAndAddApplication(username, body, organization, - orgInfo.getOrganizationSelector()); + orgInfo.getOrganizationId()); ApplicationDTO createdApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(createdApplication); //to be set as the Location header @@ -435,8 +435,8 @@ public Response applicationsApplicationIdGet(String applicationId, String ifNone } application.setApplicationAttributes(applicationAttributes); if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) - || (orgInfo.getOrganizationSelector() != null - && orgInfo.getOrganizationSelector().equals(application.getSharedOrganization()))) { + || (orgInfo.getOrganizationId() != null + && orgInfo.getOrganizationId().equals(application.getSharedOrganization()))) { ApplicationDTO applicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(application); applicationDTO.setHashEnabled(OAuthServerConfiguration.getInstance().isClientSecretHashEnabled()); Set scopes = apiConsumer @@ -487,7 +487,7 @@ public Response applicationsApplicationIdPut(String applicationId, ApplicationDT } OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); Application updatedApplication = preProcessAndUpdateApplication(username, body, oldApplication, - applicationId, orgInfo.getOrganizationSelector()); + applicationId, orgInfo.getOrganizationId()); ApplicationDTO updatedApplicationDTO = ApplicationMappingUtil.fromApplicationtoDTO(updatedApplication); return Response.ok().entity(updatedApplicationDTO).build(); @@ -935,8 +935,8 @@ private Set getApplicationKeys(String applicationUUID, String tenantDoma Application application = apiConsumer.getLightweightApplicationByUUID(applicationUUID); if (application != null) { if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) - || (orgInfo != null && orgInfo.getOrganizationSelector() != null - && orgInfo.getOrganizationSelector().equals(application.getSharedOrganization()))) { + || (orgInfo != null && orgInfo.getOrganizationId() != null + && orgInfo.getOrganizationId().equals(application.getSharedOrganization()))) { return apiConsumer.getApplicationKeysOfApplication(application.getId(), tenantDomain); } else { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_APPLICATION, applicationUUID, log); @@ -1304,8 +1304,8 @@ public Response applicationsApplicationIdOauthKeysKeyMappingIdGenerateTokenPost( OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); if (application != null) { - if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) || (orgInfo.getOrganizationSelector() != null - && orgInfo.getOrganizationSelector().equals(application.getSharedOrganization()))) { + if (RestAPIStoreUtils.isUserAccessAllowedForApplication(application) || (orgInfo.getOrganizationId() != null + && orgInfo.getOrganizationId().equals(application.getSharedOrganization()))) { ApplicationKeyDTO appKey = getApplicationKeyByAppIDAndKeyMapping(applicationId, keyMappingId); if (appKey != null) { String jsonInput = null; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java index 7b8c9e00fe66..09b5f28fc1d5 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java @@ -206,7 +206,7 @@ public static List filterAllowedKeyManagersForOrgani List keymanagerConfigs, OrganizationInfo orgInfo) { List allowedList = new ArrayList(); - String organization = orgInfo.getOrganizationSelector(); + String organization = orgInfo.getOrganizationId(); for (KeyManagerConfigurationDTO keyManagerConfigurationDTO : keymanagerConfigs) { List allowedOrgs = keyManagerConfigurationDTO.getAllowedOrganizations(); // Add to allowedList if no organizations are restricted or if the organization is allowed diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index c3ecdb3d7b99..fdbf90889acf 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -105,6 +105,7 @@ public boolean authenticate(Message message) throws APIManagementException { try { if (tokenInfo == null) { tokenInfo = getTokenMetaData(accessToken); + tokenInfo.setUserOrganizationInfo(getOrganizationInfo(tokenInfo.getEndUserName())); } } catch (APIManagementException e) { log.error("Error while retrieving token information for token: " + accessToken, e); @@ -157,7 +158,7 @@ public boolean authenticate(Message message) throws APIManagementException { message.put(RestApiConstants.SUB_ORGANIZATION, tenantDomain); if (ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService() .getAPIManagerConfiguration().getOrgAccessControl().isEnabled()) { - message.put(RestApiConstants.ORGANIZATION_INFO, getOrganizationInfo(tenantDomain, username)); + message.put(RestApiConstants.ORGANIZATION_INFO, tokenInfo.getUserOrganizationInfo()); } if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { APIUtil.loadTenantConfigBlockingMode(tenantDomain); @@ -248,7 +249,11 @@ protected String getConfigurationElementValue(String property) { .getFirstProperty(property); } - public OrganizationInfo getOrganizationInfo(String tenantDomain, String username) { + public OrganizationInfo getOrganizationInfo(String username) { + if (log.isDebugEnabled()) { + log.debug("Retrieving organization information for user: " + username); + } + String tenantDomain = MultitenantUtils.getTenantDomain(username); OrganizationInfo orgInfo = new OrganizationInfo(); orgInfo.setSuperOrganization(tenantDomain); @@ -258,7 +263,7 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username getAPIManagerConfigurationService().getAPIManagerConfiguration(); String orgNameClaim = config.getOrgAccessControl().getOrgNameLocalClaim(); String orgIdClaim = config.getOrgAccessControl().getOrgIdLocalClaim(); - String orgSelectorClaim = config.getOrgAccessControl().getOrgSelectorClaim(); + if (StringUtils.isBlank(orgNameClaim)) { orgNameClaim = "http://wso2.org/claims/organization"; } @@ -266,10 +271,9 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username orgIdClaim = "http://wso2.org/claims/organizationId"; } + String organization = null; String organizationId = null; - String orgSelector = null; - String[] groupIdArray = null; try { if (tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { isSuperTenant = true; @@ -279,39 +283,33 @@ public OrganizationInfo getOrganizationInfo(String tenantDomain, String username //if the user is not in the super tenant domain then find the domain name and tenant id. if (!isSuperTenant) { - tenantDomain = MultitenantUtils.getTenantDomain(username); tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager() .getTenantId(tenantDomain); } + if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { + //when the username is an email in supertenant, it has at least 2 occurrences of '@' + long count = username.chars().filter(ch -> ch == '@').count(); + //in the case of email, there will be more than one '@' + boolean isEmailUsernameEnabled = Boolean.parseBoolean(CarbonUtils.getServerConfiguration(). + getFirstProperty("EnableEmailUserName")); + if (isEmailUsernameEnabled || (username.endsWith(SUPER_TENANT_SUFFIX) && count <= 1)) { + username = MultitenantUtils.getTenantAwareUsername(username); + } + } + UserRealm realm = (UserRealm) realmService.getTenantUserRealm(tenantId); UserStoreManager manager = realm.getUserStoreManager(); organization = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgNameClaim, null); organizationId = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); - if (StringUtils.isBlank(orgSelectorClaim)) { - orgSelector = organization; // default selector will be organization name - } else { - orgSelector = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), - orgSelectorClaim, null); - } - if (organization != null) { - if (organization.contains(",")) { - groupIdArray = organization.split(","); - for (int i = 0; i < groupIdArray.length; i++) { - groupIdArray[i] = groupIdArray[i].toString().trim(); - } - } else { - organization = organization.trim(); - groupIdArray = new String[] {organization}; - orgInfo.setName(organization); // check for multiple orgs - orgInfo.setId(organizationId); - orgInfo.setOrganizationSelector(orgSelector); - } - } else { - // If claim is null then returning a empty string - groupIdArray = new String[] {}; + + orgInfo.setName(organization); + orgInfo.setOrganizationId(organizationId); + + if (log.isDebugEnabled()) { + log.debug("organization = " + organization + " ,organizationId = " + organizationId); } } catch (JSONException e) { log.error("Exception occured while trying to get group Identifier from login response", e); From 479ebe82b490f56de1ad05dbc53b786b0c3babd5 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 23 Jan 2025 22:03:18 +0530 Subject: [PATCH 52/74] Fix app sharing issue --- .../impl/dao/constants/SQLConstantsH2MySQL.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java index 59ff88cc00b2..7534ab2c5f52 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstantsH2MySQL.java @@ -42,7 +42,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " GROUP_ID, " + " UUID, " + " APP.CREATED_BY AS CREATED_BY, " + - " APP.TOKEN_TYPE AS TOKEN_TYPE " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + " FROM" + " AM_APPLICATION APP, " + " AM_SUBSCRIBER SUB " + @@ -74,7 +75,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " GROUP_ID, " + " UUID, " + " APP.CREATED_BY AS CREATED_BY, " + - " APP.TOKEN_TYPE AS TOKEN_TYPE " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + " FROM" + " AM_APPLICATION APP, " + " AM_SUBSCRIBER SUB " + @@ -105,7 +107,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " GROUP_ID, " + " UUID, " + " APP.CREATED_BY AS CREATED_BY, " + - " APP.TOKEN_TYPE AS TOKEN_TYPE " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + " FROM" + " AM_APPLICATION APP, " + " AM_SUBSCRIBER SUB " + @@ -143,7 +146,8 @@ public class SQLConstantsH2MySQL extends SQLConstants{ " GROUP_ID, " + " UUID, " + " APP.CREATED_BY AS CREATED_BY, " + - " APP.TOKEN_TYPE AS TOKEN_TYPE " + + " APP.TOKEN_TYPE AS TOKEN_TYPE, " + + " APP.SHARED_ORGANIZATION AS SHARED_ORGANIZATION " + " FROM" + " AM_APPLICATION APP, " + " AM_SUBSCRIBER SUB " + From f4acefe7f6353fc941d1d5faabac11a33a0a9c7c Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Sat, 25 Jan 2025 08:19:05 +0530 Subject: [PATCH 53/74] Add claim check --- .../rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index fdbf90889acf..4d211c667534 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -39,6 +39,8 @@ import org.wso2.carbon.identity.oauth2.dto.OAuth2ClientApplicationDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationRequestDTO; import org.wso2.carbon.identity.oauth2.dto.OAuth2TokenValidationResponseDTO; +import org.wso2.carbon.user.api.Claim; +import org.wso2.carbon.user.api.ClaimMapping; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.UserRealm; import org.wso2.carbon.user.core.UserStoreManager; @@ -302,9 +304,10 @@ public OrganizationInfo getOrganizationInfo(String username) { UserStoreManager manager = realm.getUserStoreManager(); organization = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgNameClaim, null); - organizationId = - manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); - + if (realm.getClaimManager().getClaim(orgIdClaim) != null) { + organizationId = + manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); + } orgInfo.setName(organization); orgInfo.setOrganizationId(organizationId); From 87037775ab50b75d4349df39d3ac8d44264e25d3 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 28 Jan 2025 12:56:16 +0530 Subject: [PATCH 54/74] Add current org to the visibility restriction --- .../.checkstyle | 17 +++++++++++++ .../v1/common/mappings/ImportUtils.java | 2 +- .../common/mappings/PublisherCommonUtils.java | 25 ++++++++++++++++--- .../publisher/v1/impl/ApisApiServiceImpl.java | 18 +++++++++++-- 4 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/.checkstyle diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/.checkstyle b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/.checkstyle new file mode 100644 index 000000000000..bc4575b83b28 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/.checkstyle @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java index 85baaa5aa087..88fe5ddb82d5 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java @@ -365,7 +365,7 @@ public static ImportedAPIDTO importApi(String extractedFolderPath, APIDTO import if (!PublisherCommonUtils.isThirdPartyAsyncAPI(importedApiDTO)) { importedApi = PublisherCommonUtils .addAPIWithGeneratedSwaggerDefinition(importedApiDTO, ImportExportConstants.OAS_VERSION_3, - importedApiDTO.getProvider(), organization); + importedApiDTO.getProvider(), organization, null); // Add/update swagger content except for streaming APIs and GraphQL APIs if (!PublisherCommonUtils.isStreamingAPI(importedApiDTO) && !APIConstants.APITransportType.GRAPHQL.toString().equalsIgnoreCase(apiType)) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index ab15f9147aef..84453bd2a236 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -65,6 +65,7 @@ import org.wso2.carbon.apimgt.api.model.Identifier; import org.wso2.carbon.apimgt.api.model.LifeCycleEvent; import org.wso2.carbon.apimgt.api.model.OperationPolicy; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.SOAPToRestSequence; import org.wso2.carbon.apimgt.api.model.ServiceEntry; @@ -190,10 +191,19 @@ public static API updateApiAndDefinition(API originalAPI, APIDTO apiDtoToUpdate, * @throws APIManagementException If an error occurs while updating the API * @throws FaultGatewaysException If an error occurs while updating manage of an existing API */ - public static API updateApi(API originalAPI, APIDTO apiDtoToUpdate, APIProvider apiProvider, String[] tokenScopes) + public static API updateApi(API originalAPI, APIDTO apiDtoToUpdate, APIProvider apiProvider, String[] tokenScopes, + OrganizationInfo orginfo) throws ParseException, CryptoException, APIManagementException, FaultGatewaysException { - API apiToUpdate = prepareForUpdateApi(originalAPI, apiDtoToUpdate, apiProvider, tokenScopes); + if (orginfo != null && orginfo.getOrganizationId() != null) { + String visibleOrgs = apiToUpdate.getVisibleOrganizations(); + if (!StringUtils.isEmpty(visibleOrgs) + && !APIConstants.DEFAULT_VISIBLE_ORG.equals(apiToUpdate.getVisibleOrganizations())) { + // set the current user organizatin as visible organization. + visibleOrgs = visibleOrgs + "," + orginfo.getOrganizationId(); + apiToUpdate.setVisibleOrganizations(visibleOrgs); + } + } apiProvider.updateAPI(apiToUpdate, originalAPI); API apiUpdated = apiProvider.getAPIbyUUID(originalAPI.getUuid(), originalAPI.getOrganization()); if (apiUpdated != null && !StringUtils.isEmpty(apiUpdated.getEndpointConfig())) { @@ -1092,7 +1102,7 @@ public static void validateScopes(API api) throws APIManagementException { * @throws CryptoException Error while encrypting */ public static API addAPIWithGeneratedSwaggerDefinition(APIDTO apiDto, String oasVersion, String username, - String organization) + String organization, OrganizationInfo orgInfo) throws APIManagementException, CryptoException { String name = apiDto.getName(); apiDto.setName(name.trim().replaceAll("\\s{2,}", " ")); @@ -1205,6 +1215,15 @@ public static API addAPIWithGeneratedSwaggerDefinition(APIDTO apiDto, String oas String apiDefinition = asyncApiParser.generateAsyncAPIDefinition(apiToAdd); apiToAdd.setAsyncApiDefinition(apiDefinition); } + if (orgInfo != null && orgInfo.getOrganizationId() != null) { + String visibleOrgs = apiToAdd.getVisibleOrganizations(); + if (!StringUtils.isEmpty(visibleOrgs) + && !APIConstants.DEFAULT_VISIBLE_ORG.equals(apiToAdd.getVisibleOrganizations())) { + // set the current user organizatin as visible organization. + visibleOrgs = visibleOrgs + "," + orgInfo.getOrganizationId(); + apiToAdd.setVisibleOrganizations(visibleOrgs); + } + } //adding the api apiProvider.addAPI(apiToAdd); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java index 78f11846038f..7a262e761e26 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java @@ -86,6 +86,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; import java.io.*; +import java.lang.reflect.Array; import java.net.*; import java.nio.file.Files; import java.util.*; @@ -214,9 +215,10 @@ public Response createAPI(APIDTO body, String oasVersion, MessageContext message APIDTO createdApiDTO; try { String organization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo orgInfo = RestApiUtil.getOrganizationInfo(messageContext); API createdApi = PublisherCommonUtils .addAPIWithGeneratedSwaggerDefinition(body, oasVersion, RestApiCommonUtil.getLoggedInUsername(), - organization); + organization, orgInfo ); createdApiDTO = APIMappingUtil.fromAPItoDTO(createdApi); //This URI used to set the location header of the POST response createdApiUri = new URI(RestApiConstants.RESOURCE_PATH_APIS + "/" + createdApiDTO.getId()); @@ -238,7 +240,17 @@ public Response getAPI(String apiId, String xWSO2Tenant, String ifNoneMatch, MessageContext messageContext) throws APIManagementException { APIProvider apiProvider = RestApiCommonUtil.getLoggedInUserProvider(); String organization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo organizationInfo = RestApiUtil.getOrganizationInfo(messageContext); APIDTO apiToReturn = getAPIByID(apiId, apiProvider, organization); + if (apiToReturn.getVisibleOrganizations() != null && organizationInfo != null + && organizationInfo.getOrganizationId() != null) { + // Remove current organization id from the visible org list. + List orglist = apiToReturn.getVisibleOrganizations(); + ArrayList newOrgList = new ArrayList(orglist); + newOrgList.remove(organizationInfo.getOrganizationId()); + apiToReturn.setVisibleOrganizations(newOrgList); + } + return Response.ok().entity(apiToReturn).build(); } @@ -708,6 +720,7 @@ public Response updateAPI(String apiId, APIDTO body, String ifMatch, MessageCont try { String organization = RestApiUtil.getValidatedOrganization(messageContext); + OrganizationInfo organizationInfo = RestApiUtil.getOrganizationInfo(messageContext); //validate if api exists CommonUtils.validateAPIExistence(apiId); if (!PublisherCommonUtils.validateEndpointConfigs(body)) { @@ -739,9 +752,10 @@ public Response updateAPI(String apiId, APIDTO body, String ifMatch, MessageCont APIProvider apiProvider = RestApiCommonUtil.getProvider(username); API originalAPI = apiProvider.getAPIbyUUID(apiId, organization); originalAPI.setOrganization(organization); + //validate API update operation permitted based on the LC state validateAPIOperationsPerLC(originalAPI.getStatus()); - API updatedApi = PublisherCommonUtils.updateApi(originalAPI, body, apiProvider, tokenScopes); + API updatedApi = PublisherCommonUtils.updateApi(originalAPI, body, apiProvider, tokenScopes, organizationInfo); return Response.ok().entity(APIMappingUtil.fromAPItoDTO(updatedApi)).build(); } catch (APIManagementException e) { //Auth failure occurs when cross tenant accessing APIs. Sends 404, since we don't need From fd7c0cd2a4dc77b5c9925c300189c0840979bf1e Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 28 Jan 2025 17:46:30 +0530 Subject: [PATCH 55/74] Remove org visiblity when importing API --- .../rest/api/publisher/v1/common/mappings/ImportUtils.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java index 88fe5ddb82d5..1659ddd97e8a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/ImportUtils.java @@ -118,6 +118,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -318,6 +319,7 @@ public static ImportedAPIDTO importApi(String extractedFolderPath, APIDTO import importedApiDTO.setVisibility(convertedOldAPI.getVisibility()); importedApiDTO.setVisibleRoles(convertedOldAPI.getVisibleRoles()); importedApiDTO.setVisibleTenants(convertedOldAPI.getVisibleTenants()); + importedApiDTO.setVisibleOrganizations(Collections.EMPTY_LIST); // ignore org visibility importedApiDTO.setSubscriptionAvailability(convertedOldAPI.getSubscriptionAvailability()); importedApiDTO.setSubscriptionAvailableTenants(convertedOldAPI.getSubscriptionAvailableTenants()); importedApiDTO.monetization(convertedOldAPI.getMonetization()); @@ -344,6 +346,7 @@ public static ImportedAPIDTO importApi(String extractedFolderPath, APIDTO import log.info("Cannot find : " + importedApiDTO.getName() + "-" + importedApiDTO.getVersion() + ". Creating it."); } + importedApiDTO.setVisibleOrganizations(Collections.EMPTY_LIST); // ignore org visibility when importing // Initialize to CREATED when import currentStatus = APIStatus.CREATED.toString(); importedApiDTO.setLifeCycleStatus(currentStatus); From a61230e387160c133ecf637e721ae9dd5f408005 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Tue, 28 Jan 2025 17:57:17 +0530 Subject: [PATCH 56/74] Fix bug --- .../carbon/apimgt/impl/utils/APIUtil.java | 24 +++++++++++++++++++ .../impl/OAuthOpaqueAuthenticatorImpl.java | 19 ++++++++------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index e2b0e85950a4..d1e5ff52187d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -91,6 +91,7 @@ import org.wso2.carbon.apimgt.api.doc.model.Parameter; import org.wso2.carbon.apimgt.api.dto.GatewayVisibilityPermissionConfigurationDTO; import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; +import org.wso2.carbon.apimgt.api.dto.OrganizationDetailsDTO; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.APICategory; import org.wso2.carbon.apimgt.api.model.APIIdentifier; @@ -11120,4 +11121,27 @@ public static Boolean isOrgWideAppUpdateEnabled() { return Boolean.getBoolean( APIConstants.ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED); } + + public static String getOrganizationIdFromExternalReference(String referenceId, String organizationName, + String rootOrganization) throws APIManagementException { + String organizationId = null; + OrganizationDetailsDTO orgDetails = ApiMgtDAO.getInstance().getOrganizationDetalsByExternalOrgId(referenceId, + rootOrganization); + if (orgDetails != null) { + organizationId = orgDetails.getOrganizationId(); + } else { + // No organization entry in the db. add entry without parent info. + + OrganizationDetailsDTO info = new OrganizationDetailsDTO(); + info.setExternalOrganizationReference(referenceId); + info.setTenantDomain(rootOrganization); + info.setName(organizationName); + OrganizationDetailsDTO addedInfo = ApiMgtDAO.getInstance().addOrganization(info); + if (addedInfo != null) { + organizationId = addedInfo.getOrganizationId(); + } + + } + return organizationId; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index 4d211c667534..3a846db2974c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -107,7 +107,9 @@ public boolean authenticate(Message message) throws APIManagementException { try { if (tokenInfo == null) { tokenInfo = getTokenMetaData(accessToken); - tokenInfo.setUserOrganizationInfo(getOrganizationInfo(tokenInfo.getEndUserName())); + if (tokenInfo.getEndUserName() != null) { + tokenInfo.setUserOrganizationInfo(getOrganizationInfo(tokenInfo.getEndUserName())); + } } } catch (APIManagementException e) { log.error("Error while retrieving token information for token: " + accessToken, e); @@ -251,7 +253,7 @@ protected String getConfigurationElementValue(String property) { .getFirstProperty(property); } - public OrganizationInfo getOrganizationInfo(String username) { + public OrganizationInfo getOrganizationInfo(String username) throws APIManagementException { if (log.isDebugEnabled()) { log.debug("Retrieving organization information for user: " + username); } @@ -272,8 +274,7 @@ public OrganizationInfo getOrganizationInfo(String username) { if (StringUtils.isBlank(orgIdClaim)) { orgIdClaim = "http://wso2.org/claims/organizationId"; } - - + String organization = null; String organizationId = null; try { @@ -307,6 +308,8 @@ public OrganizationInfo getOrganizationInfo(String username) { if (realm.getClaimManager().getClaim(orgIdClaim) != null) { organizationId = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); + // Get the internal organization id using externa id + //organizationId = APIUtil.getOrganizationIdFromExternalReference(organizationId, organization, tenantDomain); // TODO enable this after org add UI } orgInfo.setName(organization); orgInfo.setOrganizationId(organizationId); @@ -314,11 +317,11 @@ public OrganizationInfo getOrganizationInfo(String username) { if (log.isDebugEnabled()) { log.debug("organization = " + organization + " ,organizationId = " + organizationId); } - } catch (JSONException e) { - log.error("Exception occured while trying to get group Identifier from login response", e); } catch (org.wso2.carbon.user.api.UserStoreException e) { - log.error("Error while checking user existence for " + username, e); - } + String error = "Error while checking user existence for " + username; + log.error(error, e); + throw new APIManagementException(error, e); + } return orgInfo; } From bc299828ac61d2d5be7a724057f703df7460a0af Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 11:01:36 +0530 Subject: [PATCH 57/74] Add migration code for API --- .../wso2/carbon/apimgt/impl/APIConstants.java | 1 + .../impl/indexing/indexer/CustomAPIIndexer.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index 7631939f95a0..3c5749134fd8 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -2359,6 +2359,7 @@ public enum APITransportType { * CustomIndexer property to indicate whether it is gone through API Custom Indexer. */ public static final String CUSTOM_API_INDEXER_PROPERTY = "registry.customIndexer"; + public static final String VISIBLE_ORGANIZATION_PROPERTY = "visible_organizations"; /** * Parameter related with accessControl support. diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java index e8913546579b..62de38990682 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java @@ -24,6 +24,7 @@ import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.impl.utils.IndexerUtil; import org.wso2.carbon.governance.api.exception.GovernanceException; import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; import org.wso2.carbon.governance.api.util.GovernanceUtils; @@ -32,7 +33,9 @@ import org.wso2.carbon.registry.core.RegistryConstants; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.core.utils.RegistryUtils; import org.wso2.carbon.registry.indexing.AsyncIndexer; +import org.wso2.carbon.registry.indexing.IndexingConstants; import org.wso2.carbon.registry.indexing.IndexingManager; import org.wso2.carbon.registry.indexing.solr.IndexDocument; @@ -44,6 +47,8 @@ import static org.wso2.carbon.apimgt.impl.APIConstants.CUSTOM_API_INDEXER_PROPERTY; import static org.wso2.carbon.apimgt.impl.APIConstants.OVERVIEW_PREFIX; +import static org.wso2.carbon.apimgt.impl.APIConstants.VISIBLE_ORGANIZATION_PROPERTY; + /** * This is the custom indexer to add the API properties, to existing APIs. @@ -68,18 +73,22 @@ public IndexDocument getIndexedDocument(AsyncIndexer.File2Index fileData) throws if (log.isDebugEnabled()) { log.debug("CustomAPIIndexer is currently indexing the api at path " + resourcePath); } - + // Here we are adding properties as fields, so that we can search the properties as we do for attributes. IndexDocument indexDocument = super.getIndexedDocument(fileData); Map> fields = indexDocument.getFields(); if (resource != null) { Properties properties = resource.getProperties(); Enumeration propertyNames = properties.propertyNames(); + boolean hasOrganizationProperty = false; while (propertyNames.hasMoreElements()) { String property = (String) propertyNames.nextElement(); if (log.isDebugEnabled()) { log.debug("API at " + resourcePath + " has " + property + " property"); } + if (VISIBLE_ORGANIZATION_PROPERTY.equals(property)) { + hasOrganizationProperty = true; + } if (property.startsWith(APIConstants.API_RELATED_CUSTOM_PROPERTIES_PREFIX)) { fields.put((OVERVIEW_PREFIX + property), getLowerCaseList(resource.getPropertyValues(property))); if (log.isDebugEnabled()) { @@ -87,6 +96,11 @@ public IndexDocument getIndexedDocument(AsyncIndexer.File2Index fileData) throws } } } + if (!hasOrganizationProperty) { + List orgProperties = new ArrayList<>(); + orgProperties.add(VISIBLE_ORGANIZATION_PROPERTY + ",all" ); + fields.put(IndexingConstants.FIELD_PROPERTY_VALUES, orgProperties); + } indexDocument.setFields(fields); } return indexDocument; From ec339c38569df171bdeae4c3e9b6b1c9bc953300 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 11:31:58 +0530 Subject: [PATCH 58/74] Add code changes --- .../rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java index 3a846db2974c..20b98128af2c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.util/src/main/java/org/wso2/carbon/apimgt/rest/api/util/impl/OAuthOpaqueAuthenticatorImpl.java @@ -309,7 +309,11 @@ public OrganizationInfo getOrganizationInfo(String username) throws APIManagemen organizationId = manager.getUserClaimValue(MultitenantUtils.getTenantAwareUsername(username), orgIdClaim, null); // Get the internal organization id using externa id - //organizationId = APIUtil.getOrganizationIdFromExternalReference(organizationId, organization, tenantDomain); // TODO enable this after org add UI + /* + if (!StringUtils.isEmpty(organizationId)) { + organizationId = APIUtil.getOrganizationIdFromExternalReference(organizationId, organization, + tenantDomain); // TODO enable this after org add UI + }*/ } orgInfo.setName(organization); orgInfo.setOrganizationId(organizationId); From a75026ea22e2ae37ef51bd37364b5b0404b7eb37 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 13:53:27 +0530 Subject: [PATCH 59/74] Add org_handle column --- .../api/dto/OrganizationDetailsDTO.java | 29 +++++++++++++++++-- .../wso2/carbon/apimgt/impl/APIAdminImpl.java | 2 ++ .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 6 ++-- .../impl/dao/constants/SQLConstants.java | 8 +++-- .../carbon/apimgt/impl/utils/APIUtil.java | 23 +++++++++++++++ .../src/main/resources/sql/h2.sql | 1 + 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java index ea4856dee27b..ddcb5491a4a5 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/dto/OrganizationDetailsDTO.java @@ -16,58 +16,81 @@ * under the License. */ - package org.wso2.carbon.apimgt.api.dto; public class OrganizationDetailsDTO { - + private String organizationId; private String parentOrganizationId; private String externalOrganizationReference; private String Name; private String tenantDomain; private String description; + private String organizationHandle; + public String getOrganizationId() { return organizationId; } + public void setOrganizationId(String organizationId) { this.organizationId = organizationId; } + public String getParentOrganizationId() { return parentOrganizationId; } + public void setParentOrganizationId(String parentOrganizationId) { this.parentOrganizationId = parentOrganizationId; } + public String getName() { return Name; } + public void setName(String name) { Name = name; } + public String getTenantDomain() { return tenantDomain; } + public void setTenantDomain(String tenantDomain) { this.tenantDomain = tenantDomain; } + public String getDescription() { return description; } + public void setDescription(String description) { this.description = description; } + public String getExternalOrganizationReference() { return externalOrganizationReference; } + public void setExternalOrganizationReference(String externalOrganizationReference) { this.externalOrganizationReference = externalOrganizationReference; } + + public String getOrganizationHandle() { + return organizationHandle; + } + + public void setOrganizationHandle(String organizationHandle) { + this.organizationHandle = organizationHandle; + } + @Override public String toString() { return "OrganizationDetailsDTO [organizationId=" + organizationId + ", parentOrganizationId=" + parentOrganizationId + ", externalOrganizationReference=" + externalOrganizationReference + ", Name=" - + Name + ", tenantDomain=" + tenantDomain + ", description=" + description + "]"; + + Name + ", tenantDomain=" + tenantDomain + ", description=" + description + ", organizationHandle=" + + organizationHandle + "]"; } + } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java index 0ff03924d7c5..bc61f50e0559 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java @@ -1854,9 +1854,11 @@ public OrganizationDetailsDTO addOrganization(OrganizationDetailsDTO orgDto) thr OrganizationDetailsDTO savedOrgInfo = apiMgtDAO.getOrganizationDetalsByExternalOrgId( orgDto.getExternalOrganizationReference(), orgDto.getTenantDomain()); if (savedOrgInfo != null) { + orgDto.setOrganizationHandle(APIUtil.getOrganizationHandle(orgDto.getName())); orgDto.setOrganizationId(savedOrgInfo.getOrganizationId()); apiMgtDAO.updateOrganizationDetails(orgDto); } else { + orgDto.setOrganizationHandle(APIUtil.getOrganizationHandle(orgDto.getName())); savedOrgInfo = apiMgtDAO.addOrganization(orgDto); orgDto.setOrganizationId(savedOrgInfo.getOrganizationId()); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index e3b3c7458c85..a3d281ec7048 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -10342,6 +10342,7 @@ public OrganizationDetailsDTO addOrganization(OrganizationDetailsDTO organizatio preparedStatement.setString(4, organizationDTO.getParentOrganizationId()); preparedStatement.setString(5, organizationDTO.getDescription()); preparedStatement.setString(6, organizationDTO.getTenantDomain()); + preparedStatement.setString(7, organizationDTO.getOrganizationHandle()); preparedStatement.executeUpdate(); conn.commit(); } @@ -10430,12 +10431,13 @@ public void updateOrganizationDetails(OrganizationDetailsDTO organizationDetails preparedStatement.setString(1, organizationDetailsDTO.getName()); preparedStatement.setString(2, organizationDetailsDTO.getDescription()); preparedStatement.setString(3, organizationDetailsDTO.getExternalOrganizationReference()); - preparedStatement.setString(4, organizationDetailsDTO.getOrganizationId()); + preparedStatement.setString(4, organizationDetailsDTO.getOrganizationHandle()); + preparedStatement.setString(5, organizationDetailsDTO.getOrganizationId()); preparedStatement.executeUpdate(); conn.commit(); } } catch (SQLException e) { - handleException("Failed to delete organization Id : " + "Error while Updating organization details for " + handleException("Failed to update organization Id : " + "Error while Updating organization details for " + organizationDetailsDTO.getOrganizationId(), e); } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java index a93218916cad..15cab48421d2 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java @@ -3841,11 +3841,13 @@ public static class KeyManagerSqlConstants { public static class OrganizationSqlConstants { public static final String ADD_ORGANIZATION = - " INSERT INTO AM_ORGANIZATION_MAPPING (ORG_UUID,EXT_ORG_ID,DISPLAY_NAME,PARENT_ORG_UUID,DESCRIPTION,ROOT_ORGANIZATION) " + - "VALUES (?,?,?,?,?,?)"; + " INSERT INTO AM_ORGANIZATION_MAPPING" + + " (ORG_UUID,EXT_ORG_ID,DISPLAY_NAME,PARENT_ORG_UUID,DESCRIPTION,ROOT_ORGANIZATION,ORG_HANDLE) " + + "VALUES (?,?,?,?,?,?,?)"; public static final String UPDATE_ORGANIZATION = - "UPDATE AM_ORGANIZATION_MAPPING SET DISPLAY_NAME = ?, DESCRIPTION = ?, EXT_ORG_ID=? WHERE ORG_UUID = ?"; + "UPDATE AM_ORGANIZATION_MAPPING " + + " SET DISPLAY_NAME = ?, DESCRIPTION = ?, EXT_ORG_ID=?, ORG_HANDLE=? WHERE ORG_UUID = ?"; public static final String DELETE_ORGANIZATION = "DELETE FROM AM_ORGANIZATION_MAPPING WHERE ORG_UUID = ? AND ROOT_ORGANIZATION=?"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index d1e5ff52187d..66f5b9c90802 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -275,6 +275,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -292,6 +293,8 @@ import javax.cache.CacheManager; import javax.cache.Caching; import java.security.cert.X509Certificate; +import java.text.Normalizer; + import javax.validation.constraints.NotNull; import javax.xml.XMLConstants; import javax.xml.namespace.QName; @@ -353,6 +356,9 @@ public final class APIUtil { private static Schema operationPolicySpecSchema; private static final String contextRegex = "^[a-zA-Z0-9_${}/.;()-]+$"; private static String hashingAlgorithm = SHA_256; + + private static final Pattern NONLATIN = Pattern.compile("[^\\w-]"); + private static final Pattern WHITESPACE = Pattern.compile("[\\s]"); private APIUtil() { @@ -11136,6 +11142,7 @@ public static String getOrganizationIdFromExternalReference(String referenceId, info.setExternalOrganizationReference(referenceId); info.setTenantDomain(rootOrganization); info.setName(organizationName); + info.setOrganizationHandle(getOrganizationHandle(organizationName)); OrganizationDetailsDTO addedInfo = ApiMgtDAO.getInstance().addOrganization(info); if (addedInfo != null) { organizationId = addedInfo.getOrganizationId(); @@ -11144,4 +11151,20 @@ public static String getOrganizationIdFromExternalReference(String referenceId, } return organizationId; } + + public static String getOrganizationHandle(String name) { + String sanatizedName = null; + if (name == null) { + return sanatizedName; + } + + String nowhitespace = WHITESPACE.matcher(name).replaceAll("-"); // Replace spaces with hyphens + String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); // Decompose Unicode characters + String slug = NONLATIN.matcher(normalized).replaceAll(""); // Remove non-alphanumeric characters + + // Convert to lowercase and trim hyphens from the beginning/end + slug = slug.toLowerCase(Locale.ENGLISH).replaceAll("^-+|-+$", ""); + + return slug; + } } diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql index bcdd9d907462..f275f5855780 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/h2.sql @@ -2003,6 +2003,7 @@ CREATE TABLE IF NOT EXISTS AM_ORGANIZATION_MAPPING ( EXT_ORG_ID VARCHAR(100) NOT NULL, DISPLAY_NAME VARCHAR(100) NULL, PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), DESCRIPTION VARCHAR(256) NULL, ROOT_ORGANIZATION VARCHAR(255), PRIMARY KEY (ORG_UUID) From 99b7b0d043c87d22d3bf50a82aa247bdf4784e3f Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 13:57:12 +0530 Subject: [PATCH 60/74] Refactor --- .../java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 66f5b9c90802..6f2fa276dacb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -11160,11 +11160,11 @@ public static String getOrganizationHandle(String name) { String nowhitespace = WHITESPACE.matcher(name).replaceAll("-"); // Replace spaces with hyphens String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); // Decompose Unicode characters - String slug = NONLATIN.matcher(normalized).replaceAll(""); // Remove non-alphanumeric characters + sanatizedName = NONLATIN.matcher(normalized).replaceAll(""); // Remove non-alphanumeric characters // Convert to lowercase and trim hyphens from the beginning/end - slug = slug.toLowerCase(Locale.ENGLISH).replaceAll("^-+|-+$", ""); + sanatizedName = sanatizedName.toLowerCase(Locale.ENGLISH).replaceAll("^-+|-+$", ""); - return slug; + return sanatizedName; } } From 785cb060d8619ffff641c811df2be70e521b41b9 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 14:17:37 +0530 Subject: [PATCH 61/74] Fix update path --- .../src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java index bc61f50e0559..0f91c1284a93 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIAdminImpl.java @@ -1875,6 +1875,7 @@ public OrganizationDetailsDTO getOrganizationDetails(String organizationId, Stri @Override public OrganizationDetailsDTO updateOrganization(OrganizationDetailsDTO organizationInfoDTO) throws APIManagementException { + organizationInfoDTO.setOrganizationHandle(APIUtil.getOrganizationHandle(organizationInfoDTO.getName())); apiMgtDAO.updateOrganizationDetails(organizationInfoDTO); return apiMgtDAO.getOrganizationDetails(organizationInfoDTO.getOrganizationId(), organizationInfoDTO.getTenantDomain()); From bf0b1f7f7dbf1b454c8c1495c050bc7a1fe4acdd Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 14:58:03 +0530 Subject: [PATCH 62/74] Add db scripts --- .../src/main/resources/sql/db2.sql | 21 +++++++++++++++++ .../src/main/resources/sql/mssql.sql | 23 +++++++++++++++++++ .../src/main/resources/sql/mysql.sql | 19 +++++++++++++++ .../src/main/resources/sql/mysql_cluster.sql | 19 +++++++++++++++ .../src/main/resources/sql/oracle.sql | 20 ++++++++++++++++ .../src/main/resources/sql/oracle_23c.sql | 20 ++++++++++++++++ .../src/main/resources/sql/oracle_rac.sql | 21 +++++++++++++++++ .../src/main/resources/sql/postgresql.sql | 21 +++++++++++++++++ 8 files changed, 164 insertions(+) diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql index 0fe395dbb83a..936573f3b726 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/db2.sql @@ -2297,6 +2297,7 @@ CREATE TABLE AM_APPLICATION ( UUID VARCHAR(256), TOKEN_TYPE VARCHAR(100), ORGANIZATION VARCHAR(100) NOT NULL, + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE RESTRICT, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION) @@ -2887,6 +2888,26 @@ CREATE TABLE AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ) / + +CREATE TABLE AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +); + / + +CREATE TABLE AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +); + / CREATE TABLE AM_API_CATEGORIES ( UUID VARCHAR(50) NOT NULL, diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql index 087ba7b9154b..c8fc2294f5dc 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mssql.sql @@ -1693,6 +1693,7 @@ CREATE TABLE AM_APPLICATION ( UUID VARCHAR(256), TOKEN_TYPE VARCHAR(10), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), @@ -2352,6 +2353,19 @@ CREATE TABLE AM_USER ( PRIMARY KEY(USER_ID) ); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_ORGANIZATION_MAPPING]') AND TYPE IN (N'U')) +CREATE TABLE AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +); + IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_KEY_MANAGER]') AND TYPE IN (N'U')) CREATE TABLE AM_KEY_MANAGER ( UUID VARCHAR(50) NOT NULL, @@ -2377,6 +2391,15 @@ CREATE TABLE AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[AM_KEY_MANAGER_ALLOWED_ORGS]') AND type in (N'U')) +CREATE TABLE AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +); + IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_GW_PUBLISHED_API_DETAILS]') AND TYPE IN (N'U')) CREATE TABLE AM_GW_PUBLISHED_API_DETAILS ( API_ID varchar(255) NOT NULL, diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql index 2f6d756905fd..f19dd773a474 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql.sql @@ -1944,6 +1944,17 @@ CREATE TABLE IF NOT EXISTS AM_POLICY_GLOBAL ( UNIQUE (UUID) )ENGINE INNODB; +CREATE TABLE IF NOT EXISTS AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +)ENGINE INNODB; + CREATE TABLE IF NOT EXISTS AM_THROTTLE_TIER_PERMISSIONS ( THROTTLE_TIER_PERMISSIONS_ID INT NOT NULL AUTO_INCREMENT, TIER VARCHAR(50) NULL, @@ -2180,6 +2191,14 @@ CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ); + +CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +); + -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- CREATE TABLE IF NOT EXISTS AM_GW_PUBLISHED_API_DETAILS ( diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql index 59541ae6e6c2..92ab8474c807 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/mysql_cluster.sql @@ -1666,6 +1666,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( UUID VARCHAR(256), TOKEN_TYPE VARCHAR(10), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE RESTRICT, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), @@ -2236,6 +2237,24 @@ CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ) ENGINE=NDB; +CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +)ENGINE=NDB; + +CREATE TABLE IF NOT EXISTS AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), +PRIMARY KEY (ORG_UUID) +)ENGINE=NDB; + -- BotDATA Email table -- CREATE TABLE IF NOT EXISTS AM_NOTIFICATION_SUBSCRIBER ( UUID VARCHAR(255), diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql index 0a6aed95a70d..d146c9322e1c 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle.sql @@ -2412,6 +2412,7 @@ CREATE TABLE AM_APPLICATION ( UUID VARCHAR2(256), TOKEN_TYPE VARCHAR2(100), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE CASCADE, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), @@ -3369,7 +3370,26 @@ CREATE TABLE AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ) / + +CREATE TABLE AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +) + / +CREATE TABLE AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +) + / -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql index 81decde2c171..8fcbfebb4f71 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_23c.sql @@ -2412,6 +2412,7 @@ CREATE TABLE AM_APPLICATION ( UUID VARCHAR2(256), TOKEN_TYPE VARCHAR2(100), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE CASCADE, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), @@ -3382,6 +3383,25 @@ CREATE TABLE AM_KEY_MANAGER_PERMISSIONS ( ) / +CREATE TABLE AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +) + / + +CREATE TABLE AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +) + / -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql index afe7bfb94ee1..3baac167ab5c 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/oracle_rac.sql @@ -2402,6 +2402,7 @@ CREATE TABLE AM_APPLICATION ( UUID VARCHAR2(256), TOKEN_TYPE VARCHAR2(100), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE CASCADE, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), @@ -3346,6 +3347,26 @@ CREATE TABLE AM_KEY_MANAGER ( ) / +CREATE TABLE AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +) + / + +CREATE TABLE AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +) + / + CREATE TABLE AM_KEY_MANAGER_PERMISSIONS ( KEY_MANAGER_UUID VARCHAR(50) NOT NULL, PERMISSIONS_TYPE VARCHAR(50) NOT NULL, diff --git a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql index d1e1213b8e3f..a31ec3acdd71 100644 --- a/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql +++ b/features/apimgt/org.wso2.carbon.apimgt.core.feature/src/main/resources/sql/postgresql.sql @@ -1816,6 +1816,7 @@ CREATE TABLE IF NOT EXISTS AM_APPLICATION ( UUID VARCHAR(256), TOKEN_TYPE VARCHAR(10), ORGANIZATION VARCHAR(100), + SHARED_ORGANIZATION VARCHAR(100), FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, PRIMARY KEY(APPLICATION_ID), UNIQUE (NAME,SUBSCRIBER_ID,ORGANIZATION), @@ -2466,6 +2467,26 @@ CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_PERMISSIONS ( FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE ); +DROP TABLE IF EXISTS AM_KEY_MANAGER_ALLOWED_ORGS; +CREATE TABLE IF NOT EXISTS AM_KEY_MANAGER_ALLOWED_ORGS ( + KEY_MANAGER_UUID VARCHAR(50) NOT NULL, + ALLOWED_ORGANIZATIONS VARCHAR(50) NOT NULL, + PRIMARY KEY (KEY_MANAGER_UUID, ALLOWED_ORGANIZATIONS), + FOREIGN KEY (KEY_MANAGER_UUID) REFERENCES AM_KEY_MANAGER(UUID) ON DELETE CASCADE +); + +DROP TABLE IF EXISTS AM_ORGANIZATION_MAPPING; +CREATE TABLE IF NOT EXISTS AM_ORGANIZATION_MAPPING ( + ORG_UUID VARCHAR(50) NOT NULL, + EXT_ORG_ID VARCHAR(100) NOT NULL, + DISPLAY_NAME VARCHAR(100) NULL, + PARENT_ORG_UUID VARCHAR(50), + ORG_HANDLE VARCHAR(100), + DESCRIPTION VARCHAR(256) NULL, + ROOT_ORGANIZATION VARCHAR(255), + PRIMARY KEY (ORG_UUID) +); + -- AM_GW_PUBLISHED_API_DETAILS & AM_GW_API_ARTIFACTS are independent tables for Artifact synchronizer feature which -- -- should not have any referential integrity constraints with other tables in AM database-- DROP TABLE IF EXISTS AM_GW_PUBLISHED_API_DETAILS; From 19b3677938b4380b3e8eb7d73989b21764e60b07 Mon Sep 17 00:00:00 2001 From: Chamila Adhikarinayake Date: Thu, 30 Jan 2025 15:52:36 +0530 Subject: [PATCH 63/74] Refactor code --- .../org/wso2/carbon/apimgt/api/model/API.java | 13 ++++----- .../apimgt/api/model/OrganizationInfo.java | 29 ++++++++++++------- .../wso2/carbon/apimgt/impl/APIConstants.java | 1 - .../carbon/apimgt/impl/APIConsumerImpl.java | 3 +- .../apimgt/impl/APIManagerConfiguration.java | 5 ---- .../apimgt/impl/ThrottlePolicyConstants.java | 1 - .../carbon/apimgt/impl/dao/ApiMgtDAO.java | 5 +--- .../apimgt/impl/dto/OrgAccessControl.java | 15 +++++----- .../indexing/indexer/CustomAPIIndexer.java | 2 -- .../carbon/apimgt/impl/utils/APIUtil.java | 7 +---- .../persistence/RegistryPersistenceImpl.java | 16 +--------- .../utils/RegistryPersistenceUtil.java | 8 ++--- .../common/mappings/PublisherCommonUtils.java | 2 +- .../api/store/v1/impl/ApisApiServiceImpl.java | 2 -- 14 files changed, 41 insertions(+), 68 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java index 216f1e79e4c4..9b19fc8724c2 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java @@ -104,8 +104,7 @@ public class API implements Serializable { private String visibleTenants; private String visibleOrganizations; - - private boolean endpointSecured = false; + private boolean endpointSecured = false; private boolean endpointAuthDigest = false; private String endpointUTUsername; private String endpointUTPassword; @@ -1565,12 +1564,12 @@ public void setApiPolicies(List apiPolicies) { } public String getVisibleOrganizations() { - return visibleOrganizations; - } + return visibleOrganizations; + } - public void setVisibleOrganizations(String visibleOrganizations) { - this.visibleOrganizations = visibleOrganizations; - } + public void setVisibleOrganizations(String visibleOrganizations) { + this.visibleOrganizations = visibleOrganizations; + } /** * Property to hold whether the API isEGRESS (1) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java index 4ea772b91a53..91295a83d35d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2025, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,52 +14,61 @@ * limitations under the License. */ - package org.wso2.carbon.apimgt.api.model; public class OrganizationInfo { - - String superOrganization; - String name; - String id; - String organizationId; - OrganizationInfo parentOrganization; - OrganizationInfo[] childOrganizations; - + private String superOrganization; + private String name; + private String id; + private String organizationId; + private OrganizationInfo parentOrganization; + private OrganizationInfo[] childOrganizations; + public String getSuperOrganization() { return superOrganization; } + public void setSuperOrganization(String superOrganization) { this.superOrganization = superOrganization; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public OrganizationInfo getParentOrganization() { return parentOrganization; } + public void setParentOrganization(OrganizationInfo parentOrganization) { this.parentOrganization = parentOrganization; } + public OrganizationInfo[] getChildOrganizations() { return childOrganizations; } + public void setChildOrganizations(OrganizationInfo[] childOrganizations) { this.childOrganizations = childOrganizations; } + public String getOrganizationId() { return organizationId; } + public void setOrganizationId(String organizationId) { this.organizationId = organizationId; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index 3c5749134fd8..dd6909f89a58 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -3271,7 +3271,6 @@ public static class TokenValidationConstants { public static final String ORG_BASED_ACCESS_CONTROL_ENABLE = "Enable"; public static final String ORG_BASED_ACCESS_CONTROL_ORG_NAME_CLAIM = "OrganizationNameLocalClaim"; public static final String ORG_BASED_ACCESS_CONTROL_ORG_ID_CLAIM = "OrganizationIDLocalClaim"; - public static final String ORG_BASED_ACCESS_CONTROL_SELECTOR_CLAIM = "OrgaizationSelectorLocalClaim"; public static class TransactionCounter { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index bb1eae894bef..c49a699300d0 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -3922,7 +3922,7 @@ private Map searchPaginatedAPIs(String searchQuery, int start, i throw new APIManagementException("Error while searching the api ", e); } return result; - } +} @Override public ApiTypeWrapper getAPIorAPIProductByUUID(String uuid, String organization) throws APIManagementException { @@ -4221,7 +4221,6 @@ public Map searchPaginatedContent(String searchQuery, String org Organization org = new Organization(organization); Map properties = APIUtil.getUserProperties(userame); String[] roles = APIUtil.getFilteredUserRoles(userame); - ; UserContext ctx = new UserContext(userame, org, properties, roles); return searchPaginatedContent(org, searchQuery, start, end, ctx); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java index 97d4e5147d56..1310749a00c1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIManagerConfiguration.java @@ -701,11 +701,6 @@ private void setOrgBasedAccessControlConfigs(OMElement element) { orgAccessControl.setEnabled(Boolean.parseBoolean(orgEnableElement.getText())); } - OMElement orgSelectorElement = - element.getFirstChildWithName(new QName(APIConstants.ORG_BASED_ACCESS_CONTROL_SELECTOR_CLAIM)); - if (orgSelectorElement != null) { - orgAccessControl.setOrgSelectorClaim(orgSelectorElement.getText()); - } OMElement orgNameElement = element.getFirstChildWithName(new QName(APIConstants.ORG_BASED_ACCESS_CONTROL_ORG_NAME_CLAIM)); if (orgNameElement != null) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java index a70101a864ba..ebef1dbf2558 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/ThrottlePolicyConstants.java @@ -131,5 +131,4 @@ public class ThrottlePolicyConstants { public static final String COLUMN_MAX_DEPTH = "MAX_DEPTH"; public static final String COLUMN_MAX_COMPLEXITY = "MAX_COMPLEXITY"; - } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java index a3d281ec7048..c205556bac49 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/ApiMgtDAO.java @@ -11984,7 +11984,6 @@ public void addSubscriptionPolicy(SubscriptionPolicy policy) throws APIManagemen policy.getMonetizationPlanProperties().get(APIConstants.Monetization.CURRENCY)); policyStatement.setInt(26, policy.getSubscriberCount()); } - policyStatement.executeUpdate(); conn.commit(); } catch (SQLIntegrityConstraintViolationException e) { @@ -13177,7 +13176,6 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan policy.setGraphQLMaxDepth(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_DEPTH)); policy.setGraphQLMaxComplexity(resultSet.getInt(ThrottlePolicyConstants.COLUMN_MAX_COMPLEXITY)); policy.setSubscriberCount(resultSet.getInt(ThrottlePolicyConstants.COLUMN_CONNECTION_COUNT)); - InputStream binary = resultSet.getBinaryStream(ThrottlePolicyConstants.COLUMN_CUSTOM_ATTRIB); if (binary != null) { byte[] customAttrib = APIUtil.toByteArray(binary); @@ -13207,7 +13205,7 @@ public SubscriptionPolicy getSubscriptionPolicyByUUID(String uuid) throws APIMan } return policy; } - + /** * Retrieves list of pipelines for the policy with policy Id: policyId * @@ -13692,7 +13690,6 @@ public void updateSubscriptionPolicy(SubscriptionPolicy policy) throws APIManage } } updateStatement.executeUpdate(); - connection.commit(); } catch (SQLException e) { if (connection != null) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java index 3c24445940e9..ef0d1c57d2e7 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dto/OrgAccessControl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2025, WSO2 LLc. (http://www.wso2.org) All Rights Reserved. * * WSO2 LLc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -22,29 +22,28 @@ public class OrgAccessControl { private boolean isEnabled; private String orgNameLocalClaim; private String orgIdLocalClaim; - private String orgselectorClaim; + public boolean isEnabled() { return isEnabled; } + public void setEnabled(boolean isEnabled) { this.isEnabled = isEnabled; } + public String getOrgNameLocalClaim() { return orgNameLocalClaim; } + public void setOrgNameLocalClaim(String orgNameLocalClaim) { this.orgNameLocalClaim = orgNameLocalClaim; } + public String getOrgIdLocalClaim() { return orgIdLocalClaim; } + public void setOrgIdLocalClaim(String orgIdLocalClaim) { this.orgIdLocalClaim = orgIdLocalClaim; } - public String getOrgSelectorClaim() { - return orgselectorClaim; - } - public void setOrgSelectorClaim(String orgselectorClaim) { - this.orgselectorClaim = orgselectorClaim; - } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java index 62de38990682..e6103d23b498 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/indexing/indexer/CustomAPIIndexer.java @@ -49,7 +49,6 @@ import static org.wso2.carbon.apimgt.impl.APIConstants.OVERVIEW_PREFIX; import static org.wso2.carbon.apimgt.impl.APIConstants.VISIBLE_ORGANIZATION_PROPERTY; - /** * This is the custom indexer to add the API properties, to existing APIs. */ @@ -73,7 +72,6 @@ public IndexDocument getIndexedDocument(AsyncIndexer.File2Index fileData) throws if (log.isDebugEnabled()) { log.debug("CustomAPIIndexer is currently indexing the api at path " + resourcePath); } - // Here we are adding properties as fields, so that we can search the properties as we do for attributes. IndexDocument indexDocument = super.getIndexedDocument(fileData); Map> fields = indexDocument.getFields(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 6f2fa276dacb..ccffe8f56ecb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -11137,7 +11137,6 @@ public static String getOrganizationIdFromExternalReference(String referenceId, organizationId = orgDetails.getOrganizationId(); } else { // No organization entry in the db. add entry without parent info. - OrganizationDetailsDTO info = new OrganizationDetailsDTO(); info.setExternalOrganizationReference(referenceId); info.setTenantDomain(rootOrganization); @@ -11147,7 +11146,6 @@ public static String getOrganizationIdFromExternalReference(String referenceId, if (addedInfo != null) { organizationId = addedInfo.getOrganizationId(); } - } return organizationId; } @@ -11155,16 +11153,13 @@ public static String getOrganizationIdFromExternalReference(String referenceId, public static String getOrganizationHandle(String name) { String sanatizedName = null; if (name == null) { - return sanatizedName; + return sanatizedName; } - String nowhitespace = WHITESPACE.matcher(name).replaceAll("-"); // Replace spaces with hyphens String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); // Decompose Unicode characters sanatizedName = NONLATIN.matcher(normalized).replaceAll(""); // Remove non-alphanumeric characters - // Convert to lowercase and trim hyphens from the beginning/end sanatizedName = sanatizedName.toLowerCase(Locale.ENGLISH).replaceAll("^-+|-+$", ""); - return sanatizedName; } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 0ceb36a37d2f..f98023345e2f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1183,9 +1183,6 @@ protected static List searchDevportalAPIs(String query, int query = query.replace("PUBLISHED", "published").replace("PROTOTYPED", "prototyped").replace("DEPRECATED", "deprecated");// convert to lowercase Map fields = RegistryPersistenceUtil.getFields(query); - //since store_view_roles and overview_visible_organizations are passed as property search value, remove this. - fields.remove("overview_store_view_roles"); - fields.remove("overview_visible_organizations"); String filterQuery = RegistryPersistenceUtil.buildFQStringForProperties(query); String modifiedQuery = "q=* TO *&" + filterQuery; @@ -1243,9 +1240,6 @@ private DevPortalAPISearchResult searchPaginatedDevPortalAPIs(Registry userRegis PaginationContext.init(start, offset, "ASC", APIConstants.API_OVERVIEW_NAME, maxPaginationLimit); log.debug("Dev portal list apis query " + searchQuery); - //List governanceArtifacts = GovernanceUtils - // .findGovernanceArtifacts(searchQuery, userRegistry, APIConstants.API_RXT_MEDIA_TYPE, - // true); List governanceArtifacts = searchDevportalAPIs(searchQuery, tenantIDLocal, userRegistry, start, offset); totalLength = PaginationContext.getInstance().getLength(); boolean isFound = true; @@ -3458,10 +3452,6 @@ public PublisherAPIProduct addAPIProduct(Organization org, PublisherAPIProduct p String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; - // if (StringUtils.isEmpty(apiProduct.getVisibleOrganizations())) { - //visibleOrgs = apiProduct.getVisibleOrganizations(); - // TODO fix for products and do needful for unified search - // } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), apiProduct.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(apiProduct.getId().getProviderName(), @@ -3689,10 +3679,6 @@ public PublisherAPIProduct updateAPIProduct(Organization org, PublisherAPIProduc String publisherAccessControlRoles = apiProduct.getAccessControlRoles(); String visibleOrgs = APIConstants.DEFAULT_VISIBLE_ORG; - // if (APIConstants.API_RESTRICTED_BY_ORG.equals(apiProduct.getVisibility())){ - //visibleOrgs = apiProduct.getVisibleOrganizations(); - // TODO fix for products and do needful for unified search - // } updateRegistryResources(registry, artifactPath, publisherAccessControlRoles, apiProduct.getAccessControl(), apiProduct.getAdditionalProperties(), visibleOrgs); RegistryPersistenceUtil.setResourcePermissions(apiProduct.getId().getProviderName(), @@ -4339,7 +4325,7 @@ private void setAPITypeForSwagger(String resourcePath, int index, } private String getOrganizationVisibilityForApiArtifact(Registry registry, String apiId) throws RegistryException { - /*Get org visibility value*/ + // Get org visibility value* String artifactPath = GovernanceUtils.getArtifactPath(registry, apiId); //get API Resource apiResource = registry.get(artifactPath); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index 3831fbf3b1b9..b06cbef4515f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -187,7 +187,7 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_ENABLE_STORE, Boolean.toString(api.isEnableStore())); artifact.setAttribute(APIConstants.API_OVERVIEW_TESTKEY, api.getTestKey()); artifact.setAttribute(APIConstants.API_OVERVIEW_VERSION_COMPARABLE, api.getVersionTimestamp()); - + //Validate if the API has an unsupported context before setting it in the artifact String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); if (APIConstants.SUPER_TENANT_DOMAIN.equals(tenantDomain)) { @@ -1919,7 +1919,6 @@ public static Map getFields(String query) { for (String parameter : parameters) { // Split each parameter by '=' to get key and value String[] keyValue = parameter.split("="); - // Extract the key and value String key = keyValue[0]; String value = keyValue.length > 1 ? keyValue[1] : ""; @@ -1950,9 +1949,10 @@ public static Map getFields(String query) { break; } } - outputMap.put("mediaType", "application/vnd.wso2-api+xml"); - + //since store_view_roles and overview_visible_organizations are passed as property search value, remove this. + outputMap.remove("overview_store_view_roles"); + outputMap.remove("overview_visible_organizations"); return outputMap; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index 84453bd2a236..f5ad71b81532 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -1508,7 +1508,7 @@ public static API prepareToCreateAPIByDTO(APIDTO body, APIProvider apiProvider, throw new APIManagementException(errorMessage, ExceptionCodes.INVALID_USER_ROLES); } } - + //Get all existing versions of api been adding List apiVersions = apiProvider.getApiVersionsMatchingApiNameAndOrganization(body.getName(), diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 7cc85407f005..3901ac862886 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -108,8 +108,6 @@ public Response apisGet(Integer limit, Integer offset, String xWSO2Tenant, Strin .replace(APIConstants.CONTENT_SEARCH_TYPE_PREFIX + ":", APIConstants.NAME_TYPE_PREFIX + ":"); } - //Map allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, superOrganization, offset, - // limit, null, null); Map allMatchedApisMap; if (APIUtil.isOrganizationAccessControlEnabled()) { allMatchedApisMap = apiConsumer.searchPaginatedAPIs(query, orgInfo, offset, From a8c07a3892b6e8b87b1b25a4bbb8b01cafced9f8 Mon Sep 17 00:00:00 2001 From: Nethmi Ranasinghe Date: Fri, 31 Jan 2025 14:02:00 +0530 Subject: [PATCH 64/74] Fix minor bugs related to Organizations --- .../apimgt/rest/api/admin/v1/dto/OrganizationDTO.java | 6 +++--- .../rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java | 4 ++++ .../src/main/resources/admin-api.yaml | 2 +- .../src/main/resources/admin-api.yaml | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java index b9a59adb879c..6c790ba8ab30 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/admin/v1/dto/OrganizationDTO.java @@ -35,9 +35,8 @@ public OrganizationDTO organizationId(String organizationId) { } - @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", required = true, value = "UUID of the organization. ") + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", value = "UUID of the organization. ") @JsonProperty("organizationId") - @NotNull public String getOrganizationId() { return organizationId; } @@ -54,8 +53,9 @@ public OrganizationDTO externalOrganizationId(String externalOrganizationId) { } - @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", value = "External id of the organization. ") + @ApiModelProperty(example = "ece92bdc-e1e6-325c-b6f4-656208a041e9", required = true, value = "External id of the organization. ") @JsonProperty("externalOrganizationId") + @NotNull public String getExternalOrganizationId() { return externalOrganizationId; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java index 625b96458797..3b796a0d67eb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/admin/v1/impl/OrganizationsApiServiceImpl.java @@ -130,6 +130,10 @@ public Response organizationsPost(OrganizationDTO organizationDTO, MessageContex orgId = orgInfo.getOrganizationId(); organizationDTO.setParentOrganizationId(orgId); // set current users organization as parent id if available. } + if (organizationDTO.getParentOrganizationId() == null) { + throw new APIManagementException("Parent Organization not found", + ExceptionCodes.MISSING_ORGANINATION); + } OrganizationDetailsDTO orgDto = OrganizationsMappingUtil.toOrganizationDetailsDTO(organizationDTO); orgDto.setTenantDomain(superOrganization); orgDto = apiAdmin.addOrganization(orgDto); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml index 37e99ae43427..7af77d1f5481 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.admin.v1/src/main/resources/admin-api.yaml @@ -4889,7 +4889,7 @@ components: Organization: title: Organization required: - - organizationId + - externalOrganizationId type: object properties: organizationId: diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml index 37e99ae43427..7af77d1f5481 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/admin-api.yaml @@ -4889,7 +4889,7 @@ components: Organization: title: Organization required: - - organizationId + - externalOrganizationId type: object properties: organizationId: From 1e2297b0a14f324cbc484c47255f35e39e4e7301 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Wed, 22 Jan 2025 17:12:09 +0530 Subject: [PATCH 65/74] Add publisher REST API changes for organization based subscription policies --- .../org/wso2/carbon/apimgt/api/model/API.java | 45 ++++++- .../apimgt/api/model/OrganizationTiers.java | 58 ++++++++ .../wso2/carbon/apimgt/api/model/Tier.java | 2 + .../wso2/carbon/apimgt/impl/APIConstants.java | 1 + .../carbon/apimgt/impl/utils/APIUtil.java | 19 +++ .../apimgt/persistence/APIConstants.java | 1 + .../persistence/dto/OrganizationTiers.java | 50 +++++++ .../apimgt/persistence/dto/PublisherAPI.java | 9 ++ .../utils/RegistryPersistenceUtil.java | 10 ++ .../src/main/resources/publisher-api.yaml | 24 ++++ .../rest/api/publisher/v1/dto/APIDTO.java | 26 +++- .../v1/dto/OrganizationPoliciesDTO.java | 124 ++++++++++++++++++ .../v1/common/mappings/APIMappingUtil.java | 60 ++++++++- .../common/mappings/PublisherCommonUtils.java | 63 ++++++++- .../src/main/resources/publisher-api.yaml | 24 ++++ 15 files changed, 508 insertions(+), 8 deletions(-) create mode 100644 components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java create mode 100644 components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationPoliciesDTO.java diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java index 9b19fc8724c2..9997a8a91f6e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java @@ -30,6 +30,7 @@ import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; @@ -74,6 +75,7 @@ public class API implements Serializable { private Date lastUpdated; private String updatedBy; private Set availableTiers = new LinkedHashSet(); + private Set availableTiersForOrganizations = new LinkedHashSet<>(); private Set availableSubscriptionLevelPolicies = new LinkedHashSet(); private String apiLevelPolicy; private AuthorizationPolicy authorizationPolicy; @@ -766,8 +768,47 @@ public void removeAllPolicies() { availableSubscriptionLevelPolicies.clear(); } - public void removeAvailableTiers(Set availableTiers) { - this.availableTiers.removeAll(availableTiers); + public Set getAvailableTiersForOrganizations() { + return Collections.unmodifiableSet(availableTiersForOrganizations); + } + + public void setAvailableTiersForOrganizations(Set availableTiersForOrganizations) { + this.availableTiersForOrganizations = availableTiersForOrganizations; + } + + public void removeAllTiersForOrganizations() { + availableTiersForOrganizations.clear(); + } + + public void setAvailableTiersForOrganizationsFromString(String tiersString) { + + if (tiersString == null || tiersString.isEmpty()) { + return; + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, OrganizationTiers[].class); + availableTiersForOrganizations = new LinkedHashSet<>(Arrays.asList(tiersArray)); + } catch (Exception e) { + log.error("Error while converting string to availableTiersForOrganizations object for API : " + getUUID(), + e); + } + } + + public String getAvailableTiersForOrganizationsAsString() { + if (availableTiersForOrganizations == null || availableTiersForOrganizations.isEmpty()) { + return null; + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(availableTiersForOrganizations); + } catch (JsonProcessingException e) { + log.error("Error while converting availableTiersForOrganizations to string for API : " + getUUID(), e); + return null; + } catch (Exception e) { + log.error("Unexpected error while processing availableTiersForOrganizations for API : " + getUUID(), e); + return null; + } } public Set getUriTemplates() { diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java new file mode 100644 index 000000000000..e280c330e569 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.api.model; + +import java.util.Set; + +/** + * This class represent the Tier + */ +public class OrganizationTiers { + + private String organizationID; + private String organizationName; + private Set tiers; + + public String getOrganizationID() { + return organizationID; + } + + public void setOrganizationID(String organizationID) { + this.organizationID = organizationID; + } + + public String getOrganizationName() { + return organizationName; + } + + public void setOrganizationName(String organizationName) { + this.organizationName = organizationName; + } + + public Set getTiers() { + return tiers; + } + + public void setTiers(Set tiers) { + this.tiers = tiers; + } + + public void removeAllTiers() { + tiers.clear(); + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Tier.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Tier.java index 4d3317d2cb99..7837ec54402b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Tier.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/Tier.java @@ -59,6 +59,8 @@ public void setMonetizationAttributes(Map monetizationAttributes this.monetizationAttributes = monetizationAttributes; } + public Tier() {} + public Tier(String name) { this.name = name; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java index dd6909f89a58..af055bbe2016 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConstants.java @@ -307,6 +307,7 @@ public final class APIConstants { public static final String API_OVERVIEW_THUMBNAIL_URL = "overview_thumbnail"; public static final String API_OVERVIEW_STATUS = "overview_status"; public static final String API_OVERVIEW_TIER = "overview_tier"; + public static final String API_OVERVIEW_ORGANIZATION_TIERS = "overview_organizationTiers"; public static final String API_OVERVIEW_SUB_POLICY = "overview_subPolicy"; public static final String API_OVERVIEW_API_POLICY = "overview_apiPolicy"; public static final String API_OVERVIEW_IS_LATEST = "overview_isLatest"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index fc457ff5a6e0..0cd3133a15db 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -691,6 +691,10 @@ public static API getAPI(GovernanceArtifact artifact) } } + // Set available tiers for organizations + String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); + api.setAvailableTiersForOrganizationsFromString(organizationTiers); + api.addAvailableTiers(availablePolicy); String tenantDomainName = MultitenantUtils.getTenantDomain(replaceEmailDomainBack(providerName)); api.setMonetizationCategory(getAPIMonetizationCategory(availablePolicy, tenantDomainName)); @@ -815,6 +819,11 @@ public static API getLightWeightAPI(GovernanceArtifact artifact) } } api.addAvailableTiers(availablePolicy); + + // Set available tiers for organizations + String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); + api.setAvailableTiersForOrganizationsFromString(organizationTiers); + String tenantDomainName = MultitenantUtils.getTenantDomain(replaceEmailDomainBack(providerName)); api.setMonetizationCategory(getAPIMonetizationCategory(availablePolicy, tenantDomainName)); @@ -994,6 +1003,11 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_TIER, tiers); } + if (api.getAvailableTiersForOrganizationsAsString() != null) { + artifact.setAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS, + api.getAvailableTiersForOrganizationsAsString()); + } + if (APIConstants.PUBLISHED.equals(apiStatus)) { artifact.setAttribute(APIConstants.API_OVERVIEW_IS_LATEST, "true"); } @@ -1050,6 +1064,7 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, if (apiSecurity != null && !apiSecurity.contains(APIConstants.DEFAULT_API_SECURITY_OAUTH2) && !apiSecurity.contains(APIConstants.API_SECURITY_API_KEY)) { artifact.setAttribute(APIConstants.API_OVERVIEW_TIER, ""); + artifact.setAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS, ""); } } catch (GovernanceException e) { String msg = "Failed to create API for : " + api.getId().getApiName(); @@ -2705,6 +2720,10 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry, APIIden Set availableTier = getAvailableTiers(definedTiers, tiers, apiName); api.addAvailableTiers(availableTier); + // Set available tiers for organizations + String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); + api.setAvailableTiersForOrganizationsFromString(organizationTiers); + api.setContext(artifact.getAttribute(APIConstants.API_OVERVIEW_CONTEXT)); api.setContextTemplate(artifact.getAttribute(APIConstants.API_OVERVIEW_CONTEXT_TEMPLATE)); api.setLatest(Boolean.parseBoolean(artifact.getAttribute(APIConstants.API_OVERVIEW_IS_LATEST))); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java index 903d2d8d9148..e77c43ba0e7d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/APIConstants.java @@ -41,6 +41,7 @@ public final class APIConstants { public static final String API_OVERVIEW_THUMBNAIL_URL = "overview_thumbnail"; public static final String API_OVERVIEW_STATUS = "overview_status"; public static final String API_OVERVIEW_TIER = "overview_tier"; + public static final String API_OVERVIEW_ORGANIZATION_TIERS = "overview_organizationTiers"; public static final String API_OVERVIEW_SUB_POLICY = "overview_subPolicy"; public static final String API_OVERVIEW_API_POLICY = "overview_apiPolicy"; public static final String API_OVERVIEW_IS_LATEST = "overview_isLatest"; diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java new file mode 100644 index 000000000000..cba7452931b7 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com) All Rights Reserved. + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.carbon.apimgt.persistence.dto; + +import java.util.Set; + +public class OrganizationTiers { + private String organizationID; + private String organizationName; + private Set tiers; + + public String getOrganizationID() { + return organizationID; + } + + public void setOrganizationID(String organizationID) { + this.organizationID = organizationID; + } + + public String getOrganizationName() { + return organizationName; + } + + public void setOrganizationName(String organizationName) { + this.organizationName = organizationName; + } + + public Set getTiers() { + return tiers; + } + + public void setTiers(Set tiers) { + this.tiers = tiers; + } +} diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java index fb3f51727431..da3ae93d52ab 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/PublisherAPI.java @@ -78,6 +78,7 @@ public class PublisherAPI extends PublisherAPIInfo { private String testKey; private String contextTemplate; private Set availableTierNames; + private Set availableTiersForOrganizations; private Set environments; private CORSConfiguration corsConfiguration; private WebsubSubscriptionConfiguration websubSubscriptionConfiguration; @@ -464,6 +465,14 @@ public void setAvailableTierNames(Set availableTierNames) { this.availableTierNames = availableTierNames; } + public Set getAvailableTiersForOrganizations() { + return availableTiersForOrganizations; + } + + public void setAvailableTiersForOrganizations(Set availableTiersForOrganizations) { + this.availableTiersForOrganizations = availableTiersForOrganizations; + } + public Set getEnvironments() { return environments; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index b06cbef4515f..97c072c1142b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -259,6 +259,11 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_TIER, tiers); } + if (api.getAvailableTiersForOrganizationsAsString() != null) { + artifact.setAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS, + api.getAvailableTiersForOrganizationsAsString()); + } + if (APIConstants.PUBLISHED.equals(apiStatus)) { artifact.setAttribute(APIConstants.API_OVERVIEW_IS_LATEST, "true"); } @@ -318,6 +323,7 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, if (apiSecurity != null && !apiSecurity.contains(APIConstants.DEFAULT_API_SECURITY_OAUTH2) && !apiSecurity .contains(APIConstants.API_SECURITY_API_KEY)) { artifact.setAttribute(APIConstants.API_OVERVIEW_TIER, ""); + artifact.setAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS, ""); } //set gateway vendor for the API @@ -737,6 +743,10 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry) } api.setAvailableTiers(availableTiers ); + // Set available tiers for organizations + String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); + api.setAvailableTiersForOrganizationsFromString(organizationTiers); + // This contains the resolved context api.setContext(artifact.getAttribute(APIConstants.API_OVERVIEW_CONTEXT)); // We set the context template here diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index f741ee334688..7f36e216fb2f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -10127,6 +10127,13 @@ components: x-otherScopes: - apim:api_publish - apim:api_manage + organizationPolicies: + type: array + items: + $ref: '#/components/schemas/OrganizationPolicies' + x-otherScopes: + - apim:api_publish + - apim:api_manage apiThrottlingPolicy: type: string description: The API level throttling policy selected for the particular @@ -12469,6 +12476,23 @@ components: example: "" operationPolicies: $ref: '#/components/schemas/APIOperationPolicies' + OrganizationPolicies: + title: Organization based Subscription Policies + type: object + required: + - organizationID + properties: + organizationID: + type: string + example: "36c87e00-57f0-4000-9f97-b379acc4e577" + organizationName: + type: string + example: "wso2" + policies: + type: array + example: ["Silver", "Gold", "Unlimited"] + items: + type: string ScopeList: title: Scope List type: object diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java index 9255b21c4f96..8fb3bc950326 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/APIDTO.java @@ -22,6 +22,7 @@ import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.APIThreatProtectionPoliciesDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.AdvertiseInfoDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.MediationPolicyDTO; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationPoliciesDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.WSDLInfoDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.WebsubSubscriptionConfigurationDTO; import javax.validation.constraints.*; @@ -144,6 +145,9 @@ public static AudienceEnum fromValue(String v) { private List policies = new ArrayList(); @Scope(name = "apim:api_publish", description="", value ="") @Scope(name = "apim:api_manage", description="", value ="") + private List organizationPolicies = new ArrayList(); + @Scope(name = "apim:api_publish", description="", value ="") + @Scope(name = "apim:api_manage", description="", value ="") private String apiThrottlingPolicy = null; private String authorizationHeader = null; private String apiKeyHeader = null; @@ -745,6 +749,24 @@ public void setPolicies(List policies) { this.policies = policies; } + /** + **/ + public APIDTO organizationPolicies(List organizationPolicies) { + this.organizationPolicies = organizationPolicies; + return this; + } + + + @ApiModelProperty(value = "") + @Valid + @JsonProperty("organizationPolicies") + public List getOrganizationPolicies() { + return organizationPolicies; + } + public void setOrganizationPolicies(List organizationPolicies) { + this.organizationPolicies = organizationPolicies; + } + /** * The API level throttling policy selected for the particular API **/ @@ -1476,6 +1498,7 @@ public boolean equals(java.lang.Object o) { Objects.equals(transport, API.transport) && Objects.equals(tags, API.tags) && Objects.equals(policies, API.policies) && + Objects.equals(organizationPolicies, API.organizationPolicies) && Objects.equals(apiThrottlingPolicy, API.apiThrottlingPolicy) && Objects.equals(authorizationHeader, API.authorizationHeader) && Objects.equals(apiKeyHeader, API.apiKeyHeader) && @@ -1519,7 +1542,7 @@ public boolean equals(java.lang.Object o) { @Override public int hashCode() { - return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, audiences, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, visibleOrganizations, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, subtypeConfiguration, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, gatewayType, asyncTransportProtocols, egress); + return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, audiences, transport, tags, policies, organizationPolicies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, visibleOrganizations, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, subtypeConfiguration, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, gatewayType, asyncTransportProtocols, egress); } @Override @@ -1551,6 +1574,7 @@ public String toString() { sb.append(" transport: ").append(toIndentedString(transport)).append("\n"); sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); sb.append(" policies: ").append(toIndentedString(policies)).append("\n"); + sb.append(" organizationPolicies: ").append(toIndentedString(organizationPolicies)).append("\n"); sb.append(" apiThrottlingPolicy: ").append(toIndentedString(apiThrottlingPolicy)).append("\n"); sb.append(" authorizationHeader: ").append(toIndentedString(authorizationHeader)).append("\n"); sb.append(" apiKeyHeader: ").append(toIndentedString(apiKeyHeader)).append("\n"); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationPoliciesDTO.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationPoliciesDTO.java new file mode 100644 index 000000000000..c6c30f0c3120 --- /dev/null +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/dto/OrganizationPoliciesDTO.java @@ -0,0 +1,124 @@ +package org.wso2.carbon.apimgt.rest.api.publisher.v1.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.*; + + +import io.swagger.annotations.*; +import java.util.Objects; + +import javax.xml.bind.annotation.*; +import org.wso2.carbon.apimgt.rest.api.common.annotations.Scope; +import com.fasterxml.jackson.annotation.JsonCreator; + +import javax.validation.Valid; + + + +public class OrganizationPoliciesDTO { + + private String organizationID = null; + private String organizationName = null; + private List policies = new ArrayList(); + + /** + **/ + public OrganizationPoliciesDTO organizationID(String organizationID) { + this.organizationID = organizationID; + return this; + } + + + @ApiModelProperty(example = "36c87e00-57f0-4000-9f97-b379acc4e577", required = true, value = "") + @JsonProperty("organizationID") + @NotNull + public String getOrganizationID() { + return organizationID; + } + public void setOrganizationID(String organizationID) { + this.organizationID = organizationID; + } + + /** + **/ + public OrganizationPoliciesDTO organizationName(String organizationName) { + this.organizationName = organizationName; + return this; + } + + + @ApiModelProperty(example = "wso2", value = "") + @JsonProperty("organizationName") + public String getOrganizationName() { + return organizationName; + } + public void setOrganizationName(String organizationName) { + this.organizationName = organizationName; + } + + /** + **/ + public OrganizationPoliciesDTO policies(List policies) { + this.policies = policies; + return this; + } + + + @ApiModelProperty(example = "[\"Silver\",\"Gold\",\"Unlimited\"]", value = "") + @JsonProperty("policies") + public List getPolicies() { + return policies; + } + public void setPolicies(List policies) { + this.policies = policies; + } + + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + OrganizationPoliciesDTO organizationPolicies = (OrganizationPoliciesDTO) o; + return Objects.equals(organizationID, organizationPolicies.organizationID) && + Objects.equals(organizationName, organizationPolicies.organizationName) && + Objects.equals(policies, organizationPolicies.policies); + } + + @Override + public int hashCode() { + return Objects.hash(organizationID, organizationName, policies); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class OrganizationPoliciesDTO {\n"); + + sb.append(" organizationID: ").append(toIndentedString(organizationID)).append("\n"); + sb.append(" organizationName: ").append(toIndentedString(organizationName)).append("\n"); + sb.append(" policies: ").append(toIndentedString(policies)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java index 19c85bd93fe7..3ae246b15ae4 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/APIMappingUtil.java @@ -54,6 +54,7 @@ import org.wso2.carbon.apimgt.api.model.LifeCycleEvent; import org.wso2.carbon.apimgt.api.model.Mediation; import org.wso2.carbon.apimgt.api.model.OperationPolicy; +import org.wso2.carbon.apimgt.api.model.OrganizationTiers; import org.wso2.carbon.apimgt.api.model.ResourcePath; import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.SequenceBackendData; @@ -113,6 +114,7 @@ import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.MockResponsePayloadListDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OpenAPIDefinitionValidationResponseDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OpenAPIDefinitionValidationResponseInfoDTO; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationPoliciesDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.PaginationDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.ProductAPIDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.ResourcePathDTO; @@ -302,12 +304,34 @@ public static API fromDTOtoAPI(APIDTO dto, String provider) throws APIManagement model.addTags(apiTags); } + // Set tiers without considering organizations Set apiTiers = new HashSet<>(); List tiersFromDTO = dto.getPolicies(); for (String tier : tiersFromDTO) { apiTiers.add(new Tier(tier)); } model.addAvailableTiers(apiTiers); + + if (APIUtil.isOrganizationAccessControlEnabled()) { + // Set tiers for organizations + Set organizationAPITiers = new HashSet<>(); + List organizationPoliciesDTOs = dto.getOrganizationPolicies(); + + for (OrganizationPoliciesDTO organizationPoliciesDTO : organizationPoliciesDTOs) { + OrganizationTiers organizationTiers = new OrganizationTiers(); + Set apiTiersForOrganization = new HashSet<>(); + for (String tier : organizationPoliciesDTO.getPolicies()) { + apiTiersForOrganization.add(new Tier(tier)); + } + organizationTiers.setOrganizationID(organizationPoliciesDTO.getOrganizationID()); + organizationTiers.setOrganizationName(organizationPoliciesDTO.getOrganizationName()); + organizationTiers.setTiers(apiTiersForOrganization); + organizationAPITiers.add(organizationTiers); + } + model.setAvailableTiersForOrganizations(organizationAPITiers); + } + + model.setApiLevelPolicy(dto.getApiThrottlingPolicy()); String transports = StringUtils.join(dto.getTransport(), ','); @@ -1368,6 +1392,17 @@ public static APIDTO fromAPItoDTO(API model, boolean preserveCredentials, dto.setPolicies(tiersToReturn); dto.setApiThrottlingPolicy(model.getApiLevelPolicy()); + if (APIUtil.isOrganizationAccessControlEnabled() && model.getAvailableTiersForOrganizations() != null) { + Set organizationAPITiers = model.getAvailableTiersForOrganizations(); + List organizationPolicies = new ArrayList<>(); + + for (OrganizationTiers organizationTiers : organizationAPITiers) { + OrganizationPoliciesDTO organizationPoliciesDTO = getOrganizationPoliciesDTO(organizationTiers); + organizationPolicies.add(organizationPoliciesDTO); + } + dto.setOrganizationPolicies(organizationPolicies); + } + //APIs created with type set to "NULL" will be considered as "HTTP" if (model.getType() == null || model.getType().toLowerCase().equals("null")) { dto.setType(APIDTO.TypeEnum.HTTP); @@ -2724,6 +2759,24 @@ public static APIProductDTO fromAPIProducttoDTO(APIProduct product) throws APIMa return productDto; } + /** + * This method converts OrganizationTiers object to OrganizationPoliciesDTO. + * @param organizationTiers OrganizationTiers object + * @return + */ + private static OrganizationPoliciesDTO getOrganizationPoliciesDTO(OrganizationTiers organizationTiers) { + OrganizationPoliciesDTO organizationPoliciesDTO = new OrganizationPoliciesDTO(); + Set apiTiers = organizationTiers.getTiers(); + List tiersToReturn = new ArrayList<>(); + for (Tier tier : apiTiers) { + tiersToReturn.add(tier.getName()); + } + organizationPoliciesDTO.setPolicies(tiersToReturn); + organizationPoliciesDTO.setOrganizationID(organizationTiers.getOrganizationID()); + organizationPoliciesDTO.setOrganizationName(organizationTiers.getOrganizationName()); + return organizationPoliciesDTO; + } + private static APIProductDTO.SubscriptionAvailabilityEnum mapSubscriptionAvailabilityFromAPIProducttoDTO( String subscriptionAvailability) { @@ -2826,9 +2879,6 @@ public static APIProduct fromDTOtoAPIProduct(APIProductDTO dto, String provider) product.setAudiences(new HashSet<>(audiences)); } - Set apiTiers = new HashSet<>(); - List tiersFromDTO = dto.getPolicies(); - if (dto.getVisibility() != null) { product.setVisibility(mapVisibilityFromDTOtoAPIProduct(dto.getVisibility())); } @@ -2850,11 +2900,13 @@ public static APIProduct fromDTOtoAPIProduct(APIProductDTO dto, String provider) product.setAccessControl(APIConstants.API_RESTRICTED_VISIBILITY); } + // Set Tiers without considering organizations + Set apiTiers = new HashSet<>(); + List tiersFromDTO = dto.getPolicies(); for (String tier : tiersFromDTO) { apiTiers.add(new Tier(tier)); } product.setAvailableTiers(apiTiers); - product.setProductLevelPolicy(dto.getApiThrottlingPolicy()); product.setGatewayVendor(dto.getGatewayVendor()); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java index f5ad71b81532..8f121daa7295 100755 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/common/mappings/PublisherCommonUtils.java @@ -98,6 +98,7 @@ import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.GraphQLValidationResponseGraphQLInfoDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.LifecycleHistoryDTO; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.LifecycleStateDTO; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationPoliciesDTO; import org.wso2.carbon.core.util.CryptoException; import org.wso2.carbon.core.util.CryptoUtil; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; @@ -429,6 +430,7 @@ private static API prepareForUpdateApi(API originalAPI, APIDTO apiDtoToUpdate, A List apiSecurity = apiDtoToUpdate.getSecurityScheme(); //validation for tiers List tiersFromDTO = apiDtoToUpdate.getPolicies(); + List organizationPoliciesDTOs = apiDtoToUpdate.getOrganizationPolicies(); // Remove the subscriptionless tier if other tiers are available. if (tiersFromDTO != null && tiersFromDTO.size() > 1) { String tierToDrop = null; @@ -478,9 +480,9 @@ private static API prepareForUpdateApi(API originalAPI, APIDTO apiDtoToUpdate, A } } + Set definedTiers = apiProvider.getTiers(); if (tiersFromDTO != null && !tiersFromDTO.isEmpty()) { //check whether the added API's tiers are all valid - Set definedTiers = apiProvider.getTiers(); List invalidTiers = getInvalidTierNames(definedTiers, tiersFromDTO); if (invalidTiers.size() > 0) { throw new APIManagementException( @@ -488,6 +490,65 @@ private static API prepareForUpdateApi(API originalAPI, APIDTO apiDtoToUpdate, A ExceptionCodes.TIER_NAME_INVALID); } } + // Organization based subscription policies + if (APIUtil.isOrganizationAccessControlEnabled()) { + for (OrganizationPoliciesDTO organizationPoliciesDTO : organizationPoliciesDTOs) { + List organizationTiersFromDTO = organizationPoliciesDTO.getPolicies(); + + // Remove the subscriptionless tier if other tiers are available. + if (organizationTiersFromDTO != null && organizationTiersFromDTO.size() > 1) { + String tierToDrop = null; + for (String tier : organizationTiersFromDTO) { + if (tier.contains(APIConstants.DEFAULT_SUB_POLICY_SUBSCRIPTIONLESS)) { + tierToDrop = tier; + break; + } + } + if (tierToDrop != null) { + organizationTiersFromDTO.remove(tierToDrop); + organizationPoliciesDTO.setPolicies(tiersFromDTO); + } + } + boolean conditionForOrganization = ( + (organizationTiersFromDTO == null || organizationTiersFromDTO.isEmpty() && !( + APIConstants.CREATED.equals(originalStatus) || APIConstants.PROTOTYPED.equals( + originalStatus))) && !apiDtoToUpdate.getAdvertiseInfo().isAdvertised()); + if (!APIUtil.isSubscriptionValidationDisablingAllowed(tenantDomain)) { + if (apiSecurity != null && (apiSecurity.contains(APIConstants.DEFAULT_API_SECURITY_OAUTH2) + || apiSecurity.contains(APIConstants.API_SECURITY_API_KEY)) && conditionForOrganization) { + throw new APIManagementException("A tier should be defined if the API is not in CREATED " + + "or PROTOTYPED state", ExceptionCodes.TIER_CANNOT_BE_NULL); + } + } else { + if (apiSecurity != null) { + if (apiSecurity.contains(APIConstants.API_SECURITY_API_KEY) && conditionForOrganization) { + throw new APIManagementException("A tier should be defined if the API is not in CREATED " + + "or PROTOTYPED state", ExceptionCodes.TIER_CANNOT_BE_NULL); + } else if (apiSecurity.contains(APIConstants.DEFAULT_API_SECURITY_OAUTH2)) { + // Internally set the default tier when no tiers are defined in order to support + // subscription validation disabling for OAuth2 secured APIs + if (organizationTiersFromDTO != null && organizationTiersFromDTO.isEmpty()) { + if (isAsyncAPI) { + organizationTiersFromDTO.add( + APIConstants.DEFAULT_SUB_POLICY_ASYNC_SUBSCRIPTIONLESS); + } else { + organizationTiersFromDTO.add(APIConstants.DEFAULT_SUB_POLICY_SUBSCRIPTIONLESS); + } + organizationPoliciesDTO.setPolicies(organizationTiersFromDTO); + } + } + } + } + if (organizationTiersFromDTO != null && !organizationTiersFromDTO.isEmpty()) { + List invalidTiers = getInvalidTierNames(definedTiers, organizationTiersFromDTO); + if (invalidTiers.size() > 0) { + throw new APIManagementException("Specified tier(s) " + Arrays.toString(invalidTiers.toArray()) + + " are invalid", ExceptionCodes.TIER_NAME_INVALID); + } + } + } + } + if (apiDtoToUpdate.getAccessControlRoles() != null) { String errorMessage = validateUserRoles(apiDtoToUpdate.getAccessControlRoles()); if (!errorMessage.isEmpty()) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index f741ee334688..7f36e216fb2f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -10127,6 +10127,13 @@ components: x-otherScopes: - apim:api_publish - apim:api_manage + organizationPolicies: + type: array + items: + $ref: '#/components/schemas/OrganizationPolicies' + x-otherScopes: + - apim:api_publish + - apim:api_manage apiThrottlingPolicy: type: string description: The API level throttling policy selected for the particular @@ -12469,6 +12476,23 @@ components: example: "" operationPolicies: $ref: '#/components/schemas/APIOperationPolicies' + OrganizationPolicies: + title: Organization based Subscription Policies + type: object + required: + - organizationID + properties: + organizationID: + type: string + example: "36c87e00-57f0-4000-9f97-b379acc4e577" + organizationName: + type: string + example: "wso2" + policies: + type: array + example: ["Silver", "Gold", "Unlimited"] + items: + type: string ScopeList: title: Scope List type: object From 1d2ed2d97c68f36cbde5658c8482c7e2d5d06ee7 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Thu, 30 Jan 2025 19:36:13 +0530 Subject: [PATCH 66/74] Add organizationID query parameter when fetching subscription policies --- .../src/main/resources/publisher-api.yaml | 8 ++++++ .../apimgt/rest/api/publisher/v1/ApisApi.java | 4 +-- .../rest/api/publisher/v1/ApisApiService.java | 2 +- .../publisher/v1/impl/ApisApiServiceImpl.java | 4 +-- .../v1/utils/RestApiPublisherUtils.java | 28 +++++++++++++++++++ .../src/main/resources/publisher-api.yaml | 8 ++++++ 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml index 7f36e216fb2f..c8a77b2c0fea 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.common/src/main/resources/publisher-api.yaml @@ -1294,6 +1294,7 @@ paths: - $ref: '#/components/parameters/requestedTenant' - $ref: '#/components/parameters/If-None-Match' - $ref: '#/components/parameters/isAiApi' + - $ref: '#/components/parameters/organizationID' responses: 200: description: | @@ -14311,6 +14312,13 @@ components: schema: type: boolean default: false + organizationID: + name: organizationID + in: query + description: | + Indicates the organization ID + schema: + type: string offset: name: offset in: query diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java index 6eafedcdaadf..a38adfd3e19e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApi.java @@ -1113,8 +1113,8 @@ public Response getAPISpecificOperationPolicyContentByPolicyId(@ApiParam(value = @ApiResponse(code = 304, message = "Not Modified. Empty body because the client has already the latest version of the requested resource. ", response = Void.class), @ApiResponse(code = 404, message = "Not Found. The specified resource does not exist.", response = ErrorDTO.class), @ApiResponse(code = 406, message = "Not Acceptable. The requested media type is not supported.", response = ErrorDTO.class) }) - public Response getAPISubscriptionPolicies(@ApiParam(value = "**API ID** consisting of the **UUID** of the API. ",required=true) @PathParam("apiId") String apiId, @ApiParam(value = "For cross-tenant invocations, this is used to specify the tenant domain, where the resource need to be retirieved from. " )@HeaderParam("X-WSO2-Tenant") String xWSO2Tenant, @ApiParam(value = "Validator for conditional requests; based on the ETag of the formerly retrieved variant of the resource. " )@HeaderParam("If-None-Match") String ifNoneMatch, @ApiParam(value = "Indicates the quota policy type to be AI API quota or not. ", defaultValue="false") @DefaultValue("false") @QueryParam("isAiApi") Boolean isAiApi) throws APIManagementException{ - return delegate.getAPISubscriptionPolicies(apiId, xWSO2Tenant, ifNoneMatch, isAiApi, securityContext); + public Response getAPISubscriptionPolicies(@ApiParam(value = "**API ID** consisting of the **UUID** of the API. ",required=true) @PathParam("apiId") String apiId, @ApiParam(value = "For cross-tenant invocations, this is used to specify the tenant domain, where the resource need to be retirieved from. " )@HeaderParam("X-WSO2-Tenant") String xWSO2Tenant, @ApiParam(value = "Validator for conditional requests; based on the ETag of the formerly retrieved variant of the resource. " )@HeaderParam("If-None-Match") String ifNoneMatch, @ApiParam(value = "Indicates the quota policy type to be AI API quota or not. ", defaultValue="false") @DefaultValue("false") @QueryParam("isAiApi") Boolean isAiApi, @ApiParam(value = "Indicates the organization ID ") @QueryParam("organizationID") String organizationID) throws APIManagementException{ + return delegate.getAPISubscriptionPolicies(apiId, xWSO2Tenant, ifNoneMatch, isAiApi, organizationID, securityContext); } @GET diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java index 8d7b71fe1339..3dca596e45e6 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/gen/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/ApisApiService.java @@ -116,7 +116,7 @@ public interface ApisApiService { public Response getAPIRevisionDeployments(String apiId, MessageContext messageContext) throws APIManagementException; public Response getAPIRevisions(String apiId, String query, MessageContext messageContext) throws APIManagementException; public Response getAPISpecificOperationPolicyContentByPolicyId(String apiId, String operationPolicyId, MessageContext messageContext) throws APIManagementException; - public Response getAPISubscriptionPolicies(String apiId, String xWSO2Tenant, String ifNoneMatch, Boolean isAiApi, MessageContext messageContext) throws APIManagementException; + public Response getAPISubscriptionPolicies(String apiId, String xWSO2Tenant, String ifNoneMatch, Boolean isAiApi, String organizationID, MessageContext messageContext) throws APIManagementException; public Response getAPISwagger(String apiId, String ifNoneMatch, MessageContext messageContext) throws APIManagementException; public Response getAPIThumbnail(String apiId, String ifNoneMatch, MessageContext messageContext) throws APIManagementException; public Response getAllAPISpecificOperationPolicies(String apiId, Integer limit, Integer offset, String query, MessageContext messageContext) throws APIManagementException; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java index 7a262e761e26..51d7a50287bc 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/impl/ApisApiServiceImpl.java @@ -3689,7 +3689,7 @@ public Response generateMockScripts(String apiId, String ifNoneMatch, MessageCon @Override public Response getAPISubscriptionPolicies(String apiId, String xWSO2Tenant, String ifNoneMatch, Boolean isAiApi, - MessageContext messageContext) throws APIManagementException { + String organizationID, MessageContext messageContext) throws APIManagementException { APIProvider apiProvider = RestApiCommonUtil.getLoggedInUserProvider(); String organization = RestApiUtil.getValidatedOrganization(messageContext); APIDTO apiInfo = getAPIByID(apiId, apiProvider, organization); @@ -3697,7 +3697,7 @@ public Response getAPISubscriptionPolicies(String apiId, String xWSO2Tenant, Str ThrottlingPolicyDTO.PolicyLevelEnum.SUBSCRIPTION.toString(), true, isAiApi); if (apiInfo != null) { - List apiPolicies = apiInfo.getPolicies(); + List apiPolicies = RestApiPublisherUtils.getSubscriptionPoliciesForOrganization(apiInfo, organizationID); List apiThrottlingPolicies = ApisApiServiceImplUtils.filterAPIThrottlingPolicies(apiPolicies, availableThrottlingPolicyList); return Response.ok().entity(apiThrottlingPolicies).build(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/RestApiPublisherUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/RestApiPublisherUtils.java index cd7022132f65..470f7bba124c 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/RestApiPublisherUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/publisher/v1/utils/RestApiPublisherUtils.java @@ -45,6 +45,8 @@ import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.common.RestApiConstants; import org.wso2.carbon.apimgt.rest.api.publisher.v1.common.mappings.PublisherCommonUtils; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.APIDTO; +import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.OrganizationPoliciesDTO; import org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -57,6 +59,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; import java.util.Map; public class RestApiPublisherUtils { @@ -470,4 +474,28 @@ private static Path resolveFilePath(final String baseDirPathString, return resolvedPath; } + + /** + * Fetches subscription policies for the relevant organization ID. + * @param apiInfo APIDTO object + * @param organizationID Organziation ID + * @return List of subscription policies + */ + public static List getSubscriptionPoliciesForOrganization(APIDTO apiInfo, String organizationID) { + + if (organizationID == null) { + return apiInfo.getPolicies(); + } + List policies = new ArrayList<>(); + List organizationPoliciesDTOs = apiInfo.getOrganizationPolicies(); + if (organizationPoliciesDTOs != null && !organizationPoliciesDTOs.isEmpty()) { + for (OrganizationPoliciesDTO organizationPoliciesDTO : organizationPoliciesDTOs) { + if (StringUtils.equals(organizationID, organizationPoliciesDTO.getOrganizationID())) { + policies = organizationPoliciesDTO.getPolicies(); + break; + } + } + } + return policies; + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml index 7f36e216fb2f..c8a77b2c0fea 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1/src/main/resources/publisher-api.yaml @@ -1294,6 +1294,7 @@ paths: - $ref: '#/components/parameters/requestedTenant' - $ref: '#/components/parameters/If-None-Match' - $ref: '#/components/parameters/isAiApi' + - $ref: '#/components/parameters/organizationID' responses: 200: description: | @@ -14311,6 +14312,13 @@ components: schema: type: boolean default: false + organizationID: + name: organizationID + in: query + description: | + Indicates the organization ID + schema: + type: string offset: name: offset in: query From 4ccdbd2f9c40c5b91b557a6d519655dd6cf3a85a Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Thu, 30 Jan 2025 19:36:42 +0530 Subject: [PATCH 67/74] Add devportal related backend changes for organization based subscriptions --- .../carbon/apimgt/impl/APIConsumerImpl.java | 38 +++++++++---- .../carbon/apimgt/impl/utils/APIUtil.java | 18 +++++++ .../persistence/RegistryPersistenceImpl.java | 3 ++ .../persistence/dto/DevPortalAPIInfo.java | 53 +++++++++++++++++++ .../persistence/dto/OrganizationTiers.java | 4 ++ .../api/store/v1/impl/ApisApiServiceImpl.java | 5 ++ .../v1/impl/SubscriptionsApiServiceImpl.java | 19 +++++++ .../rest/api/store/v1/utils/APIUtils.java | 19 +++++++ 8 files changed, 150 insertions(+), 9 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index c49a699300d0..dd7383590c54 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -77,6 +77,7 @@ import org.wso2.carbon.apimgt.api.model.OAuthAppRequest; import org.wso2.carbon.apimgt.api.model.OAuthApplicationInfo; import org.wso2.carbon.apimgt.api.model.OrganizationInfo; +import org.wso2.carbon.apimgt.api.model.OrganizationTiers; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.Scope; import org.wso2.carbon.apimgt.api.model.SubscribedAPI; @@ -3854,7 +3855,7 @@ public Map searchPaginatedAPIs(String searchQuery, String organi Map properties = APIUtil.getUserProperties(userName); UserContext userCtx = new UserContext(userNameWithoutChange, org, properties, roles); - return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); + return searchPaginatedAPIs(searchQuery, start, end, org, userCtx, null); } @Override @@ -3867,15 +3868,19 @@ public Map searchPaginatedAPIs(String searchQuery, OrganizationI UserContext userCtx = new UserContext(userNameWithoutChange, new Organization(organizationInfo.getOrganizationId()), properties, roles); - return searchPaginatedAPIs(searchQuery, start, end, org, userCtx); + return searchPaginatedAPIs(searchQuery, start, end, org, userCtx, organizationInfo); } private Map searchPaginatedAPIs(String searchQuery, int start, int end, Organization org, - UserContext userCtx) throws APIManagementException { + UserContext userCtx, OrganizationInfo orgInfo) throws APIManagementException { Map result = new HashMap(); if (log.isDebugEnabled()) { log.debug("Original search query received : " + searchQuery); } + String organizationID = null; + if (orgInfo != null) { + organizationID = orgInfo.getOrganizationId(); + } try { DevPortalAPISearchResult searchAPIs = apiPersistenceInstance.searchAPIsForDevPortal(org, searchQuery, @@ -3889,6 +3894,7 @@ private Map searchPaginatedAPIs(String searchQuery, int start, i List apiList = new ArrayList<>(); for (DevPortalAPIInfo devPortalAPIInfo : list) { API mappedAPI = APIMapper.INSTANCE.toApi(devPortalAPIInfo); + APIUtil.updateAvailableTiersByOrganization(devPortalAPIInfo, organizationID); try { mappedAPI.setRating(APIUtil.getAverageRating(mappedAPI.getUuid())); Set tierNameSet = devPortalAPIInfo.getAvailableTierNames(); @@ -4034,22 +4040,36 @@ private API addTiersToAPI(API api, String organization) throws APIManagementExce int tenantId = APIUtil.getInternalIdFromTenantDomainOrOrganization(organization); Set tierNames = api.getAvailableTiers(); Map definedTiers = APIUtil.getTiers(tenantId); - - Set availableTiers = new HashSet(); Set deniedTiers = getDeniedTiers(tenantId); + Set availableTiers = getAvailableTiers(tierNames, deniedTiers, definedTiers); + api.removeAllTiers(); + api.addAvailableTiers(availableTiers); + if (APIUtil.isOrganizationAccessControlEnabled() && api.getAvailableTiersForOrganizations() != null) { + Set organizationTiersSet = api.getAvailableTiersForOrganizations(); + for (OrganizationTiers organizationTiers : organizationTiersSet) { + Set tierNamesForOrganization = organizationTiers.getTiers(); + Set availableTiersForOrganization = getAvailableTiers(tierNamesForOrganization, deniedTiers, definedTiers); + organizationTiers.removeAllTiers(); + organizationTiers.setTiers(availableTiersForOrganization); + } + } + return api; + } + + private Set getAvailableTiers(Set tierNames, Set deniedTiers, Map definedTiers) { + + Set availableTiers = new HashSet(); for (Tier tierName : tierNames) { Tier definedTier = definedTiers.get(tierName.getName()); if (definedTier != null && (!deniedTiers.contains(definedTier.getName()))) { availableTiers.add(definedTier); } else { - log.warn("Unknown tier: " + tierName + " found on API: "); + log.warn("Unknown tier: " + tierName + " found"); } } availableTiers.removeIf(tier -> deniedTiers.contains(tier.getName())); - api.removeAllTiers(); - api.addAvailableTiers(availableTiers); - return api; + return availableTiers; } private APIProduct addTiersToAPI(APIProduct apiProduct, String organization) throws APIManagementException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 0cd3133a15db..ecc045df1305 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -182,6 +182,8 @@ import org.wso2.carbon.apimgt.impl.notifier.exceptions.NotifierException; import org.wso2.carbon.apimgt.impl.recommendationmgt.RecommendationEnvironment; import org.wso2.carbon.apimgt.impl.resolver.OnPremResolver; +import org.wso2.carbon.apimgt.persistence.dto.DevPortalAPIInfo; +import org.wso2.carbon.apimgt.persistence.dto.OrganizationTiers; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.ServerConfiguration; import org.wso2.carbon.context.CarbonContext; @@ -3596,6 +3598,22 @@ public static float getAverageRating(int apiId) throws APIManagementException { return ApiMgtDAO.getInstance().getAverageRating(apiId); } + public static void updateAvailableTiersByOrganization(DevPortalAPIInfo devPortalAPIInfo, String organization) { + + Set availableTiers = devPortalAPIInfo.getAvailableTierNames(); + Set availableTiersForOrganizations = devPortalAPIInfo.getAvailableTiersForOrganizations(); + if (organization != null) { + for (OrganizationTiers organizationTiers : availableTiersForOrganizations) { + String orgName = organizationTiers.getOrganizationID(); + if (organization.equals(orgName)) { + availableTiers = organizationTiers.getTiers(); + break; + } + } + } + devPortalAPIInfo.setAvailableTierNames(availableTiers); + } + public static List getAllTenantsWithSuperTenant() throws UserStoreException { Tenant[] tenants = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager().getAllTenants(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 77fe3dc2c40b..77c057fd577f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1292,6 +1292,9 @@ private DevPortalAPISearchResult searchPaginatedDevPortalAPIs(Registry userRegis } } apiInfo.setAvailableTierNames(availableTiers); + // Set available tiers for organizations + String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); + apiInfo.setAvailableTiersForOrganizationsFromString(organizationTiers); apiInfo.setSubscriptionAvailability( artifact.getAttribute(APIConstants.API_OVERVIEW_SUBSCRIPTION_AVAILABILITY)); apiInfo.setSubscriptionAvailableOrgs( diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java index 4b0c8fd2ad9c..aface03db92d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java @@ -15,6 +15,14 @@ */ package org.wso2.carbon.apimgt.persistence.dto; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.api.model.API; +import org.wso2.carbon.apimgt.api.model.Tier; + +import java.util.Arrays; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -24,6 +32,7 @@ * APIs in DevPortal which are stored in the persistence layer are included in this. */ public class DevPortalAPIInfo { + private static final Log log = LogFactory.getLog(DevPortalAPIInfo.class); private String id; private String apiName; private String version; @@ -34,6 +43,7 @@ public class DevPortalAPIInfo { private String businessOwner; private String status; private Set availableTierNames; + private Set availableTiersForOrganizations = new LinkedHashSet<>();; private String subscriptionAvailability; private String subscriptionAvailableOrgs; private String createdTime; @@ -131,6 +141,49 @@ public Set getAvailableTierNames() { public void setAvailableTierNames(Set availableTierNames) { this.availableTierNames = availableTierNames; } + + public Set getAvailableTiersForOrganizations() { + return availableTiersForOrganizations; + } + + public void setAvailableTiersForOrganizations(Set availableTiersForOrganizations) { + this.availableTiersForOrganizations = availableTiersForOrganizations; + } + + public void setAvailableTiersForOrganizationsFromString(String tiersString) { + + if (tiersString == null || tiersString.isEmpty()) { + return; + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + org.wso2.carbon.apimgt.api.model.OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, + org.wso2.carbon.apimgt.api.model.OrganizationTiers[].class); + for (org.wso2.carbon.apimgt.api.model.OrganizationTiers organizationTiersToMap : tiersArray) { + OrganizationTiers organizationTiers = getOrganizationTiers(organizationTiersToMap); + availableTiersForOrganizations.add(organizationTiers); + } + } catch (Exception e) { + log.error("Error while converting string to availableTiersForOrganizations object for API : " + getId(), + e); + } + } + + private static OrganizationTiers getOrganizationTiers( + org.wso2.carbon.apimgt.api.model.OrganizationTiers organizationTiersToMap) { + + OrganizationTiers organizationTiers = new OrganizationTiers(); + organizationTiers.setOrganizationID(organizationTiersToMap.getOrganizationID()); + organizationTiers.setOrganizationName(organizationTiersToMap.getOrganizationName()); + Set tiersToMap = organizationTiersToMap.getTiers(); + Set tiers = new LinkedHashSet<>(); + for (Tier tierToMap : tiersToMap) { + tiers.add(tierToMap.getName()); + } + organizationTiers.setTiers(tiers); + return organizationTiers; + } + public String getSubscriptionAvailableOrgs() { return subscriptionAvailableOrgs; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java index cba7452931b7..629b440c501d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/OrganizationTiers.java @@ -47,4 +47,8 @@ public Set getTiers() { public void setTiers(Set tiers) { this.tiers = tiers; } + + public void removeAllTiers() { + tiers.clear(); + } } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 3901ac862886..6a652e0e8556 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1187,6 +1187,11 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); } + if (!api.isAPIProduct()) { + org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils + .updateAvailableTiersByOrganization(api.getApi(), userOrg); + } + // Extracting clicked API name by the user, for the recommendation system apiConsumer.publishClickedAPI(api, userName, organization); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java index 2ff61d2bfc26..128e95344db1 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java @@ -36,6 +36,7 @@ import org.wso2.carbon.apimgt.api.model.ApiTypeWrapper; import org.wso2.carbon.apimgt.api.model.Application; import org.wso2.carbon.apimgt.api.model.Monetization; +import org.wso2.carbon.apimgt.api.model.OrganizationInfo; import org.wso2.carbon.apimgt.api.model.SubscribedAPI; import org.wso2.carbon.apimgt.api.model.Subscriber; import org.wso2.carbon.apimgt.api.model.SubscriptionResponse; @@ -230,6 +231,12 @@ public Response subscriptionsPost(SubscriptionDTO body, String xWSO2Tenant, Mess ApiTypeWrapper apiTypeWrapper = apiConsumer.getAPIorAPIProductByUUID(body.getApiId(), organization); + OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); + userOrgInfo.setSuperOrganization(organization); + if (!apiTypeWrapper.isAPIProduct()) { + org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils + .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), userOrgInfo.getOrganizationId()); + } apiTypeWrapper.setTier(body.getThrottlingPolicy()); @@ -342,6 +349,12 @@ public Response subscriptionsSubscriptionIdPut(String subscriptionId, Subscripti ApiTypeWrapper apiTypeWrapper = apiConsumer.getAPIorAPIProductByUUID(body.getApiId(), organization); + OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); + userOrgInfo.setSuperOrganization(organization); + if (!apiTypeWrapper.isAPIProduct()) { + org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils + .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), userOrgInfo.getOrganizationId()); + } apiTypeWrapper.setTier(body.getThrottlingPolicy()); @@ -427,6 +440,12 @@ public Response subscriptionsMultiplePost(List body, String xWS ApiTypeWrapper apiTypeWrapper = apiConsumer.getAPIorAPIProductByUUID(subscriptionDTO.getApiId(), organization); + OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); + userOrgInfo.setSuperOrganization(organization); + if (!apiTypeWrapper.isAPIProduct()) { + org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( + apiTypeWrapper.getApi(), userOrgInfo.getOrganizationId()); + } apiTypeWrapper.setTier(subscriptionDTO.getThrottlingPolicy()); SubscriptionResponse subscriptionResponse = apiConsumer .addSubscription(apiTypeWrapper, username, application); diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java index 09b5f28fc1d5..b7054d018495 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java @@ -23,6 +23,8 @@ import org.wso2.carbon.apimgt.api.dto.KeyManagerConfigurationDTO; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.APIProduct; +import org.wso2.carbon.apimgt.api.model.OrganizationTiers; +import org.wso2.carbon.apimgt.api.model.Tier; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.api.model.Environment; import org.wso2.carbon.apimgt.api.model.OrganizationInfo; @@ -218,4 +220,21 @@ public static List filterAllowedKeyManagersForOrgani return allowedList; } + +public static void updateAvailableTiersByOrganization(API api, String organization) { + + Set availableTiers = api.getAvailableTiers(); + Set availableTiersForOrganizations = api.getAvailableTiersForOrganizations(); + if (organization != null) { + for (OrganizationTiers organizationTiers : availableTiersForOrganizations) { + String orgName = organizationTiers.getOrganizationID(); + if (organization.equals(orgName)) { + availableTiers = organizationTiers.getTiers(); + break; + } + } + } + api.removeAllTiers(); + api.setAvailableTiers(availableTiers); +} } From abab480ae4c590be462c79cab420977b12f4619a Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Thu, 30 Jan 2025 21:59:45 +0530 Subject: [PATCH 68/74] Fix unit test failures --- .../src/main/java/org/wso2/carbon/apimgt/api/model/API.java | 2 +- .../src/test/java/APIMappingUtilTest.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java index 9997a8a91f6e..bc2d8acc6173 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java @@ -769,7 +769,7 @@ public void removeAllPolicies() { } public Set getAvailableTiersForOrganizations() { - return Collections.unmodifiableSet(availableTiersForOrganizations); + return availableTiersForOrganizations; } public void setAvailableTiersForOrganizations(Set availableTiersForOrganizations) { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/test/java/APIMappingUtilTest.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/test/java/APIMappingUtilTest.java index a249ab3ba57a..4bc2affe0974 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/test/java/APIMappingUtilTest.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher.v1.common/src/test/java/APIMappingUtilTest.java @@ -30,6 +30,7 @@ import org.wso2.carbon.apimgt.impl.APIManagerConfiguration; import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; import org.wso2.carbon.apimgt.impl.APIManagerConfigurationServiceImpl; +import org.wso2.carbon.apimgt.impl.dto.OrgAccessControl; import org.wso2.carbon.apimgt.impl.internal.ServiceReferenceHolder; import org.wso2.carbon.apimgt.rest.api.publisher.v1.common.mappings.APIMappingUtil; import org.wso2.carbon.apimgt.rest.api.publisher.v1.dto.APIDTO; @@ -74,6 +75,7 @@ public void setup() { apidto.setOperations(operationList); apidto.setLifeCycleStatus(APIConstants.CREATED); config = Mockito.mock(APIManagerConfiguration.class); + OrgAccessControl orgAccessControl = Mockito.mock(OrgAccessControl.class); APIManagerConfigurationService apiManagerConfigurationService = new APIManagerConfigurationServiceImpl(config); ServiceReferenceHolder.getInstance().setAPIManagerConfigurationService(apiManagerConfigurationService); APIManagerConfiguration config = ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService() @@ -84,6 +86,8 @@ public void setup() { .thenReturn(ALLOW_METHOD); Mockito.when(config.getFirstProperty(APIConstants.CORS_CONFIGURATION_ACCESS_CTL_ALLOW_ORIGIN)) .thenReturn(ALLOW_ORIGIN); + Mockito.when(config.getOrgAccessControl()).thenReturn(orgAccessControl); + Mockito.when(orgAccessControl.isEnabled()).thenReturn(false); } @Test From 31e2c8b3e5544d7e2ac6fa59fb5c05b4d592af11 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Thu, 30 Jan 2025 22:21:38 +0530 Subject: [PATCH 69/74] Refactor code --- .../apimgt/api/model/OrganizationTiers.java | 2 +- .../carbon/apimgt/impl/APIConsumerImpl.java | 3 +- .../carbon/apimgt/impl/utils/APIUtil.java | 5 +++ .../persistence/dto/DevPortalAPIInfo.java | 2 -- .../rest/api/store/v1/utils/APIUtils.java | 31 +++++++++++-------- 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java index e280c330e569..fd602604eb47 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/OrganizationTiers.java @@ -20,7 +20,7 @@ import java.util.Set; /** - * This class represent the Tier + * This class represent Organization Tiers */ public class OrganizationTiers { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index dd7383590c54..7e94b505fd8a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -4049,7 +4049,8 @@ private API addTiersToAPI(API api, String organization) throws APIManagementExce Set organizationTiersSet = api.getAvailableTiersForOrganizations(); for (OrganizationTiers organizationTiers : organizationTiersSet) { Set tierNamesForOrganization = organizationTiers.getTiers(); - Set availableTiersForOrganization = getAvailableTiers(tierNamesForOrganization, deniedTiers, definedTiers); + Set availableTiersForOrganization = getAvailableTiers(tierNamesForOrganization, deniedTiers, + definedTiers); organizationTiers.removeAllTiers(); organizationTiers.setTiers(availableTiersForOrganization); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index ecc045df1305..386e5ded55e3 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -3598,6 +3598,11 @@ public static float getAverageRating(int apiId) throws APIManagementException { return ApiMgtDAO.getInstance().getAverageRating(apiId); } + /** + * Update available tiers in the DevPortalAPIInfo according to the organization. + * @param devPortalAPIInfo DevPortalAPIInfo object + * @param organization Organization ID + */ public static void updateAvailableTiersByOrganization(DevPortalAPIInfo devPortalAPIInfo, String organization) { Set availableTiers = devPortalAPIInfo.getAvailableTierNames(); diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java index aface03db92d..aab9f6562622 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java @@ -18,10 +18,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.Tier; -import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java index b7054d018495..728ec19853f8 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java @@ -221,20 +221,25 @@ public static List filterAllowedKeyManagersForOrgani return allowedList; } -public static void updateAvailableTiersByOrganization(API api, String organization) { - - Set availableTiers = api.getAvailableTiers(); - Set availableTiersForOrganizations = api.getAvailableTiersForOrganizations(); - if (organization != null) { - for (OrganizationTiers organizationTiers : availableTiersForOrganizations) { - String orgName = organizationTiers.getOrganizationID(); - if (organization.equals(orgName)) { - availableTiers = organizationTiers.getTiers(); - break; + /** + * Update available tiers in the API according to the organization. + * @param api API object + * @param organization Organization name + */ + public static void updateAvailableTiersByOrganization(API api, String organization) { + + Set availableTiers = api.getAvailableTiers(); + Set availableTiersForOrganizations = api.getAvailableTiersForOrganizations(); + if (organization != null) { + for (OrganizationTiers organizationTiers : availableTiersForOrganizations) { + String orgName = organizationTiers.getOrganizationID(); + if (organization.equals(orgName)) { + availableTiers = organizationTiers.getTiers(); + break; + } } } + api.removeAllTiers(); + api.setAvailableTiers(availableTiers); } - api.removeAllTiers(); - api.setAvailableTiers(availableTiers); -} } From b2b4a2ce016ff64911dd6fd276355f5ee1ddb887 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Fri, 31 Jan 2025 17:50:43 +0530 Subject: [PATCH 70/74] Get organization ID from external ID when creating a subscription --- .../wso2/carbon/apimgt/impl/APIConsumerImpl.java | 3 ++- .../org/wso2/carbon/apimgt/impl/utils/APIUtil.java | 4 ++-- .../rest/api/store/v1/impl/ApisApiServiceImpl.java | 6 ++++-- .../store/v1/impl/SubscriptionsApiServiceImpl.java | 13 ++++++++++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 7e94b505fd8a..038f5e1bae45 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -3879,7 +3879,8 @@ private Map searchPaginatedAPIs(String searchQuery, int start, i } String organizationID = null; if (orgInfo != null) { - organizationID = orgInfo.getOrganizationId(); + organizationID = APIUtil.getOrganizationIdFromExternalReference(orgInfo.getOrganizationId(), + orgInfo.getName(), tenantDomain); } try { diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 386e5ded55e3..9bf536e26e80 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -3609,8 +3609,8 @@ public static void updateAvailableTiersByOrganization(DevPortalAPIInfo devPortal Set availableTiersForOrganizations = devPortalAPIInfo.getAvailableTiersForOrganizations(); if (organization != null) { for (OrganizationTiers organizationTiers : availableTiersForOrganizations) { - String orgName = organizationTiers.getOrganizationID(); - if (organization.equals(orgName)) { + String orgID = organizationTiers.getOrganizationID(); + if (organization.equals(orgID)) { availableTiers = organizationTiers.getTiers(); break; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 6a652e0e8556..b7a103a7ca01 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1188,8 +1188,10 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo } if (!api.isAPIProduct()) { - org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils - .updateAvailableTiersByOrganization(api.getApi(), userOrg); + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); + org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( + api.getApi(), organizationID); } // Extracting clicked API name by the user, for the recommendation system diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java index 128e95344db1..fd7fd225e1ae 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java @@ -41,6 +41,7 @@ import org.wso2.carbon.apimgt.api.model.Subscriber; import org.wso2.carbon.apimgt.api.model.SubscriptionResponse; import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.impl.workflow.HttpWorkflowResponse; import org.wso2.carbon.apimgt.rest.api.common.RestApiCommonUtil; import org.wso2.carbon.apimgt.rest.api.common.RestApiConstants; @@ -234,8 +235,10 @@ public Response subscriptionsPost(SubscriptionDTO body, String xWSO2Tenant, Mess OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); if (!apiTypeWrapper.isAPIProduct()) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils - .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), userOrgInfo.getOrganizationId()); + .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), organizationID); } apiTypeWrapper.setTier(body.getThrottlingPolicy()); @@ -352,8 +355,10 @@ public Response subscriptionsSubscriptionIdPut(String subscriptionId, Subscripti OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); if (!apiTypeWrapper.isAPIProduct()) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils - .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), userOrgInfo.getOrganizationId()); + .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), organizationID); } apiTypeWrapper.setTier(body.getThrottlingPolicy()); @@ -443,8 +448,10 @@ public Response subscriptionsMultiplePost(List body, String xWS OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); if (!apiTypeWrapper.isAPIProduct()) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( - apiTypeWrapper.getApi(), userOrgInfo.getOrganizationId()); + apiTypeWrapper.getApi(), organizationID); } apiTypeWrapper.setTier(subscriptionDTO.getThrottlingPolicy()); SubscriptionResponse subscriptionResponse = apiConsumer From 6bf474222b7acde38e41f53c330d4b2967411fc1 Mon Sep 17 00:00:00 2001 From: hisanhunais Date: Mon, 3 Feb 2025 12:26:27 +0530 Subject: [PATCH 71/74] Bump upload-artifact version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8b7bb84f326b..3675664784ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -118,7 +118,7 @@ jobs: run: mv product-apim/modules/integration/tests-integration/tests-backend/target/surefire-reports/TEST-TestSuite.xml TEST-TestSuite_${{ matrix.id }}.xml - name: Archive testng report if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: TEST-TestSuite_${{ matrix.id }} path: | From cc1f9aea69507b8a4af2c0d97f673b648b670efa Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Wed, 5 Feb 2025 11:57:34 +0530 Subject: [PATCH 72/74] Fix null pointer errors in integration tests --- .../carbon/apimgt/impl/APIConsumerImpl.java | 2 +- .../api/store/v1/impl/ApisApiServiceImpl.java | 9 +++++--- .../v1/impl/SubscriptionsApiServiceImpl.java | 21 +++++++++++++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java index 038f5e1bae45..a2e4035c7f60 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/APIConsumerImpl.java @@ -3878,7 +3878,7 @@ private Map searchPaginatedAPIs(String searchQuery, int start, i log.debug("Original search query received : " + searchQuery); } String organizationID = null; - if (orgInfo != null) { + if (orgInfo != null && !StringUtils.isEmpty(orgInfo.getOrganizationId())) { organizationID = APIUtil.getOrganizationIdFromExternalReference(orgInfo.getOrganizationId(), orgInfo.getName(), tenantDomain); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index b7a103a7ca01..5d4ea45fbd5b 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1187,9 +1187,12 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); } - if (!api.isAPIProduct()) { - String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), - userOrgInfo.getName(), organization); + if (!api.isAPIProduct() ) { + String organizationID = null; + if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); + } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( api.getApi(), organizationID); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java index fd7fd225e1ae..7c60aa3cfdbb 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java @@ -235,8 +235,11 @@ public Response subscriptionsPost(SubscriptionDTO body, String xWSO2Tenant, Mess OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); if (!apiTypeWrapper.isAPIProduct()) { - String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), - userOrgInfo.getName(), organization); + String organizationID = null; + if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); + } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), organizationID); } @@ -355,8 +358,11 @@ public Response subscriptionsSubscriptionIdPut(String subscriptionId, Subscripti OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); if (!apiTypeWrapper.isAPIProduct()) { - String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), - userOrgInfo.getName(), organization); + String organizationID = null; + if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); + } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), organizationID); } @@ -448,8 +454,11 @@ public Response subscriptionsMultiplePost(List body, String xWS OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); if (!apiTypeWrapper.isAPIProduct()) { - String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), - userOrgInfo.getName(), organization); + String organizationID = null; + if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + userOrgInfo.getName(), organization); + } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( apiTypeWrapper.getApi(), organizationID); } From 192f8ff3fa03fdf0bcff76ff4b6bc741c9a78628 Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Wed, 5 Feb 2025 16:33:13 +0530 Subject: [PATCH 73/74] Fix integration test failures --- .../carbon/apimgt/impl/utils/APIUtil.java | 2 +- .../api/store/v1/impl/ApisApiServiceImpl.java | 7 ++----- .../v1/impl/SubscriptionsApiServiceImpl.java | 21 ++++++------------- .../rest/api/store/v1/utils/APIUtils.java | 4 ++-- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 4b554bc8b38a..7afb139e2c1d 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -3630,11 +3630,11 @@ public static void updateAvailableTiersByOrganization(DevPortalAPIInfo devPortal String orgID = organizationTiers.getOrganizationID(); if (organization.equals(orgID)) { availableTiers = organizationTiers.getTiers(); + devPortalAPIInfo.setAvailableTierNames(availableTiers); break; } } } - devPortalAPIInfo.setAvailableTierNames(availableTiers); } public static List getAllTenantsWithSuperTenant() throws UserStoreException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java index 5d4ea45fbd5b..46edb720d032 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/ApisApiServiceImpl.java @@ -1187,12 +1187,9 @@ private APIDTO getAPIByAPIId(String apiId, String organization, OrganizationInfo RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_API, apiId, log); } - if (!api.isAPIProduct() ) { - String organizationID = null; - if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { - organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + if (!api.isAPIProduct() && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), userOrgInfo.getName(), organization); - } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( api.getApi(), organizationID); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java index 7c60aa3cfdbb..63fe871e947a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/impl/SubscriptionsApiServiceImpl.java @@ -234,12 +234,9 @@ public Response subscriptionsPost(SubscriptionDTO body, String xWSO2Tenant, Mess OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); - if (!apiTypeWrapper.isAPIProduct()) { - String organizationID = null; - if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { - organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + if (!apiTypeWrapper.isAPIProduct() && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), userOrgInfo.getName(), organization); - } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), organizationID); } @@ -357,12 +354,9 @@ public Response subscriptionsSubscriptionIdPut(String subscriptionId, Subscripti OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); - if (!apiTypeWrapper.isAPIProduct()) { - String organizationID = null; - if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { - organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + if (!apiTypeWrapper.isAPIProduct() && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), userOrgInfo.getName(), organization); - } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils .updateAvailableTiersByOrganization(apiTypeWrapper.getApi(), organizationID); } @@ -453,12 +447,9 @@ public Response subscriptionsMultiplePost(List body, String xWS OrganizationInfo userOrgInfo = RestApiUtil.getOrganizationInfo(messageContext); userOrgInfo.setSuperOrganization(organization); - if (!apiTypeWrapper.isAPIProduct()) { - String organizationID = null; - if (userOrgInfo != null && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { - organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), + if (!apiTypeWrapper.isAPIProduct() && !StringUtils.isEmpty(userOrgInfo.getOrganizationId())) { + String organizationID = APIUtil.getOrganizationIdFromExternalReference(userOrgInfo.getOrganizationId(), userOrgInfo.getName(), organization); - } org.wso2.carbon.apimgt.rest.api.store.v1.utils.APIUtils.updateAvailableTiersByOrganization( apiTypeWrapper.getApi(), organizationID); } diff --git a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java index 728ec19853f8..eb67425e3c79 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java +++ b/components/apimgt/org.wso2.carbon.apimgt.rest.api.store.v1/src/main/java/org/wso2/carbon/apimgt/rest/api/store/v1/utils/APIUtils.java @@ -235,11 +235,11 @@ public static void updateAvailableTiersByOrganization(API api, String organizati String orgName = organizationTiers.getOrganizationID(); if (organization.equals(orgName)) { availableTiers = organizationTiers.getTiers(); + api.removeAllTiers(); + api.setAvailableTiers(availableTiers); break; } } } - api.removeAllTiers(); - api.setAvailableTiers(availableTiers); } } From 2cb34e6486c77a7e04cd604324e775a311bf2d6d Mon Sep 17 00:00:00 2001 From: Savindu Dimal Date: Thu, 6 Feb 2025 11:57:03 +0530 Subject: [PATCH 74/74] Refactor code Remove logical methods from model classes and move them to util classes --- .../org/wso2/carbon/apimgt/api/model/API.java | 32 ------ .../carbon/apimgt/impl/utils/APIUtil.java | 59 +++++++++- .../persistence/RegistryPersistenceImpl.java | 3 +- .../persistence/dto/DevPortalAPIInfo.java | 36 ------ .../utils/RegistryPersistenceUtil.java | 105 +++++++++++++++++- 5 files changed, 158 insertions(+), 77 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java index bc2d8acc6173..bd96b8829408 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java +++ b/components/apimgt/org.wso2.carbon.apimgt.api/src/main/java/org/wso2/carbon/apimgt/api/model/API.java @@ -30,7 +30,6 @@ import java.io.Serializable; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; @@ -780,37 +779,6 @@ public void removeAllTiersForOrganizations() { availableTiersForOrganizations.clear(); } - public void setAvailableTiersForOrganizationsFromString(String tiersString) { - - if (tiersString == null || tiersString.isEmpty()) { - return; - } - try { - ObjectMapper objectMapper = new ObjectMapper(); - OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, OrganizationTiers[].class); - availableTiersForOrganizations = new LinkedHashSet<>(Arrays.asList(tiersArray)); - } catch (Exception e) { - log.error("Error while converting string to availableTiersForOrganizations object for API : " + getUUID(), - e); - } - } - - public String getAvailableTiersForOrganizationsAsString() { - if (availableTiersForOrganizations == null || availableTiersForOrganizations.isEmpty()) { - return null; - } - try { - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.writeValueAsString(availableTiersForOrganizations); - } catch (JsonProcessingException e) { - log.error("Error while converting availableTiersForOrganizations to string for API : " + getUUID(), e); - return null; - } catch (Exception e) { - log.error("Unexpected error while processing availableTiersForOrganizations for API : " + getUUID(), e); - return null; - } - } - public Set getUriTemplates() { return uriTemplates; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java index 7afb139e2c1d..e41c6a82293f 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/utils/APIUtil.java @@ -18,6 +18,7 @@ package org.wso2.carbon.apimgt.impl.utils; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -696,7 +697,7 @@ public static API getAPI(GovernanceArtifact artifact) // Set available tiers for organizations String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); - api.setAvailableTiersForOrganizationsFromString(organizationTiers); + api.setAvailableTiersForOrganizations(getAvailableTiersForOrganizationsFromString(organizationTiers)); api.addAvailableTiers(availablePolicy); String tenantDomainName = MultitenantUtils.getTenantDomain(replaceEmailDomainBack(providerName)); @@ -825,7 +826,7 @@ public static API getLightWeightAPI(GovernanceArtifact artifact) // Set available tiers for organizations String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); - api.setAvailableTiersForOrganizationsFromString(organizationTiers); + api.setAvailableTiersForOrganizations(getAvailableTiersForOrganizationsFromString(organizationTiers)); String tenantDomainName = MultitenantUtils.getTenantDomain(replaceEmailDomainBack(providerName)); api.setMonetizationCategory(getAPIMonetizationCategory(availablePolicy, tenantDomainName)); @@ -1006,9 +1007,9 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_TIER, tiers); } - if (api.getAvailableTiersForOrganizationsAsString() != null) { + if (getAvailableTiersForOrganizationsAsString(api) != null) { artifact.setAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS, - api.getAvailableTiersForOrganizationsAsString()); + getAvailableTiersForOrganizationsAsString(api)); } if (APIConstants.PUBLISHED.equals(apiStatus)) { @@ -2742,7 +2743,7 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry, APIIden // Set available tiers for organizations String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); - api.setAvailableTiersForOrganizationsFromString(organizationTiers); + api.setAvailableTiersForOrganizations(getAvailableTiersForOrganizationsFromString(organizationTiers)); api.setContext(artifact.getAttribute(APIConstants.API_OVERVIEW_CONTEXT)); api.setContextTemplate(artifact.getAttribute(APIConstants.API_OVERVIEW_CONTEXT_TEMPLATE)); @@ -11192,6 +11193,54 @@ public static Boolean isOrgWideAppUpdateEnabled() { return Boolean.getBoolean( APIConstants.ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED); } + + /** + * Get available tiers for organizations as a string. + * + * @param api API object + * @return String object of the organization based tiers + */ + private static String getAvailableTiersForOrganizationsAsString(API api) { + + Set availableTiersForOrganizations + = api.getAvailableTiersForOrganizations(); + if (availableTiersForOrganizations == null || availableTiersForOrganizations.isEmpty()) { + return null; + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(availableTiersForOrganizations); + } catch (JsonProcessingException e) { + log.error("Error while converting availableTiersForOrganizations to string for API : " + api.getUuid(), e); + return null; + } catch (Exception e) { + log.error("Unexpected error while processing availableTiersForOrganizations for API : " + api.getUuid(), e); + return null; + } + } + + /** + * Convert string object to a OrganizationTiers set. + * + * @param tiersString String object to be converted + * @return OrganziationTiers set + */ + public static Set getAvailableTiersForOrganizationsFromString( + String tiersString) { + + if (tiersString == null || tiersString.isEmpty()) { + return new LinkedHashSet<>(); + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + org.wso2.carbon.apimgt.api.model.OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, + org.wso2.carbon.apimgt.api.model.OrganizationTiers[].class); + return new LinkedHashSet<>(Arrays.asList(tiersArray)); + } catch (Exception e) { + log.error("Error while converting string to availableTiersForOrganizations object", e); + return new LinkedHashSet<>(); + } + } public static String getOrganizationIdFromExternalReference(String referenceId, String organizationName, String rootOrganization) throws APIManagementException { diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java index 77c057fd577f..61472cbcd43a 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/RegistryPersistenceImpl.java @@ -1294,7 +1294,8 @@ private DevPortalAPISearchResult searchPaginatedDevPortalAPIs(Registry userRegis apiInfo.setAvailableTierNames(availableTiers); // Set available tiers for organizations String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); - apiInfo.setAvailableTiersForOrganizationsFromString(organizationTiers); + apiInfo.setAvailableTiersForOrganizations( + RegistryPersistenceUtil.getOrganizationTiersFromString(organizationTiers)); apiInfo.setSubscriptionAvailability( artifact.getAttribute(APIConstants.API_OVERVIEW_SUBSCRIPTION_AVAILABILITY)); apiInfo.setSubscriptionAvailableOrgs( diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java index aab9f6562622..ab984ec69ccd 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/dto/DevPortalAPIInfo.java @@ -15,10 +15,8 @@ */ package org.wso2.carbon.apimgt.persistence.dto; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.apimgt.api.model.Tier; import java.util.LinkedHashSet; import java.util.Map; @@ -148,40 +146,6 @@ public void setAvailableTiersForOrganizations(Set availableTi this.availableTiersForOrganizations = availableTiersForOrganizations; } - public void setAvailableTiersForOrganizationsFromString(String tiersString) { - - if (tiersString == null || tiersString.isEmpty()) { - return; - } - try { - ObjectMapper objectMapper = new ObjectMapper(); - org.wso2.carbon.apimgt.api.model.OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, - org.wso2.carbon.apimgt.api.model.OrganizationTiers[].class); - for (org.wso2.carbon.apimgt.api.model.OrganizationTiers organizationTiersToMap : tiersArray) { - OrganizationTiers organizationTiers = getOrganizationTiers(organizationTiersToMap); - availableTiersForOrganizations.add(organizationTiers); - } - } catch (Exception e) { - log.error("Error while converting string to availableTiersForOrganizations object for API : " + getId(), - e); - } - } - - private static OrganizationTiers getOrganizationTiers( - org.wso2.carbon.apimgt.api.model.OrganizationTiers organizationTiersToMap) { - - OrganizationTiers organizationTiers = new OrganizationTiers(); - organizationTiers.setOrganizationID(organizationTiersToMap.getOrganizationID()); - organizationTiers.setOrganizationName(organizationTiersToMap.getOrganizationName()); - Set tiersToMap = organizationTiersToMap.getTiers(); - Set tiers = new LinkedHashSet<>(); - for (Tier tierToMap : tiersToMap) { - tiers.add(tierToMap.getName()); - } - organizationTiers.setTiers(tiers); - return organizationTiers; - } - public String getSubscriptionAvailableOrgs() { return subscriptionAvailableOrgs; } diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index 97c072c1142b..c0a35656576e 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -16,6 +16,8 @@ package org.wso2.carbon.apimgt.persistence.utils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import org.apache.axis2.context.ConfigurationContext; import org.apache.commons.lang3.ArrayUtils; @@ -40,6 +42,7 @@ import org.wso2.carbon.apimgt.api.model.URITemplate; import org.wso2.carbon.apimgt.persistence.APIConstants; import org.wso2.carbon.apimgt.persistence.dto.DevPortalAPI; +import org.wso2.carbon.apimgt.persistence.dto.OrganizationTiers; import org.wso2.carbon.apimgt.persistence.dto.PublisherAPI; import org.wso2.carbon.apimgt.persistence.exceptions.APIPersistenceException; import org.wso2.carbon.apimgt.persistence.exceptions.PersistenceException; @@ -85,6 +88,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; @@ -259,9 +263,9 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, artifact.setAttribute(APIConstants.API_OVERVIEW_TIER, tiers); } - if (api.getAvailableTiersForOrganizationsAsString() != null) { + if (getAvailableTiersForOrganizationsAsString(api) != null) { artifact.setAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS, - api.getAvailableTiersForOrganizationsAsString()); + getAvailableTiersForOrganizationsAsString(api)); } if (APIConstants.PUBLISHED.equals(apiStatus)) { @@ -343,6 +347,101 @@ public static GenericArtifact createAPIArtifactContent(GenericArtifact artifact, return artifact; } + /** + * Get available tiers for organizations as a string. + * + * @param api API object + * @return String object of the organization based tiers + */ + private static String getAvailableTiersForOrganizationsAsString(API api) { + + Set availableTiersForOrganizations + = api.getAvailableTiersForOrganizations(); + if (availableTiersForOrganizations == null || availableTiersForOrganizations.isEmpty()) { + return null; + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.writeValueAsString(availableTiersForOrganizations); + } catch (JsonProcessingException e) { + log.error("Error while converting availableTiersForOrganizations to string for API : " + api.getUuid(), e); + return null; + } catch (Exception e) { + log.error("Unexpected error while processing availableTiersForOrganizations for API : " + api.getUuid(), e); + return null; + } + } + + /** + * Convert string object to an org.wso2.carbon.apimgt.api.model.OrganizationTiers set. + * + * @param tiersString String object to be converted + * @return OrganziationTiers set + */ + public static Set getAvailableTiersForOrganizationsFromString( + String tiersString) { + + if (tiersString == null || tiersString.isEmpty()) { + return new LinkedHashSet<>(); + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + org.wso2.carbon.apimgt.api.model.OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, + org.wso2.carbon.apimgt.api.model.OrganizationTiers[].class); + return new LinkedHashSet<>(Arrays.asList(tiersArray)); + } catch (Exception e) { + log.error("Error while converting string to availableTiersForOrganizations object", e); + return new LinkedHashSet<>(); + } + } + + /** + * Convert string object to an org.wso2.carbon.apimgt.persistence.dto.OrganizationTiers set. + * + * @param tiersString String object to be converted + * @return OrganziationTiers set + */ + public static Set getOrganizationTiersFromString(String tiersString) { + + Set availableTiersForOrganizations = new LinkedHashSet<>();; + if (tiersString == null || tiersString.isEmpty()) { + return availableTiersForOrganizations; + } + try { + ObjectMapper objectMapper = new ObjectMapper(); + org.wso2.carbon.apimgt.api.model.OrganizationTiers[] tiersArray = objectMapper.readValue(tiersString, + org.wso2.carbon.apimgt.api.model.OrganizationTiers[].class); + for (org.wso2.carbon.apimgt.api.model.OrganizationTiers organizationTiersToMap : tiersArray) { + OrganizationTiers organizationTiers = getOrganizationTiers(organizationTiersToMap); + availableTiersForOrganizations.add(organizationTiers); + } + } catch (Exception e) { + log.error("Error while converting string to OrganizationTiers set.", e); + } + return availableTiersForOrganizations; + } + + /** + * Map org.wso2.carbon.apimgt.api.model.OrganizationTiers to org.wso2.carbon.apimgt.persistence.dto.OrganizationTiers + * + * @param organizationTiersToMap org.wso2.carbon.apimgt.api.model.OrganizationTiers object + * @return org.wso2.carbon.apimgt.persistence.dto.OrganizationTiers object + */ + private static OrganizationTiers getOrganizationTiers( + org.wso2.carbon.apimgt.api.model.OrganizationTiers organizationTiersToMap) { + + OrganizationTiers organizationTiers = new OrganizationTiers(); + organizationTiers.setOrganizationID(organizationTiersToMap.getOrganizationID()); + organizationTiers.setOrganizationName(organizationTiersToMap.getOrganizationName()); + Set tiersToMap = organizationTiersToMap.getTiers(); + Set tiers = new LinkedHashSet<>(); + for (Tier tierToMap : tiersToMap) { + tiers.add(tierToMap.getName()); + } + organizationTiers.setTiers(tiers); + return organizationTiers; + } + private static String getWsUriMappingJsonFromDto(Map wsUriMapping) { return new Gson().toJson(wsUriMapping); } @@ -745,7 +844,7 @@ public static API getAPI(GovernanceArtifact artifact, Registry registry) // Set available tiers for organizations String organizationTiers = artifact.getAttribute(APIConstants.API_OVERVIEW_ORGANIZATION_TIERS); - api.setAvailableTiersForOrganizationsFromString(organizationTiers); + api.setAvailableTiersForOrganizations(getAvailableTiersForOrganizationsFromString(organizationTiers)); // This contains the resolved context api.setContext(artifact.getAttribute(APIConstants.API_OVERVIEW_CONTEXT));