api: listApis should return params based on caller (#8973)

This commit is contained in:
Abhishek Kumar 2024-06-11 11:28:08 +05:30 committed by GitHub
parent fcca3e8f39
commit 7aacbcb559
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 11 deletions

View File

@ -16,13 +16,14 @@
// under the License. // under the License.
package org.apache.cloudstack.api.response; package org.apache.cloudstack.api.response;
import com.cloud.serializer.Param; import java.util.HashSet;
import com.google.gson.annotations.SerializedName; import java.util.Set;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import java.util.HashSet; import com.cloud.serializer.Param;
import java.util.Set; import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class ApiDiscoveryResponse extends BaseResponse { public class ApiDiscoveryResponse extends BaseResponse {
@ -64,6 +65,18 @@ public class ApiDiscoveryResponse extends BaseResponse {
isAsync = false; isAsync = false;
} }
public ApiDiscoveryResponse(ApiDiscoveryResponse another) {
this.name = another.getName();
this.description = another.getDescription();
this.since = another.getSince();
this.isAsync = another.getAsync();
this.related = another.getRelated();
this.params = new HashSet<>(another.getParams());
this.apiResponse = new HashSet<>(another.getApiResponse());
this.type = another.getType();
this.setObjectName(another.getObjectName());
}
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
@ -123,4 +136,8 @@ public class ApiDiscoveryResponse extends BaseResponse {
public Set<ApiResponseResponse> getApiResponse() { public Set<ApiResponseResponse> getApiResponse() {
return apiResponse; return apiResponse;
} }
public String getType() {
return type;
}
} }

View File

@ -16,12 +16,14 @@
// under the License. // under the License.
package org.apache.cloudstack.api.response; package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName; import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param; import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class ApiParameterResponse extends BaseResponse { public class ApiParameterResponse extends BaseResponse {
@SerializedName(ApiConstants.NAME) @SerializedName(ApiConstants.NAME)
@ -52,6 +54,8 @@ public class ApiParameterResponse extends BaseResponse {
@Param(description = "comma separated related apis to get the parameter") @Param(description = "comma separated related apis to get the parameter")
private String related; private String related;
private transient List<RoleType> authorizedRoleTypes = null;
public ApiParameterResponse() { public ApiParameterResponse() {
} }
@ -87,4 +91,11 @@ public class ApiParameterResponse extends BaseResponse {
this.related = related; this.related = related;
} }
public void setAuthorizedRoleTypes(List<RoleType> authorizedRoleTypes) {
this.authorizedRoleTypes = authorizedRoleTypes;
}
public List<RoleType> getAuthorizedRoleTypes() {
return authorizedRoleTypes;
}
} }

View File

@ -18,8 +18,10 @@ package org.apache.cloudstack.discovery;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -28,21 +30,22 @@ import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.acl.APIChecker; import org.apache.cloudstack.acl.APIChecker;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.command.user.discovery.ListApisCmd; import org.apache.cloudstack.api.command.user.discovery.ListApisCmd;
import org.apache.cloudstack.api.response.ApiDiscoveryResponse; import org.apache.cloudstack.api.response.ApiDiscoveryResponse;
import org.apache.cloudstack.api.response.ApiParameterResponse; import org.apache.cloudstack.api.response.ApiParameterResponse;
import org.apache.cloudstack.api.response.ApiResponseResponse; import org.apache.cloudstack.api.response.ApiResponseResponse;
import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.reflections.ReflectionUtils; import org.reflections.ReflectionUtils;
@ -217,6 +220,9 @@ public class ApiDiscoveryServiceImpl extends ComponentLifecycleBase implements A
paramResponse.setSince(parameterAnnotation.since()); paramResponse.setSince(parameterAnnotation.since());
} }
paramResponse.setRelated(parameterAnnotation.entityType()[0].getName()); paramResponse.setRelated(parameterAnnotation.entityType()[0].getName());
if (parameterAnnotation.authorized() != null) {
paramResponse.setAuthorizedRoleTypes(Arrays.asList(parameterAnnotation.authorized()));
}
response.addParam(paramResponse); response.addParam(paramResponse);
} }
} }
@ -249,6 +255,7 @@ public class ApiDiscoveryServiceImpl extends ComponentLifecycleBase implements A
if (user == null) if (user == null)
return null; return null;
Account account = accountService.getAccount(user.getAccountId());
if (name != null) { if (name != null) {
if (!s_apiNameDiscoveryResponseMap.containsKey(name)) if (!s_apiNameDiscoveryResponseMap.containsKey(name))
@ -262,10 +269,9 @@ public class ApiDiscoveryServiceImpl extends ComponentLifecycleBase implements A
return null; return null;
} }
} }
responseList.add(s_apiNameDiscoveryResponseMap.get(name)); responseList.add(getApiDiscoveryResponseWithAccessibleParams(name, account));
} else { } else {
Account account = accountService.getAccount(user.getAccountId());
if (account == null) { if (account == null) {
throw new PermissionDeniedException(String.format("The account with id [%s] for user [%s] is null.", user.getAccountId(), user)); throw new PermissionDeniedException(String.format("The account with id [%s] for user [%s] is null.", user.getAccountId(), user));
} }
@ -286,13 +292,33 @@ public class ApiDiscoveryServiceImpl extends ComponentLifecycleBase implements A
} }
for (String apiName: apisAllowed) { for (String apiName: apisAllowed) {
responseList.add(s_apiNameDiscoveryResponseMap.get(apiName)); responseList.add(getApiDiscoveryResponseWithAccessibleParams(apiName, account));
} }
} }
response.setResponses(responseList); response.setResponses(responseList);
return response; return response;
} }
private static ApiDiscoveryResponse getApiDiscoveryResponseWithAccessibleParams(String name, Account account) {
if (Account.Type.ADMIN.equals(account.getType())) {
return s_apiNameDiscoveryResponseMap.get(name);
}
ApiDiscoveryResponse apiDiscoveryResponse =
new ApiDiscoveryResponse(s_apiNameDiscoveryResponseMap.get(name));
Iterator<ApiParameterResponse> iterator = apiDiscoveryResponse.getParams().iterator();
while (iterator.hasNext()) {
ApiParameterResponse parameterResponse = iterator.next();
List<RoleType> authorizedRoleTypes = parameterResponse.getAuthorizedRoleTypes();
RoleType accountRoleType = RoleType.getByAccountType(account.getType());
if (CollectionUtils.isNotEmpty(parameterResponse.getAuthorizedRoleTypes()) &&
accountRoleType != null &&
!authorizedRoleTypes.contains(accountRoleType)) {
iterator.remove();
}
}
return apiDiscoveryResponse;
}
@Override @Override
public List<Class<?>> getCommands() { public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<Class<?>>(); List<Class<?>> cmdList = new ArrayList<Class<?>>();