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