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


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/21d016b3
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/21d016b3
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/21d016b3

Branch: refs/heads/master
Commit: 21d016b3dd855e47c87c62c3e4a4e2b2ec2fb257
Parents: 2f7bfc0
Author: Alena Prokharchyk <[email protected]>
Authored: Thu Feb 20 17:14:11 2014 -0800
Committer: Alena Prokharchyk <[email protected]>
Committed: Thu Feb 20 17:15:43 2014 -0800

----------------------------------------------------------------------
 api/src/com/cloud/serializer/Param.java         |  4 ++
 .../api/response/IPAddressResponse.java         |  3 +-
 .../api/response/NetworkResponse.java           |  6 +--
 .../cloudstack/api/response/UserVmResponse.java |  3 +-
 .../cloudstack/api/response/VolumeResponse.java |  3 +-
 .../cloudstack/api/response/VpcResponse.java    |  3 +-
 server/src/com/cloud/api/ApiGsonHelper.java     |  4 +-
 .../com/cloud/api/ApiResponseGsonHelper.java    | 39 +++++++++++++++++++-
 .../cloud/api/ResponseObjectTypeAdapter.java    |  7 ++--
 .../api/response/ApiResponseSerializer.java     | 24 ++++++++++++
 10 files changed, 81 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/api/src/com/cloud/serializer/Param.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/serializer/Param.java 
b/api/src/com/cloud/serializer/Param.java
index 02deb6f..3e6f852 100644
--- a/api/src/com/cloud/serializer/Param.java
+++ b/api/src/com/cloud/serializer/Param.java
@@ -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 {};
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java 
b/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
index 1f51d5a..3c03247 100644
--- a/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
@@ -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;
 
     /*

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java 
b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
index 58ec956..bf92aa4 100644
--- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
@@ -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)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java 
b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
index 26ecb5b..84d532b 100644
--- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -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)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java 
b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
index 319a734..27e95de 100644
--- a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java
@@ -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)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/api/src/org/apache/cloudstack/api/response/VpcResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VpcResponse.java 
b/api/src/org/apache/cloudstack/api/response/VpcResponse.java
index 928d1b2..eeafb40 100644
--- a/api/src/org/apache/cloudstack/api/response/VpcResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/VpcResponse.java
@@ -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) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/server/src/com/cloud/api/ApiGsonHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiGsonHelper.java 
b/server/src/com/cloud/api/ApiGsonHelper.java
index 58f29ce..faa70c2 100644
--- a/server/src/com/cloud/api/ApiGsonHelper.java
+++ b/server/src/com/cloud/api/ApiGsonHelper.java
@@ -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 {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/server/src/com/cloud/api/ApiResponseGsonHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseGsonHelper.java 
b/server/src/com/cloud/api/ApiResponseGsonHelper.java
index 3352cc8..c2cc9d9 100644
--- a/server/src/com/cloud/api/ApiResponseGsonHelper.java
+++ b/server/src/com/cloud/api/ApiResponseGsonHelper.java
@@ -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;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/server/src/com/cloud/api/ResponseObjectTypeAdapter.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ResponseObjectTypeAdapter.java 
b/server/src/com/cloud/api/ResponseObjectTypeAdapter.java
index a4bc6ca..44baedc 100644
--- a/server/src/com/cloud/api/ResponseObjectTypeAdapter.java
+++ b/server/src/com/cloud/api/ResponseObjectTypeAdapter.java
@@ -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());
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/21d016b3/server/src/com/cloud/api/response/ApiResponseSerializer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java 
b/server/src/com/cloud/api/response/ApiResponseSerializer.java
index f276e89..e9633a7 100644
--- a/server/src/com/cloud/api/response/ApiResponseSerializer.java
+++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java
@@ -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 {

Reply via email to