diff --git a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java index e419bb3751..91500e1cce 100644 --- a/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java +++ b/components/apimgt-extensions/io.entgra.device.mgt.core.apimgt.webapp.publisher/src/main/java/io/entgra/device/mgt/core/apimgt/webapp/publisher/APIPublisherServiceImpl.java @@ -18,7 +18,6 @@ package io.entgra.device.mgt.core.apimgt.webapp.publisher; import com.google.gson.Gson; -import io.entgra.device.mgt.core.apimgt.annotations.Scopes; import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServices; import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationServicesImpl; import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices; @@ -43,7 +42,6 @@ import io.entgra.device.mgt.core.device.mgt.core.config.permission.ScopeMapping; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; import org.json.JSONObject; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.apimgt.api.APIManagementException; @@ -80,6 +78,9 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.Date; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Phaser; /** * This class represents the concrete implementation of the APIPublisherService that corresponds to providing all @@ -98,8 +99,43 @@ public class APIPublisherServiceImpl implements APIPublisherService { public static final String API_GLOBAL_VISIBILITY = "PUBLIC"; public static final String API_PRIVATE_VISIBILITY = "PRIVATE"; private static final String ADMIN_ROLE_KEY = "admin"; - + private static final ExecutorService scopeRoleExecutorService = Executors.newCachedThreadPool(); private static final Log log = LogFactory.getLog(APIPublisherServiceImpl.class); + public static class ScopeUpdaterTask implements Runnable { + private final Phaser phaser; + private final PublisherRESTAPIServices publisherRESTAPIServices; + private final APIApplicationKey apiApplicationKey; + private final AccessTokenInfo accessTokenInfo; + private final Scope scope; + public ScopeUpdaterTask(Phaser phaser, PublisherRESTAPIServices publisherRESTAPIServices, + APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope scope) { + this.phaser = phaser; + this.publisherRESTAPIServices = publisherRESTAPIServices; + this.apiApplicationKey = apiApplicationKey; + this.accessTokenInfo = accessTokenInfo; + this.scope = scope; + } + + @Override + public void run() { + phaser.register(); + try { + if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getName())) { + publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope); + } else { + // todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list + log.warn(scope.getName() + " not available as shared scope"); + } + } catch (Exception e) { + log.info("Error occurred while updating role scope mapping via APIM REST endpoint.", e); + } finally { + if (log.isDebugEnabled()) { + log.debug("Role binding is completed for scope" + scope.getName()); + } + phaser.arriveAndDeregister(); + } + } + } @Override public void publishAPI(APIConfig apiConfig) throws APIManagerPublisherException { @@ -635,18 +671,12 @@ public class APIPublisherServiceImpl implements APIPublisherService { Map permScopeMap = APIPublisherDataHolder.getInstance().getPermScopeMapping(); if (permissions.length != 0) { - updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, permissions, permScopeMap, false); + updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, + permissions, permissions, permScopeMap, false); } if (removedPermissions.length != 0) { - updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, removedPermissions, permScopeMap, true); - } - - try { - updatePermissions(roleName, Arrays.asList(permissions)); - } catch (UserStoreException e) { - String errorMsg = "Error occurred when adding permissions to role: " + roleName; - log.error(errorMsg, e); - throw new APIManagerPublisherException(errorMsg, e); + updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, + removedPermissions, permissions, permScopeMap, true); } } catch (APIServicesException e) { String errorMsg = "Error while processing Publisher REST API response"; @@ -677,9 +707,11 @@ public class APIPublisherServiceImpl implements APIPublisherService { * @throws APIManagerPublisherException If the method receives invalid permission to update. */ private void updateScopes (String roleName, PublisherRESTAPIServices publisherRESTAPIServices, - APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, - Scope[] scopeList, String[] permissions, Map permScopeMap, boolean removingPermissions ) + APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope[] scopeList, + String[] permissions, String[] allowedPermissions, + Map permScopeMap, boolean removingPermissions) throws APIManagerPublisherException { + Phaser phaser = new Phaser(1); for (String permission : permissions) { String scopeValue = permScopeMap.get(permission); if (scopeValue == null) { @@ -714,21 +746,21 @@ public class APIPublisherServiceImpl implements APIPublisherService { } } scope.setBindings(existingRoleList); - - try { - if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getName())) { - publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope); - } else { - // todo: come to this level means, that scope is removed from API, but haven't removed from the scope-role-permission-mappings list - log.warn(scope.getName() + " not available as shared scope"); - } - } catch (APIServicesException | BadRequestException | UnexpectedResponseException e) { - log.error("Error occurred while updating role scope mapping via APIM REST endpoint.", e); - } + scopeRoleExecutorService.submit(new ScopeUpdaterTask(phaser, publisherRESTAPIServices, + apiApplicationKey, accessTokenInfo, scope)); break; } } } + try { + updatePermissions(roleName, Arrays.asList(allowedPermissions)); + } catch (UserStoreException e) { + String errorMsg = "Error occurred when adding permissions to role: " + roleName; + log.error(errorMsg, e); + throw new APIManagerPublisherException(errorMsg, e); + } + phaser.arriveAndAwaitAdvance(); + log.info("Permission and scope updating is successfully completed for role : " + roleName); } private void updatePermissions(String role, List permissions) throws UserStoreException { @@ -741,6 +773,7 @@ public class APIPublisherServiceImpl implements APIPublisherService { authorizationManager.clearRoleAuthorization(role); for (String permission : permissions) { authorizationManager.authorizeRole(role, permission, CarbonConstants.UI_PERMISSION_ACTION); + authorizationManager.refreshAllowedRolesForResource(permission); } } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/RoleManagementServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/RoleManagementServiceImpl.java index 19009bf436..f99cb264e7 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/RoleManagementServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/RoleManagementServiceImpl.java @@ -724,23 +724,17 @@ public class RoleManagementServiceImpl implements RoleManagementService { */ private void updatePermissions(String roleName, RoleInfo roleInfo, UserRealm userRealm) { String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true); - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - try { - PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); - DeviceMgtAPIUtils.getApiPublisher().updateScopeRoleMapping(roleName, - RoleManagementServiceImpl.this.getPlatformUIPermissions(roleName, userRealm, - roleInfo.getPermissions()), RoleManagementServiceImpl.this.getPlatformUIPermissions(roleName, userRealm, - roleInfo.getRemovedPermissions())); - } catch (APIManagerPublisherException | UserAdminException e) { - log.error("Error Occurred while updating role scope mapping. ", e); - } finally { - PrivilegedCarbonContext.endTenantFlow(); - } - } - }); - thread.start(); + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + DeviceMgtAPIUtils.getApiPublisher().updateScopeRoleMapping(roleName, + RoleManagementServiceImpl.this.getPlatformUIPermissions(roleName, userRealm, + roleInfo.getPermissions()), RoleManagementServiceImpl.this.getPlatformUIPermissions(roleName, userRealm, + roleInfo.getRemovedPermissions())); + } catch (APIManagerPublisherException | UserAdminException e) { + log.error("Error Occurred while updating role scope mapping. ", e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } } }