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