Performance enhancement for permission updating procedure #268

Open
rajitha wants to merge 3 commits from rajitha/device-mgt-core:performance-enhancement into master

@ -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<String, String> 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<String, String> permScopeMap, boolean removingPermissions )
APIApplicationKey apiApplicationKey, AccessTokenInfo accessTokenInfo, Scope[] scopeList,
String[] permissions, String[] allowedPermissions,
Map<String, String> 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<String> 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);
}
}

@ -724,9 +724,6 @@ 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);
@ -740,7 +737,4 @@ public class RoleManagementServiceImpl implements RoleManagementService {
PrivilegedCarbonContext.endTenantFlow();
}
}
});
thread.start();
}
}

Loading…
Cancel
Save