Return 400 instead of 403 when missing X-FromAppId
[aai/gizmo.git] / src / main / java / org / onap / crud / service / CrudRestService.java
1 /**
2  * ============LICENSE_START=======================================================
3  * Gizmo
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  *
22  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23  */
24 package org.onap.crud.service;
25
26 import com.google.gson.JsonElement;
27
28 import org.apache.cxf.jaxrs.ext.PATCH;
29 import org.onap.aai.cl.api.Logger;
30 import org.onap.aai.cl.eelf.LoggerFactory;
31 import org.onap.aaiauth.auth.Auth;
32 import org.onap.crud.exception.CrudException;
33 import org.onap.crud.logging.CrudServiceMsgs;
34 import org.onap.crud.logging.LoggingUtil;
35 import org.onap.crud.util.CrudServiceConstants;
36 import org.onap.crud.util.CrudServiceUtil;
37 import org.slf4j.MDC;
38
39 import java.security.cert.X509Certificate;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 import javax.security.auth.x500.X500Principal;
45 import javax.servlet.http.HttpServletRequest;
46 import javax.ws.rs.*;
47 import javax.ws.rs.core.*;
48 import javax.ws.rs.core.Response.Status;
49
50 public class CrudRestService {
51
52   private AbstractGraphDataService graphDataService;
53   Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
54   Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
55   private Auth auth;
56
57   private String mediaType = MediaType.APPLICATION_JSON;
58   public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
59
60   public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
61     this.graphDataService = graphDataService;
62     this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
63   }
64
65   public enum Action {
66     POST, GET, PUT, DELETE, PATCH
67   }
68
69   public void startup() {
70
71   }
72
73   @GET
74   @Path("/{version}/{type}/{id}")
75   @Consumes({MediaType.APPLICATION_JSON})
76   @Produces({MediaType.APPLICATION_JSON})
77   public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
78                             @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
79                             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
80     LoggingUtil.initMdcContext(req, headers);
81
82     logger.debug("Incoming request..." + content);
83     Response response = null;
84
85
86     try {
87       if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
88         String result = graphDataService.getVertex(version, id, type);
89         response = Response.status(Status.OK).entity(result).type(mediaType).build();
90       } else {
91         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
92       }
93     } catch (CrudException ce) {
94       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
95     } catch (Exception e) {
96       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
97
98     }
99
100     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
101     return response;
102   }
103
104   @GET
105   @Path("/{version}/{type}/")
106   @Consumes({MediaType.APPLICATION_JSON})
107   @Produces({MediaType.APPLICATION_JSON})
108   public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
109                               @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
110                               @Context HttpServletRequest req) {
111
112     LoggingUtil.initMdcContext(req, headers);
113
114     logger.debug("Incoming request..." + content);
115     Response response = null;
116     try {
117       if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
118
119         Map<String, String> filter = new HashMap<String, String>();
120         for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
121           filter.put(e.getKey(), e.getValue().get(0));
122         }
123
124         String result = graphDataService.getVertices(version, type, filter);
125         response = Response.status(Status.OK).entity(result).type(mediaType).build();
126       } else {
127         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
128       }
129     } catch (CrudException ce) {
130       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
131     } catch (Exception e) {
132       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
133
134     }
135
136     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
137     return response;
138   }
139
140   @GET
141   @Path("/relationships/{version}/{type}/{id}")
142   @Consumes({MediaType.APPLICATION_JSON})
143   @Produces({MediaType.APPLICATION_JSON})
144   public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
145                           @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
146                           @Context UriInfo uriInfo, @Context HttpServletRequest req) {
147     LoggingUtil.initMdcContext(req, headers);
148
149     logger.debug("Incoming request..." + content);
150     Response response = null;
151
152
153     try {
154       if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
155
156         String result = graphDataService.getEdge(version, id, type);
157         response = Response.status(Status.OK).entity(result).type(mediaType).build();
158       } else {
159         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
160       }
161     } catch (CrudException ce) {
162       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
163     } catch (Exception e) {
164       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
165     }
166
167     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
168     return response;
169   }
170
171   @GET
172   @Path("/relationships/{version}/{type}/")
173   @Consumes({MediaType.APPLICATION_JSON})
174   @Produces({MediaType.APPLICATION_JSON})
175   public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
176                            @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
177                            @Context HttpServletRequest req) {
178
179     LoggingUtil.initMdcContext(req, headers);
180
181     logger.debug("Incoming request..." + content);
182     Response response = null;
183
184
185     Map<String, String> filter = new HashMap<String, String>();
186     for (Map.Entry<String, List<String>> e : uriInfo.getQueryParameters().entrySet()) {
187       filter.put(e.getKey(), e.getValue().get(0));
188     }
189
190     try {
191       if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
192         String result = graphDataService.getEdges(version, type, filter);
193         response = Response.status(Status.OK).entity(result).type(mediaType).build();
194       } else {
195         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
196       }
197     } catch (CrudException ce) {
198       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
199     } catch (Exception e) {
200       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
201     }
202
203     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
204     return response;
205   }
206
207   @PUT
208   @Path("/relationships/{version}/{type}/{id}")
209   @Consumes({MediaType.APPLICATION_JSON})
210   @Produces({MediaType.APPLICATION_JSON})
211   public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
212                              @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
213                              @Context UriInfo uriInfo, @Context HttpServletRequest req) {
214
215     LoggingUtil.initMdcContext(req, headers);
216
217     logger.debug("Incoming request..." + content);
218     Response response = null;
219
220
221     try {
222       if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
223         EdgePayload payload = EdgePayload.fromJson(content);
224         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
225           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
226         }
227         if (payload.getId() != null && !payload.getId().equals(id)) {
228           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
229         }
230         String result;
231
232         if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
233             && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
234           result = graphDataService.patchEdge(version, id, type, payload);
235         } else {
236
237           result = graphDataService.updateEdge(version, id, type, payload);
238         }
239
240         response = Response.status(Status.OK).entity(result).type(mediaType).build();
241       } else {
242         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
243       }
244     } catch (CrudException ce) {
245       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
246     } catch (Exception e) {
247       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
248     }
249
250     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
251     return response;
252   }
253
254   @PATCH
255   @Path("/relationships/{version}/{type}/{id}")
256   @Consumes({"application/merge-patch+json"})
257   @Produces({MediaType.APPLICATION_JSON})
258   public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
259                             @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
260                             @Context UriInfo uriInfo, @Context HttpServletRequest req) {
261
262     LoggingUtil.initMdcContext(req, headers);
263
264     logger.debug("Incoming request..." + content);
265     Response response = null;
266
267     try {
268       if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
269         EdgePayload payload = EdgePayload.fromJson(content);
270         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
271           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
272         }
273         if (payload.getId() != null && !payload.getId().equals(id)) {
274           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
275         }
276
277         String result = graphDataService.patchEdge(version, id, type, payload);
278         response = Response.status(Status.OK).entity(result).type(mediaType).build();
279       } else {
280         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
281       }
282     } catch (CrudException ce) {
283       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
284     } catch (Exception e) {
285       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
286     }
287
288     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
289     return response;
290   }
291
292   @PUT
293   @Path("/{version}/{type}/{id}")
294   @Consumes({MediaType.APPLICATION_JSON})
295   @Produces({MediaType.APPLICATION_JSON})
296   public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
297                                @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
298                                @Context UriInfo uriInfo, @Context HttpServletRequest req) {
299
300     LoggingUtil.initMdcContext(req, headers);
301
302     logger.debug("Incoming request..." + content);
303     Response response = null;
304
305
306     try {
307       if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
308         VertexPayload payload = VertexPayload.fromJson(content);
309         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
310           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
311         }
312         if (payload.getId() != null && !payload.getId().equals(id)) {
313           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
314         }
315
316         String result;
317
318         payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
319
320         if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
321             && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
322           result = graphDataService.patchVertex(version, id, type, payload);
323         } else {
324
325           result = graphDataService.updateVertex(version, id, type, payload);
326         }
327         response = Response.status(Status.OK).entity(result).type(mediaType).build();
328       } else {
329         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
330       }
331     } catch (CrudException ce) {
332       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
333     } catch (Exception e) {
334       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
335     }
336
337     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
338     return response;
339   }
340
341   @PATCH
342   @Path("/{version}/{type}/{id}")
343   @Consumes({"application/merge-patch+json"})
344   @Produces({MediaType.APPLICATION_JSON})
345   public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
346                               @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
347                               @Context UriInfo uriInfo, @Context HttpServletRequest req) {
348
349     LoggingUtil.initMdcContext(req, headers);
350
351     logger.debug("Incoming request..." + content);
352     Response response = null;
353
354     try {
355       if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
356         VertexPayload payload = VertexPayload.fromJson(content);
357         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
358           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
359         }
360         if (payload.getId() != null && !payload.getId().equals(id)) {
361           throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
362         }
363
364         payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
365
366         String result = graphDataService.patchVertex(version, id, type, payload);
367         response = Response.status(Status.OK).entity(result).type(mediaType).build();
368       } else {
369         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
370       }
371     } catch (CrudException ce) {
372       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
373     } catch (Exception e) {
374       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
375     }
376
377     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
378     return response;
379   }
380
381   @POST
382   @Path("/{version}/{type}/")
383   @Consumes({MediaType.APPLICATION_JSON})
384   @Produces({MediaType.APPLICATION_JSON})
385   public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
386                             @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
387                             @Context HttpServletRequest req) {
388
389     LoggingUtil.initMdcContext(req, headers);
390
391     logger.debug("Incoming request..." + content);
392     Response response = null;
393
394
395     try {
396       if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
397         VertexPayload payload = VertexPayload.fromJson(content);
398         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
399           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
400         }
401         if (payload.getId() != null) {
402           throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
403         }
404
405         if (payload.getType() != null && !payload.getType().equals(type)) {
406           throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
407         }
408
409         payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
410
411         String result = graphDataService.addVertex(version, type, payload);
412         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
413       } else {
414         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
415       }
416     } catch (CrudException ce) {
417       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
418     } catch (Exception e) {
419       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
420     }
421
422     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
423     return response;
424   }
425
426   private void validateBulkPayload(BulkPayload payload) throws CrudException {
427     List<String> vertices = new ArrayList<String>();
428     List<String> edges = new ArrayList<String>();
429
430     for (JsonElement v : payload.getObjects()) {
431       List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
432           v.getAsJsonObject().entrySet());
433
434       if (entries.size() != 2) {
435         throw new CrudException("", Status.BAD_REQUEST);
436       }
437       Map.Entry<String, JsonElement> opr = entries.get(0);
438       Map.Entry<String, JsonElement> item = entries.get(1);
439
440       if (vertices.contains(item.getKey())) {
441         throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
442       }
443       VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
444       if (vertexPayload.getType() == null) {
445         throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
446       }
447
448       if (!opr.getKey().equalsIgnoreCase("operation")) {
449         throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
450       }
451
452       if (!opr.getValue().getAsString().equalsIgnoreCase("add")
453           && !opr.getValue().getAsString().equalsIgnoreCase("modify")
454           && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
455         throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
456       }
457       // check if ID is populate for modify/delete operation
458       if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
459           || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
460
461         throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
462
463       }
464
465       vertices.add(item.getKey());
466     }
467
468     for (JsonElement v : payload.getRelationships()) {
469       List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
470           v.getAsJsonObject().entrySet());
471
472       if (entries.size() != 2) {
473         throw new CrudException("", Status.BAD_REQUEST);
474       }
475       Map.Entry<String, JsonElement> opr = entries.get(0);
476       Map.Entry<String, JsonElement> item = entries.get(1);
477
478       if (edges.contains(item.getKey())) {
479         throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
480       }
481
482       EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
483
484       if (edgePayload.getType() == null) {
485         throw new CrudException("Edge Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
486       }
487
488       if (!opr.getKey().equalsIgnoreCase("operation")) {
489         throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
490       }
491
492       if (!opr.getValue().getAsString().equalsIgnoreCase("add")
493           && !opr.getValue().getAsString().equalsIgnoreCase("modify")
494           && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
495         throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
496       }
497       // check if ID is populate for modify/delete operation
498       if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
499           || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
500
501         throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
502
503       }
504       if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
505         if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
506           throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(), Status.BAD_REQUEST);
507         }
508         if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
509           throw new CrudException(
510               "Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
511               Status.BAD_REQUEST);
512         }
513
514         if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
515           throw new CrudException(
516               "Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
517               Status.BAD_REQUEST);
518         }
519       }
520       edges.add(item.getKey());
521
522     }
523
524   }
525
526   @POST
527   @Path("/{version}/bulk/")
528   @Consumes({MediaType.APPLICATION_JSON})
529   @Produces({MediaType.APPLICATION_JSON})
530   public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
531                           @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
532                           @Context HttpServletRequest req) {
533
534     LoggingUtil.initMdcContext(req, headers);
535
536     logger.debug("Incoming request..." + content);
537     Response response = null;
538
539
540     try {
541       if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
542         BulkPayload payload = BulkPayload.fromJson(content);
543         if ((payload.getObjects() == null && payload.getRelationships() == null)
544             || (payload.getObjects() != null && payload.getObjects().isEmpty() && payload.getRelationships() != null
545             && payload.getRelationships().isEmpty())) {
546           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
547         }
548
549         validateBulkPayload(payload);
550         String result = graphDataService.addBulk(version, payload, headers);
551         response = Response.status(Status.OK).entity(result).type(mediaType).build();
552       } else {
553         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
554       }
555     } catch (CrudException ce) {
556       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
557     } catch (Exception e) {
558       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
559     }
560
561     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
562     return response;
563   }
564
565   @POST
566   @Path("/{version}/")
567   @Consumes({MediaType.APPLICATION_JSON})
568   @Produces({MediaType.APPLICATION_JSON})
569   public Response addVertex(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
570                             @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
571
572     LoggingUtil.initMdcContext(req, headers);
573
574     logger.debug("Incoming request..." + content);
575     Response response = null;
576
577     try {
578
579       if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
580         VertexPayload payload = VertexPayload.fromJson(content);
581         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
582           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
583         }
584         if (payload.getId() != null) {
585           throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
586         }
587
588         if (payload.getType() == null || payload.getType().isEmpty()) {
589           throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
590         }
591
592         payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
593
594         String result = graphDataService.addVertex(version, payload.getType(), payload);
595         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
596       } else {
597         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
598       }
599     } catch (CrudException ce) {
600       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
601     } catch (Exception e) {
602       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
603     }
604
605     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
606     return response;
607   }
608
609   @POST
610   @Path("/relationships/{version}/{type}/")
611   @Consumes({MediaType.APPLICATION_JSON})
612   @Produces({MediaType.APPLICATION_JSON})
613   public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
614                           @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
615                           @Context HttpServletRequest req) {
616
617     LoggingUtil.initMdcContext(req, headers);
618
619     logger.debug("Incoming request..." + content);
620     Response response = null;
621
622
623     try {
624       if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
625         EdgePayload payload = EdgePayload.fromJson(content);
626         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
627           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
628         }
629         if (payload.getId() != null) {
630           throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
631         }
632
633         if (payload.getType() != null && !payload.getType().equals(type)) {
634           throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
635         }
636         String result = graphDataService.addEdge(version, type, payload);
637         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
638       } else {
639         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
640       }
641     } catch (CrudException ce) {
642       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
643     } catch (Exception e) {
644       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
645     }
646
647     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
648     return response;
649   }
650
651   @POST
652   @Path("/relationships/{version}/")
653   @Consumes({MediaType.APPLICATION_JSON})
654   @Produces({MediaType.APPLICATION_JSON})
655   public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
656                           @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
657
658     LoggingUtil.initMdcContext(req, headers);
659
660     logger.debug("Incoming request..." + content);
661     Response response = null;
662
663
664     try {
665       if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
666         EdgePayload payload = EdgePayload.fromJson(content);
667         if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
668           throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
669         }
670         if (payload.getId() != null) {
671           throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
672         }
673
674         if (payload.getType() == null || payload.getType().isEmpty()) {
675           throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST);
676         }
677         String result = graphDataService.addEdge(version, payload.getType(), payload);
678
679         response = Response.status(Status.CREATED).entity(result).type(mediaType).build();
680       } else {
681         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
682       }
683     } catch (CrudException ce) {
684       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
685     } catch (Exception e) {
686       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
687     }
688
689     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
690     return response;
691   }
692
693   @DELETE
694   @Path("/{version}/{type}/{id}")
695   @Consumes({MediaType.APPLICATION_JSON})
696   @Produces({MediaType.APPLICATION_JSON})
697   public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
698                                @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
699                                @Context UriInfo uriInfo, @Context HttpServletRequest req) {
700
701     LoggingUtil.initMdcContext(req, headers);
702
703     logger.debug("Incoming request..." + content);
704     Response response = null;
705
706
707     try {
708       if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
709         String result = graphDataService.deleteVertex(version, id, type);
710         response = Response.status(Status.OK).entity(result).type(mediaType).build();
711       } else {
712         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
713       }
714     } catch (CrudException ce) {
715       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
716     } catch (Exception e) {
717       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
718     }
719
720     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
721     return response;
722   }
723
724   @DELETE
725   @Path("/relationships/{version}/{type}/{id}")
726   @Consumes({MediaType.APPLICATION_JSON})
727   @Produces({MediaType.APPLICATION_JSON})
728   public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
729                              @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
730                              @Context UriInfo uriInfo, @Context HttpServletRequest req) {
731
732     LoggingUtil.initMdcContext(req, headers);
733
734     logger.debug("Incoming request..." + content);
735     Response response = null;
736
737     try {
738       if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
739         String result = graphDataService.deleteEdge(version, id, type);
740         response = Response.status(Status.OK).entity(result).type(mediaType).build();
741       } else {
742         response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
743       }
744     } catch (CrudException ce) {
745       response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
746     } catch (Exception e) {
747       response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
748     }
749
750     LoggingUtil.logRestRequest(logger, auditLogger, req, response);
751     return response;
752   }
753
754   protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
755                                     String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
756     boolean isValid = false;
757     try {
758       String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
759       String authUser = null;
760       if (cipherSuite != null) {
761         X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
762         X509Certificate clientCert = certChain[0];
763         X500Principal subjectDn = clientCert.getSubjectX500Principal();
764         authUser = subjectDn.toString();
765       }
766       isValid = this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName);
767     } catch (Exception e) {
768       logResult(action, uri, e);
769       return false;
770     }
771
772     String sourceOfTruth = null;
773     if (headers.getRequestHeaders().containsKey("X-FromAppId")) {
774       sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
775     }
776
777     if (sourceOfTruth == null || sourceOfTruth.trim() == "") {
778       throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST);
779     }
780
781     return isValid;
782   }
783
784   void logResult(Action op, String uri, Exception e) {
785
786     logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString());
787
788     // Clear the MDC context so that no other transaction inadvertently
789     // uses our transaction id.
790     MDC.clear();
791   }
792 }