API response: added new field to @Param - RoleType[] authorized() default {}. The field defines who is authorized to see this partciluar reponse field. If not specified, the parameter is returned to everybody

This commit is contained in:
Alena Prokharchyk 2014-02-20 17:14:11 -08:00
parent 2f7bfc0c73
commit 21d016b3dd
10 changed files with 81 additions and 15 deletions

View File

@ -19,6 +19,8 @@ package com.cloud.serializer;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.apache.cloudstack.acl.RoleType;
@Retention(RetentionPolicy.RUNTIME)
public @interface Param {
String name() default "";
@ -33,4 +35,6 @@ public @interface Param {
boolean includeInApiDoc() default true;
String since() default "";
RoleType[] authorized() default {};
}

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.api.response;
import java.util.Date;
import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@ -146,7 +147,7 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
private Boolean isPortable;
@SerializedName(ApiConstants.FOR_DISPLAY)
@Param(description = "is public ip for display to the regular user", since = "4.4")
@Param(description = "is public ip for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
private Boolean forDisplay;
/*

View File

@ -18,8 +18,7 @@ package org.apache.cloudstack.api.response;
import java.util.List;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@ -27,6 +26,7 @@ import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.Network;
import com.cloud.projects.ProjectAccount;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = {Network.class, ProjectAccount.class})
@ -209,7 +209,7 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes
private String ip6Cidr;
@SerializedName(ApiConstants.DISPLAY_NETWORK)
@Param(description = "an optional field, whether to the display the network to the end user or not.")
@Param(description = "an optional field, whether to the display the network to the end user or not.", authorized = {RoleType.Admin})
private Boolean displayNetwork;
@SerializedName(ApiConstants.ACL_ID)

View File

@ -21,6 +21,7 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
@ -248,7 +249,7 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
private Set<AffinityGroupResponse> affinityGroupList;
@SerializedName(ApiConstants.DISPLAY_VM)
@Param(description = "an optional field whether to the display the vm to the end user or not.")
@Param(description = "an optional field whether to the display the vm to the end user or not.", authorized = {RoleType.Admin})
private Boolean displayVm;
@SerializedName(ApiConstants.IS_DYNAMICALLY_SCALABLE)

View File

@ -20,6 +20,7 @@ import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@ -188,7 +189,7 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
private Set<ResourceTagResponse> tags;
@SerializedName(ApiConstants.DISPLAY_VOLUME)
@Param(description = "an optional field whether to the display the volume to the end user or not.")
@Param(description = "an optional field whether to the display the volume to the end user or not.", authorized = {RoleType.Admin})
private Boolean displayVolume;
@SerializedName(ApiConstants.PATH)

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.api.response;
import java.util.Date;
import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
@ -107,7 +108,7 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons
private List<ResourceTagResponse> tags;
@SerializedName(ApiConstants.FOR_DISPLAY)
@Param(description = "is vpc for display to the regular user", since = "4.4")
@Param(description = "is vpc for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
private Boolean forDisplay;
public void setId(String id) {

View File

@ -18,10 +18,10 @@ package com.cloud.api;
import java.util.Map;
import com.google.gson.GsonBuilder;
import org.apache.cloudstack.api.ResponseObject;
import com.google.gson.GsonBuilder;
public class ApiGsonHelper {
private static final GsonBuilder s_gBuilder;
static {

View File

@ -16,9 +16,15 @@
// under the License.
package com.cloud.api;
import com.google.gson.GsonBuilder;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.context.CallContext;
import com.cloud.serializer.Param;
import com.cloud.user.Account;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.GsonBuilder;
/**
* The ApiResonseGsonHelper is different from ApiGsonHelper - it registeres one more adapter for String type required for api response encoding
@ -31,9 +37,38 @@ public class ApiResponseGsonHelper {
s_gBuilder.setVersion(1.3);
s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter());
s_gBuilder.registerTypeAdapter(String.class, new EncodedStringTypeAdapter());
s_gBuilder.setExclusionStrategies(new ExclStrat());
}
public static GsonBuilder getBuilder() {
return s_gBuilder;
}
private static class ExclStrat implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
Param param = f.getAnnotation(Param.class);
if (param != null) {
RoleType[] allowedRoles = param.authorized();
if (allowedRoles.length > 0) {
boolean permittedParameter = false;
Account caller = CallContext.current().getCallingAccount();
for (RoleType allowedRole : allowedRoles) {
if (allowedRole.getValue() == caller.getType()) {
permittedParameter = true;
break;
}
}
if (!permittedParameter) {
return true;
}
}
}
return false;
}
}
}

View File

@ -19,6 +19,9 @@ package com.cloud.api;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.ExceptionResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.log4j.Logger;
import com.google.gson.JsonElement;
@ -26,10 +29,6 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.ExceptionResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
public class ResponseObjectTypeAdapter implements JsonSerializer<ResponseObject> {
public static final Logger s_logger = Logger.getLogger(ResponseObjectTypeAdapter.class.getName());

View File

@ -26,6 +26,7 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.ResponseObject;
@ -34,11 +35,14 @@ import org.apache.cloudstack.api.response.CreateCmdResponse;
import org.apache.cloudstack.api.response.ExceptionResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.ApiResponseGsonHelper;
import com.cloud.api.ApiServer;
import com.cloud.serializer.Param;
import com.cloud.user.Account;
import com.cloud.utils.encoding.URLEncoder;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.ExceptionProxyObject;
@ -189,11 +193,31 @@ public class ApiResponseSerializer {
continue; // skip transient fields
}
SerializedName serializedName = field.getAnnotation(SerializedName.class);
if (serializedName == null) {
continue; // skip fields w/o serialized name
}
Param param = field.getAnnotation(Param.class);
if (param != null) {
RoleType[] allowedRoles = param.authorized();
if (allowedRoles.length > 0) {
boolean permittedParameter = false;
Account caller = CallContext.current().getCallingAccount();
for (RoleType allowedRole : allowedRoles) {
if (allowedRole.getValue() == caller.getType()) {
permittedParameter = true;
break;
}
}
if (!permittedParameter) {
s_logger.trace("Ignoring paremeter " + param.name() + " as the caller is not authorized to see it");
continue;
}
}
}
field.setAccessible(true);
Object fieldValue = null;
try {