Skip to content

Commit 21d016b

Browse files
author
Alena Prokharchyk
committed
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
1 parent 2f7bfc0 commit 21d016b

10 files changed

Lines changed: 81 additions & 15 deletions

File tree

api/src/com/cloud/serializer/Param.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.lang.annotation.Retention;
2020
import java.lang.annotation.RetentionPolicy;
2121

22+
import org.apache.cloudstack.acl.RoleType;
23+
2224
@Retention(RetentionPolicy.RUNTIME)
2325
public @interface Param {
2426
String name() default "";
@@ -33,4 +35,6 @@
3335
boolean includeInApiDoc() default true;
3436

3537
String since() default "";
38+
39+
RoleType[] authorized() default {};
3640
}

api/src/org/apache/cloudstack/api/response/IPAddressResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Date;
2020
import java.util.List;
2121

22+
import org.apache.cloudstack.acl.RoleType;
2223
import org.apache.cloudstack.api.ApiConstants;
2324
import org.apache.cloudstack.api.BaseResponse;
2425
import org.apache.cloudstack.api.EntityReference;
@@ -146,7 +147,7 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
146147
private Boolean isPortable;
147148

148149
@SerializedName(ApiConstants.FOR_DISPLAY)
149-
@Param(description = "is public ip for display to the regular user", since = "4.4")
150+
@Param(description = "is public ip for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
150151
private Boolean forDisplay;
151152

152153
/*

api/src/org/apache/cloudstack/api/response/NetworkResponse.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818

1919
import java.util.List;
2020

21-
import com.google.gson.annotations.SerializedName;
22-
21+
import org.apache.cloudstack.acl.RoleType;
2322
import org.apache.cloudstack.api.ApiConstants;
2423
import org.apache.cloudstack.api.BaseResponse;
2524
import org.apache.cloudstack.api.EntityReference;
2625

2726
import com.cloud.network.Network;
2827
import com.cloud.projects.ProjectAccount;
2928
import com.cloud.serializer.Param;
29+
import com.google.gson.annotations.SerializedName;
3030

3131
@SuppressWarnings("unused")
3232
@EntityReference(value = {Network.class, ProjectAccount.class})
@@ -209,7 +209,7 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes
209209
private String ip6Cidr;
210210

211211
@SerializedName(ApiConstants.DISPLAY_NETWORK)
212-
@Param(description = "an optional field, whether to the display the network to the end user or not.")
212+
@Param(description = "an optional field, whether to the display the network to the end user or not.", authorized = {RoleType.Admin})
213213
private Boolean displayNetwork;
214214

215215
@SerializedName(ApiConstants.ACL_ID)

api/src/org/apache/cloudstack/api/response/UserVmResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Map;
2222
import java.util.Set;
2323

24+
import org.apache.cloudstack.acl.RoleType;
2425
import org.apache.cloudstack.affinity.AffinityGroupResponse;
2526
import org.apache.cloudstack.api.ApiConstants;
2627
import org.apache.cloudstack.api.BaseResponse;
@@ -248,7 +249,7 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
248249
private Set<AffinityGroupResponse> affinityGroupList;
249250

250251
@SerializedName(ApiConstants.DISPLAY_VM)
251-
@Param(description = "an optional field whether to the display the vm to the end user or not.")
252+
@Param(description = "an optional field whether to the display the vm to the end user or not.", authorized = {RoleType.Admin})
252253
private Boolean displayVm;
253254

254255
@SerializedName(ApiConstants.IS_DYNAMICALLY_SCALABLE)

api/src/org/apache/cloudstack/api/response/VolumeResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.LinkedHashSet;
2121
import java.util.Set;
2222

23+
import org.apache.cloudstack.acl.RoleType;
2324
import org.apache.cloudstack.api.ApiConstants;
2425
import org.apache.cloudstack.api.BaseResponse;
2526
import org.apache.cloudstack.api.EntityReference;
@@ -188,7 +189,7 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity
188189
private Set<ResourceTagResponse> tags;
189190

190191
@SerializedName(ApiConstants.DISPLAY_VOLUME)
191-
@Param(description = "an optional field whether to the display the volume to the end user or not.")
192+
@Param(description = "an optional field whether to the display the volume to the end user or not.", authorized = {RoleType.Admin})
192193
private Boolean displayVolume;
193194

194195
@SerializedName(ApiConstants.PATH)

api/src/org/apache/cloudstack/api/response/VpcResponse.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Date;
2020
import java.util.List;
2121

22+
import org.apache.cloudstack.acl.RoleType;
2223
import org.apache.cloudstack.api.ApiConstants;
2324
import org.apache.cloudstack.api.BaseResponse;
2425
import org.apache.cloudstack.api.EntityReference;
@@ -107,7 +108,7 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons
107108
private List<ResourceTagResponse> tags;
108109

109110
@SerializedName(ApiConstants.FOR_DISPLAY)
110-
@Param(description = "is vpc for display to the regular user", since = "4.4")
111+
@Param(description = "is vpc for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
111112
private Boolean forDisplay;
112113

113114
public void setId(String id) {

server/src/com/cloud/api/ApiGsonHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818

1919
import java.util.Map;
2020

21-
import com.google.gson.GsonBuilder;
22-
2321
import org.apache.cloudstack.api.ResponseObject;
2422

23+
import com.google.gson.GsonBuilder;
24+
2525
public class ApiGsonHelper {
2626
private static final GsonBuilder s_gBuilder;
2727
static {

server/src/com/cloud/api/ApiResponseGsonHelper.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@
1616
// under the License.
1717
package com.cloud.api;
1818

19-
import com.google.gson.GsonBuilder;
20-
19+
import org.apache.cloudstack.acl.RoleType;
2120
import org.apache.cloudstack.api.ResponseObject;
21+
import org.apache.cloudstack.context.CallContext;
22+
23+
import com.cloud.serializer.Param;
24+
import com.cloud.user.Account;
25+
import com.google.gson.ExclusionStrategy;
26+
import com.google.gson.FieldAttributes;
27+
import com.google.gson.GsonBuilder;
2228

2329
/**
2430
* 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 {
3137
s_gBuilder.setVersion(1.3);
3238
s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter());
3339
s_gBuilder.registerTypeAdapter(String.class, new EncodedStringTypeAdapter());
40+
s_gBuilder.setExclusionStrategies(new ExclStrat());
3441
}
3542

3643
public static GsonBuilder getBuilder() {
3744
return s_gBuilder;
3845
}
46+
47+
private static class ExclStrat implements ExclusionStrategy {
48+
49+
public boolean shouldSkipClass(Class<?> arg0) {
50+
return false;
51+
}
52+
public boolean shouldSkipField(FieldAttributes f) {
53+
54+
Param param = f.getAnnotation(Param.class);
55+
if (param != null) {
56+
RoleType[] allowedRoles = param.authorized();
57+
if (allowedRoles.length > 0) {
58+
boolean permittedParameter = false;
59+
Account caller = CallContext.current().getCallingAccount();
60+
for (RoleType allowedRole : allowedRoles) {
61+
if (allowedRole.getValue() == caller.getType()) {
62+
permittedParameter = true;
63+
break;
64+
}
65+
}
66+
if (!permittedParameter) {
67+
return true;
68+
}
69+
}
70+
}
71+
return false;
72+
}
73+
}
3974
}

server/src/com/cloud/api/ResponseObjectTypeAdapter.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,16 @@
1919
import java.lang.reflect.Method;
2020
import java.lang.reflect.Type;
2121

22+
import org.apache.cloudstack.api.ResponseObject;
23+
import org.apache.cloudstack.api.response.ExceptionResponse;
24+
import org.apache.cloudstack.api.response.SuccessResponse;
2225
import org.apache.log4j.Logger;
2326

2427
import com.google.gson.JsonElement;
2528
import com.google.gson.JsonObject;
2629
import com.google.gson.JsonSerializationContext;
2730
import com.google.gson.JsonSerializer;
2831

29-
import org.apache.cloudstack.api.ResponseObject;
30-
import org.apache.cloudstack.api.response.ExceptionResponse;
31-
import org.apache.cloudstack.api.response.SuccessResponse;
32-
3332
public class ResponseObjectTypeAdapter implements JsonSerializer<ResponseObject> {
3433
public static final Logger s_logger = Logger.getLogger(ResponseObjectTypeAdapter.class.getName());
3534

server/src/com/cloud/api/response/ApiResponseSerializer.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.regex.Matcher;
2727
import java.util.regex.Pattern;
2828

29+
import org.apache.cloudstack.acl.RoleType;
2930
import org.apache.cloudstack.api.ApiConstants;
3031
import org.apache.cloudstack.api.BaseCmd;
3132
import org.apache.cloudstack.api.ResponseObject;
@@ -34,11 +35,14 @@
3435
import org.apache.cloudstack.api.response.ExceptionResponse;
3536
import org.apache.cloudstack.api.response.ListResponse;
3637
import org.apache.cloudstack.api.response.SuccessResponse;
38+
import org.apache.cloudstack.context.CallContext;
3739
import org.apache.log4j.Logger;
3840

3941
import com.cloud.api.ApiDBUtils;
4042
import com.cloud.api.ApiResponseGsonHelper;
4143
import com.cloud.api.ApiServer;
44+
import com.cloud.serializer.Param;
45+
import com.cloud.user.Account;
4246
import com.cloud.utils.encoding.URLEncoder;
4347
import com.cloud.utils.exception.CloudRuntimeException;
4448
import com.cloud.utils.exception.ExceptionProxyObject;
@@ -189,11 +193,31 @@ private static void serializeResponseObjFieldsXML(StringBuilder sb, ResponseObje
189193
continue; // skip transient fields
190194
}
191195

196+
192197
SerializedName serializedName = field.getAnnotation(SerializedName.class);
193198
if (serializedName == null) {
194199
continue; // skip fields w/o serialized name
195200
}
196201

202+
Param param = field.getAnnotation(Param.class);
203+
if (param != null) {
204+
RoleType[] allowedRoles = param.authorized();
205+
if (allowedRoles.length > 0) {
206+
boolean permittedParameter = false;
207+
Account caller = CallContext.current().getCallingAccount();
208+
for (RoleType allowedRole : allowedRoles) {
209+
if (allowedRole.getValue() == caller.getType()) {
210+
permittedParameter = true;
211+
break;
212+
}
213+
}
214+
if (!permittedParameter) {
215+
s_logger.trace("Ignoring paremeter " + param.name() + " as the caller is not authorized to see it");
216+
continue;
217+
}
218+
}
219+
}
220+
197221
field.setAccessible(true);
198222
Object fieldValue = null;
199223
try {

0 commit comments

Comments
 (0)