diff --git a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java index ed3e1751027..132416bac05 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/api/command/user/discovery/ListApisCmd.java @@ -16,7 +16,10 @@ // under the License. package org.apache.cloudstack.api.command.user.discovery; +import com.cloud.user.AccountService; +import com.cloud.user.User; import com.cloud.user.UserContext; +import com.cloud.utils.component.Inject; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,14 +42,17 @@ public class ListApisCmd extends BaseCmd { @PlugService ApiDiscoveryService _apiDiscoveryService; + @Inject + private AccountService _accountService; + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="API name") private String name; @Override public void execute() throws ServerApiException { if (_apiDiscoveryService != null) { - RoleType roleType = _accountService.getRoleType(UserContext.current().getCaller()); - ListResponse response = (ListResponse) _apiDiscoveryService.listApis(roleType, name); + User user = _accountService.getActiveUser(UserContext.current().getCallerUserId()); + ListResponse response = (ListResponse) _apiDiscoveryService.listApis(user, name); if (response == null) { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Api Discovery plugin was unable to find an api by that name or process any apis"); } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java index 611493bfc08..6458c5619e8 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryService.java @@ -16,11 +16,11 @@ // under the License. package org.apache.cloudstack.discovery; +import com.cloud.user.User; import com.cloud.utils.component.PluggableService; -import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.response.ListResponse; public interface ApiDiscoveryService extends PluggableService { - ListResponse listApis(RoleType roleType, String apiName); + ListResponse listApis(User user, String apiName); } diff --git a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java index 5f84486ae49..7e2ed17ecdc 100644 --- a/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -18,11 +18,15 @@ package org.apache.cloudstack.discovery; import com.cloud.serializer.Param; import com.cloud.server.ManagementServer; +import com.cloud.user.User; import com.cloud.utils.ReflectUtil; import com.cloud.utils.StringUtils; +import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Inject; import com.cloud.utils.component.PluggableService; import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; @@ -30,6 +34,7 @@ import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.command.user.discovery.ListApisCmd; import org.apache.cloudstack.api.response.ApiDiscoveryResponse; import org.apache.cloudstack.api.response.ApiParameterResponse; import org.apache.cloudstack.api.response.ApiResponseResponse; @@ -49,57 +54,31 @@ import java.util.Set; public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { private static final Logger s_logger = Logger.getLogger(ApiDiscoveryServiceImpl.class); - private static Map> _roleTypeDiscoveryResponseListMap; + @Inject(adapter = APIChecker.class) + protected Adapters _apiAccessCheckers; - private static Map _apiNameDiscoveryResponseMap = - new HashMap(); - - private static Map> _apiNameRoleTypeListMap = null; + private static Map _apiNameDiscoveryResponseMap = null; protected ApiDiscoveryServiceImpl() { super(); - if (_roleTypeDiscoveryResponseListMap == null) { + if (_apiNameDiscoveryResponseMap == null) { long startTime = System.nanoTime(); - _roleTypeDiscoveryResponseListMap = new HashMap>(); - for (RoleType roleType: RoleType.values()) - _roleTypeDiscoveryResponseListMap.put(roleType, new ArrayList()); + _apiNameDiscoveryResponseMap = new HashMap(); cacheResponseMap(); long endTime = System.nanoTime(); s_logger.info("Api Discovery Service: Annotation, docstrings, api relation graph processed in " + (endTime - startTime) / 1000000.0 + " ms"); } } - private Map> getApiNameRoleTypeListMap() { - Map> apiNameRoleTypeMap = new HashMap>(); - ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); - List services = locator.getAllPluggableServices(); - services.add((PluggableService) ComponentLocator.getComponent(ManagementServer.Name)); - for (PluggableService service : services) { - for (Map.Entry entry: service.getProperties().entrySet()) { - String apiName = entry.getKey(); - String roleMask = entry.getValue(); - try { - short cmdPermissions = Short.parseShort(roleMask); - if (!apiNameRoleTypeMap.containsKey(apiName)) - apiNameRoleTypeMap.put(apiName, new ArrayList()); - for (RoleType roleType: RoleType.values()) { - if ((cmdPermissions & roleType.getValue()) != 0) - apiNameRoleTypeMap.get(apiName).add(roleType); - } - } catch (NumberFormatException nfe) { - } - } - } - return apiNameRoleTypeMap; - } - private void cacheResponseMap() { Set> cmdClasses = ReflectUtil.getClassesWithAnnotation(APICommand.class, new String[]{"org.apache.cloudstack.api", "com.cloud.api"}); + //TODO: Fix and use PluggableService to get the classes + Map> responseApiNameListMap = new HashMap>(); - for(Class cmdClass: cmdClasses) { + for (Class cmdClass : cmdClasses) { APICommand apiCmdAnnotation = cmdClass.getAnnotation(APICommand.class); if (apiCmdAnnotation == null) apiCmdAnnotation = cmdClass.getSuperclass().getAnnotation(APICommand.class); @@ -123,9 +102,9 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { response.setRelated(responseName); Field[] responseFields = apiCmdAnnotation.responseObject().getDeclaredFields(); - for(Field responseField: responseFields) { + for (Field responseField : responseFields) { SerializedName serializedName = responseField.getAnnotation(SerializedName.class); - if(serializedName != null) { + if (serializedName != null) { ApiResponseResponse responseResponse = new ApiResponseResponse(); responseResponse.setName(serializedName.value()); Param param = responseField.getAnnotation(Param.class); @@ -137,14 +116,14 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } Field[] fields = ReflectUtil.getAllFieldsForClass(cmdClass, - new Class[] {BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); + new Class[]{BaseCmd.class, BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); boolean isAsync = ReflectUtil.isCmdClassAsync(cmdClass, - new Class[] {BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); + new Class[]{BaseAsyncCmd.class, BaseAsyncCreateCmd.class}); response.setAsync(isAsync); - for(Field field: fields) { + for (Field field : fields) { Parameter parameterAnnotation = field.getAnnotation(Parameter.class); if (parameterAnnotation != null && parameterAnnotation.expose() @@ -166,10 +145,10 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { _apiNameDiscoveryResponseMap.put(apiName, response); } - for (String apiName: _apiNameDiscoveryResponseMap.keySet()) { + for (String apiName : _apiNameDiscoveryResponseMap.keySet()) { ApiDiscoveryResponse response = _apiNameDiscoveryResponseMap.get(apiName); Set processedParams = new HashSet(); - for (ApiParameterResponse param: response.getParams()) { + for (ApiParameterResponse param : response.getParams()) { if (responseApiNameListMap.containsKey(param.getRelated())) { List relatedApis = responseApiNameListMap.get(param.getRelated()); param.setRelated(StringUtils.join(relatedApis, ",")); @@ -192,41 +171,48 @@ public class ApiDiscoveryServiceImpl implements ApiDiscoveryService { } @Override - public ListResponse listApis(RoleType roleType, String name) { - // Creates roles based response list cache the first time listApis is called - // Due to how adapters work, this cannot be done when mgmt loads - if (_apiNameRoleTypeListMap == null) { - long startTime = System.nanoTime(); - _apiNameRoleTypeListMap = getApiNameRoleTypeListMap(); - for (Map.Entry> entry: _apiNameRoleTypeListMap.entrySet()) { - String apiName = entry.getKey(); - for (RoleType roleTypeInList: entry.getValue()) { - _roleTypeDiscoveryResponseListMap.get(roleTypeInList).add( - _apiNameDiscoveryResponseMap.get(apiName)); - } - } - long endTime = System.nanoTime(); - s_logger.info("Api Discovery Service: List apis cached in " + (endTime - startTime) / 1000000.0 + " ms"); - } + public ListResponse listApis(User user, String name) { ListResponse response = new ListResponse(); + List responseList = new ArrayList(); + + if (user == null) + return null; + if (name != null) { if (!_apiNameDiscoveryResponseMap.containsKey(name)) return null; - List singleResponse = new ArrayList(); - singleResponse.add(_apiNameDiscoveryResponseMap.get(name)); - response.setResponses(singleResponse); + for (APIChecker apiChecker : _apiAccessCheckers) { + try { + apiChecker.checkAccess(user, name); + } catch (Exception ex) { + return null; + } + } + responseList.add(_apiNameDiscoveryResponseMap.get(name)); } else { - response.setResponses(_roleTypeDiscoveryResponseListMap.get(roleType)); + for (String apiName : _apiNameDiscoveryResponseMap.keySet()) { + boolean isAllowed = true; + for (APIChecker apiChecker : _apiAccessCheckers) { + try { + apiChecker.checkAccess(user, name); + } catch (Exception ex) { + isAllowed = false; + } + } + if (isAllowed) + responseList.add(_apiNameDiscoveryResponseMap.get(apiName)); + } } + response.setResponses(responseList); return response; } @Override - public Map getProperties() { - Map apiDiscoveryPropertyMap = new HashMap(); - apiDiscoveryPropertyMap.put("listApis", "15"); - return apiDiscoveryPropertyMap; + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(ListApisCmd.class); + return cmdList; } }