mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Add scope updating improvements
This commit is contained in:
parent
a45820e845
commit
438b7b64af
@ -36,11 +36,16 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIService
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.util.APIPublisherUtils;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.util.SelfSyncingScopeTree;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.config.WebappPublisherConfig;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.dto.ApiScope;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.dto.ApiUriTemplate;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.exception.APIManagerPublisherException;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.exceptions.MetadataManagementException;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.PermissionManagementException;
|
||||
import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager;
|
||||
import io.entgra.device.mgt.core.device.mgt.core.config.DeviceManagementConfig;
|
||||
import io.entgra.device.mgt.core.device.mgt.core.config.permission.DefaultPermission;
|
||||
@ -68,7 +73,6 @@ import org.wso2.carbon.user.core.tenant.Tenant;
|
||||
import org.wso2.carbon.user.core.tenant.TenantSearchResult;
|
||||
import org.wso2.carbon.utils.CarbonUtils;
|
||||
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.permission.mgt.PermissionManagementException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@ -82,9 +86,11 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -570,8 +576,10 @@ public class APIPublisherServiceImpl implements APIPublisherService {
|
||||
scope.setName(
|
||||
scopeMapping[2] != null ? StringUtils.trim(scopeMapping[2]) : StringUtils.EMPTY);
|
||||
// scope.setPermissions(
|
||||
// scopeMapping[3] != null ? StringUtils.trim(scopeMapping[3]) : StringUtils.EMPTY);
|
||||
String permission = scopeMapping[3] != null ? StringUtils.trim(scopeMapping[3]) : StringUtils.EMPTY;
|
||||
// scopeMapping[3] != null ? StringUtils.trim
|
||||
// (scopeMapping[3]) : StringUtils.EMPTY);
|
||||
String permission = scopeMapping[3] != null ? StringUtils.trim(scopeMapping[3]) :
|
||||
StringUtils.EMPTY;
|
||||
|
||||
List<String> rolesList = new ArrayList<>();
|
||||
for (int i = 4; i < scopeMapping.length; i++) {
|
||||
@ -586,7 +594,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
|
||||
Scope[] scopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
|
||||
for (int i = 0; i < scopes.length; i++) {
|
||||
Scope relatedScope = scopes[i];
|
||||
if (relatedScope.getName().equals(scopeMapping[2].toString())) {
|
||||
if (relatedScope.getName().equals(scopeMapping[2])) {
|
||||
scope.setId(relatedScope.getId());
|
||||
scope.setUsageCount(relatedScope.getUsageCount());
|
||||
//Including already existing roles
|
||||
@ -595,7 +603,8 @@ public class APIPublisherServiceImpl implements APIPublisherService {
|
||||
}
|
||||
scope.setBindings(rolesList);
|
||||
|
||||
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo, scope.getName())) {
|
||||
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
|
||||
scope.getName())) {
|
||||
publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope);
|
||||
// todo: permission changed in update path, is not handled yet.
|
||||
} else {
|
||||
@ -642,11 +651,94 @@ public class APIPublisherServiceImpl implements APIPublisherService {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized private SelfSyncingScopeTree getSyncTree(APIApplicationKey apiApplicationKey,
|
||||
AccessTokenInfo accessTokenInfo)
|
||||
throws APIManagerPublisherException {
|
||||
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||
SelfSyncingScopeTree selfSyncingScopeTree =
|
||||
APIPublisherDataHolder.getInstance().getSelfSyncTrees().get(tenantDomain);
|
||||
try {
|
||||
if (selfSyncingScopeTree == null) {
|
||||
Metadata metadata;
|
||||
try {
|
||||
PrivilegedCarbonContext.startTenantFlow();
|
||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(MultitenantConstants
|
||||
.SUPER_TENANT_DOMAIN_NAME, true);
|
||||
MetadataManagementService metadataManagementService =
|
||||
APIPublisherDataHolder.getInstance().getMetadataManagementService();
|
||||
metadata = metadataManagementService.retrieveMetadata(Constants.PERM_SCOPE_MAPPING_META_KEY);
|
||||
} finally {
|
||||
PrivilegedCarbonContext.endTenantFlow();
|
||||
}
|
||||
|
||||
if (metadata == null) {
|
||||
String msg = "Metadata registry service doesn't contains the required metadata for " +
|
||||
Constants.PERM_SCOPE_MAPPING_META_KEY;
|
||||
log.error(msg);
|
||||
throw new APIManagerPublisherException(msg);
|
||||
}
|
||||
|
||||
// interchange the keys and values (this has to be done form the bringing
|
||||
Map<String, String> permScopeMap = gson.fromJson(metadata.getMetaValue(), HashMap.class);
|
||||
|
||||
Map<String, String> scopePermMap = new HashMap<>();
|
||||
for (String permission: permScopeMap.keySet()) {
|
||||
scopePermMap.put(permScopeMap.get(permission), permission);
|
||||
}
|
||||
|
||||
PublisherRESTAPIServices publisherRESTAPIServices =
|
||||
APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices();
|
||||
Scope[] scopes = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
|
||||
|
||||
// o(n)
|
||||
for (Scope scope : scopes) {
|
||||
if (selfSyncingScopeTree == null) {
|
||||
selfSyncingScopeTree = new SelfSyncingScopeTree(scope, scopePermMap.get(scope.getName()),
|
||||
apiApplicationKey,
|
||||
accessTokenInfo);
|
||||
} else {
|
||||
selfSyncingScopeTree.add(scope, scopePermMap.get(scope.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
APIPublisherDataHolder.getInstance().getSelfSyncTrees().put(tenantDomain, selfSyncingScopeTree);
|
||||
}
|
||||
return selfSyncingScopeTree;
|
||||
} catch (MetadataManagementException e) {
|
||||
String msg = "Error encountered while retrieving metadata for " + Constants.PERM_SCOPE_MAPPING_META_KEY;
|
||||
log.error(msg);
|
||||
throw new APIManagerPublisherException(msg, e);
|
||||
} catch (APIManagerPublisherException | BadRequestException
|
||||
| UnexpectedResponseException | APIServicesException e) {
|
||||
String msg = "Error encountered while invoking publisher rest services";
|
||||
log.error(msg);
|
||||
throw new APIManagerPublisherException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Scope getUpdatedScope(Scope previousScope, String role, boolean remove) {
|
||||
Scope scope = new Scope();
|
||||
scope.setId(previousScope.getId());
|
||||
scope.setName(previousScope.getName());
|
||||
scope.setDisplayName(previousScope.getDisplayName());
|
||||
scope.setUsageCount(previousScope.getUsageCount());
|
||||
Set<String> bindings = new HashSet<>(previousScope.getBindings());
|
||||
if (remove) {
|
||||
bindings.remove(role);
|
||||
} else {
|
||||
bindings.add(role);
|
||||
}
|
||||
scope.setBindings(new ArrayList<>(bindings));
|
||||
return scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScopeRoleMapping(String roleName, String[] permissions, String[] removedPermissions) throws APIManagerPublisherException {
|
||||
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||
APIApplicationServices apiApplicationServices = APIPublisherDataHolder.getInstance().getApiApplicationServices();
|
||||
PublisherRESTAPIServices publisherRESTAPIServices = APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices();
|
||||
APIApplicationServices apiApplicationServices =
|
||||
APIPublisherDataHolder.getInstance().getApiApplicationServices();
|
||||
// PublisherRESTAPIServices publisherRESTAPIServices =
|
||||
// APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices();
|
||||
APIApplicationKey apiApplicationKey;
|
||||
AccessTokenInfo accessTokenInfo;
|
||||
try {
|
||||
@ -663,40 +755,70 @@ public class APIPublisherServiceImpl implements APIPublisherService {
|
||||
throw new APIManagerPublisherException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
SelfSyncingScopeTree selfSyncingScopeTree = getSyncTree(apiApplicationKey, accessTokenInfo);
|
||||
|
||||
Scope[] scopeList = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
|
||||
|
||||
Map<String, String> permScopeMap = APIPublisherDataHolder.getInstance().getPermScopeMapping();
|
||||
if (permissions.length != 0) {
|
||||
updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, permissions, permScopeMap, false);
|
||||
for (String permission : permissions) {
|
||||
Scope scope = selfSyncingScopeTree.findScope(permission);
|
||||
if (scope != null) {
|
||||
selfSyncingScopeTree.add(getUpdatedScope(scope, roleName, false), permission);
|
||||
} else {
|
||||
log.warn("Can not find a scope binding for permission [ " + permission + " ]");
|
||||
}
|
||||
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);
|
||||
}
|
||||
} catch (APIServicesException e) {
|
||||
String errorMsg = "Error while processing Publisher REST API response";
|
||||
log.error(errorMsg, e);
|
||||
throw new APIManagerPublisherException(errorMsg, e);
|
||||
} catch (BadRequestException e) {
|
||||
String errorMsg = "Error while calling Publisher REST APIs";
|
||||
log.error(errorMsg, e);
|
||||
throw new APIManagerPublisherException(errorMsg, e);
|
||||
} catch (UnexpectedResponseException e) {
|
||||
String errorMsg = "Unexpected response from the server";
|
||||
log.error(errorMsg, e);
|
||||
throw new APIManagerPublisherException(errorMsg, e);
|
||||
} finally {
|
||||
APIPublisherUtils.removeScopePublishUserIfExists(tenantDomain);
|
||||
}
|
||||
|
||||
for (String permission : removedPermissions) {
|
||||
Scope scope = selfSyncingScopeTree.findScope(permission);
|
||||
if (scope != null) {
|
||||
selfSyncingScopeTree.add(getUpdatedScope(scope, roleName, true), permission);
|
||||
} else {
|
||||
log.warn("Can not find a scope binding for permission [ " + permission + " ]");
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
// } finally {
|
||||
// APIPublisherUtils.removeScopePublishUserIfExists(tenantDomain);
|
||||
// }
|
||||
|
||||
// try {
|
||||
//
|
||||
// Scope[] scopeList = publisherRESTAPIServices.getScopes(apiApplicationKey, accessTokenInfo);
|
||||
//
|
||||
// Map<String, String> permScopeMap = APIPublisherDataHolder.getInstance().getPermScopeMapping();
|
||||
// if (permissions.length != 0) {
|
||||
// updateScopes(roleName, publisherRESTAPIServices, apiApplicationKey, accessTokenInfo, scopeList, 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);
|
||||
// }
|
||||
// } catch (APIServicesException e) {
|
||||
// String errorMsg = "Error while processing Publisher REST API response";
|
||||
// log.error(errorMsg, e);
|
||||
// throw new APIManagerPublisherException(errorMsg, e);
|
||||
// } catch (BadRequestException e) {
|
||||
// String errorMsg = "Error while calling Publisher REST APIs";
|
||||
// log.error(errorMsg, e);
|
||||
// throw new APIManagerPublisherException(errorMsg, e);
|
||||
// } catch (UnexpectedResponseException e) {
|
||||
// String errorMsg = "Unexpected response from the server";
|
||||
// log.error(errorMsg, e);
|
||||
// throw new APIManagerPublisherException(errorMsg, e);
|
||||
// } finally {
|
||||
// APIPublisherUtils.removeScopePublishUserIfExists(tenantDomain);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -851,7 +973,7 @@ public class APIPublisherServiceImpl implements APIPublisherService {
|
||||
scopeSet.add(scopeObject);
|
||||
|
||||
List<String> scopes = new ArrayList<>();
|
||||
scopes.addAll(Arrays.asList(apiUriTemplate.getScope().getKey()));
|
||||
scopes.add(apiUriTemplate.getScope().getKey());
|
||||
operation.setScopes(scopes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import io.entgra.device.mgt.core.apimgt.extension.rest.api.APIApplicationService
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.APIConfig;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.APIPublisherService;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.util.SelfSyncingScopeTree;
|
||||
import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.PostApiPublishingObsever;
|
||||
import org.wso2.carbon.context.CarbonContext;
|
||||
@ -38,6 +39,7 @@ import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
|
||||
public class APIPublisherDataHolder {
|
||||
@ -53,6 +55,11 @@ public class APIPublisherDataHolder {
|
||||
private APIApplicationServices apiApplicationServices;
|
||||
private PublisherRESTAPIServices publisherRESTAPIServices;
|
||||
private MetadataManagementService metadataManagementService;
|
||||
private static final WeakHashMap<String, SelfSyncingScopeTree> selfSyncTrees = new WeakHashMap<>();
|
||||
|
||||
public WeakHashMap<String, SelfSyncingScopeTree> getSelfSyncTrees() {
|
||||
return selfSyncTrees;
|
||||
}
|
||||
|
||||
private static APIPublisherDataHolder thisInstance = new APIPublisherDataHolder();
|
||||
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2018 - 2024, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
|
||||
*
|
||||
* Entgra (Pvt) Ltd. 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 io.entgra.device.mgt.core.apimgt.webapp.publisher.util;
|
||||
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.PublisherRESTAPIServices;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIApplicationKey;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.APIInfo.Scope;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.dto.AccessTokenInfo;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.APIServicesException;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.BadRequestException;
|
||||
import io.entgra.device.mgt.core.apimgt.extension.rest.api.exceptions.UnexpectedResponseException;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.exception.APIManagerPublisherException;
|
||||
import io.entgra.device.mgt.core.apimgt.webapp.publisher.internal.APIPublisherDataHolder;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SelfSyncingScopeTree {
|
||||
private static final Log log = LogFactory.getLog(SelfSyncingScopeTree.class);
|
||||
private static final PublisherRESTAPIServices publisherRESTAPIServices =
|
||||
APIPublisherDataHolder.getInstance().getPublisherRESTAPIServices();
|
||||
private final APIApplicationKey apiApplicationKey;
|
||||
private final AccessTokenInfo accessTokenInfo;
|
||||
private final Map<String, SelfSyncingScopeTree> childTrees = new ConcurrentHashMap<>();
|
||||
private String pathKey;
|
||||
private Scope scope;
|
||||
|
||||
public SelfSyncingScopeTree(Scope scope, String permission, APIApplicationKey apiApplicationKey,
|
||||
AccessTokenInfo accessTokenInfo) throws APIManagerPublisherException {
|
||||
this.apiApplicationKey = apiApplicationKey;
|
||||
this.accessTokenInfo = accessTokenInfo;
|
||||
add(scope, permission);
|
||||
}
|
||||
|
||||
public void add(Scope scope, String permission) throws APIManagerPublisherException {
|
||||
List<String> pathKeys = Arrays.stream(StringUtils.split(permission, "/")).collect(Collectors.toList());
|
||||
|
||||
if (pathKeys.size() == 1) {
|
||||
this.pathKey = pathKeys.get(0);
|
||||
|
||||
if (this.scope == null) {
|
||||
this.scope = scope;
|
||||
} else {
|
||||
this.update(scope);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.pathKey == null) {
|
||||
this.pathKey = pathKeys.get(0);
|
||||
}
|
||||
|
||||
pathKeys.remove(0);
|
||||
|
||||
if (childTrees.containsKey(pathKeys.get(0))) {
|
||||
childTrees.get(pathKeys.get(0)).add(scope, String.join("/", pathKeys));
|
||||
} else {
|
||||
childTrees.put(pathKeys.get(0), new SelfSyncingScopeTree(scope, String.join("/", pathKeys),
|
||||
apiApplicationKey, accessTokenInfo));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Scope findScope(String permission) {
|
||||
if (this.scope != null) {
|
||||
return this.scope;
|
||||
}
|
||||
|
||||
List<String> pathKeys = Arrays.stream(StringUtils.split(permission, "/")).collect(Collectors.toList());
|
||||
pathKeys.remove(0);
|
||||
return childTrees.get(pathKeys.get(0)).findScope(String.join("/", pathKeys));
|
||||
}
|
||||
|
||||
private void update(Scope scope) throws APIManagerPublisherException {
|
||||
try {
|
||||
if (publisherRESTAPIServices.isSharedScopeNameExists(apiApplicationKey, accessTokenInfo,
|
||||
this.scope.getName())) {
|
||||
if (publisherRESTAPIServices.updateSharedScope(apiApplicationKey, accessTokenInfo, scope)) {
|
||||
this.scope = scope;
|
||||
}
|
||||
} else {
|
||||
log.warn("Found a scope which is not reflect in the APIM end. Scope [ " + scope.getName() + " ]");
|
||||
}
|
||||
} catch (APIServicesException | BadRequestException | UnexpectedResponseException e) {
|
||||
String msg = "Error encountered while updating the scope [ " + scope.getName() + "]";
|
||||
log.error(msg, e);
|
||||
throw new APIManagerPublisherException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user