From 18fab8e18674b6bacbb0e134001274ac957f43c4 Mon Sep 17 00:00:00 2001 From: YasasRangika Date: Thu, 2 Jan 2025 11:30:18 +0530 Subject: [PATCH] Add support for org-wide application update --- .../wso2/carbon/apimgt/impl/APIConstants.java | 3 +++ .../carbon/apimgt/impl/APIConsumerImpl.java | 10 ++++---- .../carbon/apimgt/impl/utils/APIUtil.java | 16 +++++++++++++ .../src/main/resources/devportal-api.yaml | 3 +++ .../rest/api/store/v1/dto/SettingsDTO.java | 24 +++++++++++++++++-- .../v1/impl/ApplicationsApiServiceImpl.java | 16 +++++++------ .../v1/mappings/SettingsMappingUtil.java | 1 + .../src/main/resources/devportal-api.yaml | 3 +++ 8 files changed, 63 insertions(+), 13 deletions(-) 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 781edede2efd..d4ea0983095e 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 @@ -3257,4 +3257,7 @@ public static class TransactionCounter { public static final String TRANSACTIONCOUNTER = "TransactionCounter"; public static final String COUNTER_ENABLED = "Enabled"; } + + //Property for enabling application update capabilities for users in the same organization. + public static final String ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED = "orgWideAppUpdateEnabled"; } 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 24c4c60ba85e..7f212b1bd96f 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 @@ -215,6 +215,8 @@ public class APIConsumerImpl extends AbstractAPIManager implements APIConsumer { private final Object tagCacheMutex = new Object(); protected String userNameWithoutChange; + boolean orgWideAppUpdateEnabled = Boolean.getBoolean(APIConstants.ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED); + public APIConsumerImpl() throws APIManagementException { super(); @@ -1790,7 +1792,7 @@ public void updateApplication(Application application) throws APIManagementExcep isUserAppOwner = application.getSubscriber().getName().equals(existingApp.getSubscriber().getName()); } - if (!isUserAppOwner) { + if (!orgWideAppUpdateEnabled && !isUserAppOwner) { throw new APIManagementException("user: " + application.getSubscriber().getName() + ", " + "attempted to update application owned by: " + existingApp.getSubscriber().getName()); } @@ -1982,7 +1984,7 @@ public void removeApplication(Application application, String username) throws A isUserAppOwner = application.getSubscriber().getName().equals(username); } - if (!isUserAppOwner) { + if (!orgWideAppUpdateEnabled && !isUserAppOwner) { throw new APIManagementException("user: " + username + ", " + "attempted to remove application owned by: " + application.getSubscriber().getName()); } @@ -2356,7 +2358,7 @@ public Map requestApprovalForApplicationRegistration(String user isUserAppOwner = application.getSubscriber().getName().equals(userId); } - if (!isUserAppOwner) { + if (!orgWideAppUpdateEnabled && !isUserAppOwner) { throw new APIManagementException("user: " + application.getSubscriber().getName() + ", " + "attempted to generate tokens for application owned by: " + userId); } @@ -2856,7 +2858,7 @@ public OAuthApplicationInfo updateAuthClient(String userId, Application applicat isUserAppOwner = subscriberName.equals(userId); } - if (!isUserAppOwner) { + if (!orgWideAppUpdateEnabled && !isUserAppOwner) { throw new APIManagementException("user: " + userId + ", attempted to update OAuth application " + "owned by: " + subscriberName); } 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 fde4b5f08aea..abff565b5ae6 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 @@ -10972,4 +10972,20 @@ public static boolean getTransactionCounterEnable() { return ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService() .getAPIManagerConfiguration().getTransactionCounterProperties(); } + + /** + * Checks if organization-wide application updates are enabled. + *

+ * This method retrieves the value of the system property defined by + * ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED. + * If the property is not set, it returns false by default. + * + * @return {true} if organization-wide application updates are enabled; + * {false} otherwise. + */ + public static Boolean isOrgWideAppUpdateEnabled() { + + return Boolean.getBoolean( + APIConstants.ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED); + } } 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 993819c1a019..c6deac472695 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 @@ -5625,6 +5625,9 @@ components: type: boolean description: Specifies whether Marketplace Assistant feature is enabled. default: true + orgWideAppUpdateEnabled: + type: boolean + default: false ApplicationAttribute: title: Application attributes type: object 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..882d5d655b53 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 @@ -42,6 +42,7 @@ public class SettingsDTO { private Boolean apiChatEnabled = true; private Boolean aiAuthTokenProvided = false; private Boolean marketplaceAssistantEnabled = true; + private Boolean orgWideAppUpdateEnabled = false; /** **/ @@ -374,6 +375,23 @@ public void setMarketplaceAssistantEnabled(Boolean marketplaceAssistantEnabled) this.marketplaceAssistantEnabled = marketplaceAssistantEnabled; } + /** + **/ + public SettingsDTO orgWideAppUpdateEnabled(Boolean orgWideAppUpdateEnabled) { + this.orgWideAppUpdateEnabled = orgWideAppUpdateEnabled; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("orgWideAppUpdateEnabled") + public Boolean isOrgWideAppUpdateEnabled() { + return orgWideAppUpdateEnabled; + } + public void setOrgWideAppUpdateEnabled(Boolean orgWideAppUpdateEnabled) { + this.orgWideAppUpdateEnabled = orgWideAppUpdateEnabled; + } + @Override public boolean equals(java.lang.Object o) { @@ -402,12 +420,13 @@ public boolean equals(java.lang.Object o) { Objects.equals(passwordPolicyMaxLength, settings.passwordPolicyMaxLength) && Objects.equals(apiChatEnabled, settings.apiChatEnabled) && Objects.equals(aiAuthTokenProvided, settings.aiAuthTokenProvided) && - Objects.equals(marketplaceAssistantEnabled, settings.marketplaceAssistantEnabled); + Objects.equals(marketplaceAssistantEnabled, settings.marketplaceAssistantEnabled) && + Objects.equals(orgWideAppUpdateEnabled, settings.orgWideAppUpdateEnabled); } @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, userStorePasswordPattern, passwordPolicyPattern, passwordPolicyMinLength, passwordPolicyMaxLength, apiChatEnabled, aiAuthTokenProvided, marketplaceAssistantEnabled, orgWideAppUpdateEnabled); } @Override @@ -434,6 +453,7 @@ public String toString() { sb.append(" apiChatEnabled: ").append(toIndentedString(apiChatEnabled)).append("\n"); sb.append(" aiAuthTokenProvided: ").append(toIndentedString(aiAuthTokenProvided)).append("\n"); sb.append(" marketplaceAssistantEnabled: ").append(toIndentedString(marketplaceAssistantEnabled)).append("\n"); + sb.append(" orgWideAppUpdateEnabled: ").append(toIndentedString(orgWideAppUpdateEnabled)).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 61b711d67bf3..75909361e693 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 @@ -105,6 +105,7 @@ public class ApplicationsApiServiceImpl implements ApplicationsApiService { private static final Log log = LogFactory.getLog(ApplicationsApiServiceImpl.class); + boolean orgWideAppUpdateEnabled = Boolean.getBoolean(APIConstants.ORGANIZATION_WIDE_APPLICATION_UPDATE_ENABLED); /** * Retrieves all the applications that the user has access to @@ -458,7 +459,7 @@ public Response applicationsApplicationIdPut(String applicationId, ApplicationDT RestApiUtil.handleResourceNotFoundError(RestApiConstants.RESOURCE_APPLICATION, applicationId, log); } - if (!RestAPIStoreUtils.isUserOwnerOfApplication(oldApplication)) { + if (!orgWideAppUpdateEnabled && !RestAPIStoreUtils.isUserOwnerOfApplication(oldApplication)) { RestApiUtil.handleAuthorizationFailure(RestApiConstants.RESOURCE_APPLICATION, applicationId, log); } if (body.getName() != null && !body.getName().equalsIgnoreCase(oldApplication.getName())) { @@ -666,7 +667,7 @@ public Response applicationsApplicationIdApiKeysKeyTypeRevokePost(String applica org.json.JSONObject decodedBody = new org.json.JSONObject( new String(Base64.getUrlDecoder().decode(splitToken[1]))); if (application != null) { - if (RestAPIStoreUtils.isUserOwnerOfApplication(application) + if (orgWideAppUpdateEnabled || RestAPIStoreUtils.isUserOwnerOfApplication(application) || RestAPIStoreUtils.isApplicationSharedtoUser(application)) { if (decodedBody.getJSONObject(APIConstants.JwtTokenConstants.APPLICATION) != null) { org.json.JSONObject appInfo = @@ -749,7 +750,7 @@ public Response applicationsApplicationIdDelete(String applicationId, String ifM APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); Application application = apiConsumer.getLightweightApplicationByUUID(applicationId); if (application != null) { - if (RestAPIStoreUtils.isUserOwnerOfApplication(application)) { + if (orgWideAppUpdateEnabled || RestAPIStoreUtils.isUserOwnerOfApplication(application)) { apiConsumer.removeApplication(application, username); if (APIConstants.ApplicationStatus.DELETE_PENDING.equals(application.getStatus())) { if (application.getId() == -1) { @@ -790,7 +791,7 @@ public Response applicationsApplicationIdGenerateKeysPost(String applicationId, } Application application = apiConsumer.getApplicationByUUID(applicationId); if (application != null) { - if (RestAPIStoreUtils.isUserOwnerOfApplication(application)) { + if (orgWideAppUpdateEnabled || RestAPIStoreUtils.isUserOwnerOfApplication(application)) { String[] accessAllowDomainsArray = {"ALL"}; JSONObject jsonParamObj = new JSONObject(); jsonParamObj.put(ApplicationConstants.OAUTH_CLIENT_USERNAME, username); @@ -1071,7 +1072,7 @@ public Response applicationsApplicationIdKeysKeyTypePut(String applicationId, St APIConsumer apiConsumer = APIManagerFactory.getInstance().getAPIConsumer(username); Application application = apiConsumer.getApplicationByUUID(applicationId); if (application != null) { - if (RestAPIStoreUtils.isUserOwnerOfApplication(application)) { + if (orgWideAppUpdateEnabled || RestAPIStoreUtils.isUserOwnerOfApplication(application)) { String grantTypes = StringUtils.join(body.getSupportedGrantTypes(), ','); JsonObject jsonParams = new JsonObject(); jsonParams.addProperty(APIConstants.JSON_GRANT_TYPES, grantTypes); @@ -1176,7 +1177,7 @@ public Response applicationsApplicationIdMapKeysPost(String applicationId, Appli keyManagerName = body.getKeyManager(); } if (application != null) { - if (RestAPIStoreUtils.isUserOwnerOfApplication(application)) { + if (orgWideAppUpdateEnabled || RestAPIStoreUtils.isUserOwnerOfApplication(application)) { String clientId = body.getConsumerKey(); String keyType = body.getKeyType().toString(); String tokenType = APIConstants.DEFAULT_TOKEN_TYPE; @@ -1353,7 +1354,8 @@ public Response applicationsApplicationIdOauthKeysKeyMappingIdPut(String applica } if (application != null) { ApplicationKeyDTO appKey = getApplicationKeyByAppIDAndKeyMapping(applicationId, keyMappingId); - if (RestAPIStoreUtils.isUserOwnerOfApplication(application) && appKey != null) { + if ((orgWideAppUpdateEnabled || RestAPIStoreUtils.isUserOwnerOfApplication(application)) + && appKey != null) { String grantTypes = StringUtils.join(body.getSupportedGrantTypes(), ','); JsonObject jsonParams = new JsonObject(); jsonParams.addProperty(APIConstants.JSON_GRANT_TYPES, grantTypes); 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 b5206110e7b4..edf37d1a30ad 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 @@ -64,6 +64,7 @@ public SettingsDTO fromSettingstoDTO(Boolean isUserAvailable, Boolean moneatizat settingsDTO.setRecommendationEnabled(recommendationEnabled); settingsDTO.setMapExistingAuthApps(APIUtil.isMapExistingAuthAppsEnabled()); settingsDTO.setMonetizationEnabled(moneatizationEnabled); + settingsDTO.setOrgWideAppUpdateEnabled(APIUtil.isOrgWideAppUpdateEnabled()); SettingsIdentityProviderDTO identityProviderDTO = new SettingsIdentityProviderDTO(); identityProviderDTO.setExternal(APIUtil.getIdentityProviderConfig() != null); settingsDTO.setIdentityProvider(identityProviderDTO); 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 993819c1a019..c6deac472695 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 @@ -5625,6 +5625,9 @@ components: type: boolean description: Specifies whether Marketplace Assistant feature is enabled. default: true + orgWideAppUpdateEnabled: + type: boolean + default: false ApplicationAttribute: title: Application attributes type: object