2 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.crud.service;
23 import java.security.cert.X509Certificate;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
29 import javax.security.auth.x500.X500Principal;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.ws.rs.Consumes;
32 import javax.ws.rs.DELETE;
33 import javax.ws.rs.Encoded;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.POST;
36 import javax.ws.rs.PUT;
37 import javax.ws.rs.Path;
38 import javax.ws.rs.PathParam;
39 import javax.ws.rs.Produces;
40 import javax.ws.rs.core.Context;
41 import javax.ws.rs.core.EntityTag;
42 import javax.ws.rs.core.HttpHeaders;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.Response;
45 import javax.ws.rs.core.Response.Status;
46 import javax.ws.rs.core.UriInfo;
47 import org.apache.commons.lang3.tuple.ImmutablePair;
48 import org.apache.cxf.jaxrs.ext.PATCH;
49 import org.onap.aai.cl.api.Logger;
50 import org.onap.aai.cl.eelf.LoggerFactory;
51 import org.onap.aaiauth.auth.Auth;
52 import org.onap.crud.exception.CrudException;
53 import org.onap.crud.logging.CrudServiceMsgs;
54 import org.onap.crud.logging.LoggingUtil;
55 import org.onap.crud.util.CrudProperties;
56 import org.onap.crud.util.CrudServiceConstants;
57 import org.onap.crud.util.CrudServiceUtil;
59 import com.google.gson.JsonElement;
61 @Path("/services/inventory")
62 public class CrudRestService {
64 private AbstractGraphDataService graphDataService;
65 Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
66 Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
69 private String mediaType = MediaType.APPLICATION_JSON;
70 public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
72 public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
73 this.graphDataService = graphDataService;
74 this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
78 public CrudRestService(AbstractGraphDataService graphDataService, Auth auth) throws Exception {
79 this.graphDataService = graphDataService;
84 POST, GET, PUT, DELETE, PATCH
87 public void startup() {
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);
100 logger.debug("Incoming request..." + content);
101 Response response = null;
103 Map<String, String> params = addParams ( uriInfo, false, type, version );
106 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
107 ImmutablePair<EntityTag, String> result = graphDataService.getVertex(version, id, type, params);
108 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
110 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
112 } catch (CrudException ce) {
113 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
114 } catch (Exception e) {
115 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
119 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
124 @Path("/{version}/{type}/")
125 @Consumes({MediaType.APPLICATION_JSON})
126 @Produces({MediaType.APPLICATION_JSON})
127 public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
128 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
129 @Context HttpServletRequest req) {
131 LoggingUtil.initMdcContext(req, headers);
133 logger.debug("Incoming request..." + content);
134 Response response = null;
136 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
137 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
138 Map<String, String> filter = addParams ( uriInfo, true, type, version );
140 HashSet<String> properties;
141 if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
142 properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
144 properties = new HashSet<>();
147 ImmutablePair<EntityTag, String> result = graphDataService.getVertices(version, type, filter, properties);
148 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
150 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
152 } catch (CrudException ce) {
153 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
154 } catch (Exception e) {
155 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
159 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
164 @Path("/relationships/{version}/{type}/{id}")
165 @Consumes({MediaType.APPLICATION_JSON})
166 @Produces({MediaType.APPLICATION_JSON})
167 public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
168 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
169 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
170 LoggingUtil.initMdcContext(req, headers);
172 logger.debug("Incoming request..." + content);
173 Response response = null;
175 Map<String, String> params = addParams ( uriInfo, false, type, version );
178 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
180 ImmutablePair<EntityTag, String> result = graphDataService.getEdge(version, id, type, params);
181 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
183 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
185 } catch (CrudException ce) {
186 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
187 } catch (Exception e) {
188 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
191 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
196 @Path("/relationships/{version}/{type}/")
197 @Consumes({MediaType.APPLICATION_JSON})
198 @Produces({MediaType.APPLICATION_JSON})
199 public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
200 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
201 @Context HttpServletRequest req) {
203 LoggingUtil.initMdcContext(req, headers);
205 logger.debug("Incoming request..." + content);
206 Response response = null;
207 Map<String, String> filter = addParams ( uriInfo, true, type, version );
210 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
211 ImmutablePair<EntityTag, String> result = graphDataService.getEdges(version, type, filter);
212 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
214 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
216 } catch (CrudException ce) {
217 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
218 } catch (Exception e) {
219 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
222 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
227 @Path("/relationships/{version}/{type}/{id}")
228 @Consumes({MediaType.APPLICATION_JSON})
229 @Produces({MediaType.APPLICATION_JSON})
230 public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
231 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
232 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
234 LoggingUtil.initMdcContext(req, headers);
236 logger.debug("Incoming request..." + content);
237 Response response = null;
241 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
242 EdgePayload payload = EdgePayload.fromJson(content);
243 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
244 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
246 if (payload.getId() != null && !payload.getId().equals(id)) {
247 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
249 ImmutablePair<EntityTag, String> result;
250 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
251 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
252 result = graphDataService.patchEdge(version, id, type, payload);
253 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
255 result = graphDataService.updateEdge(version, id, type, payload);
256 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
260 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
262 } catch (CrudException ce) {
263 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
264 } catch (Exception e) {
265 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
268 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
273 @Path("/relationships/{version}/{type}/{id}")
274 @Consumes({"application/merge-patch+json"})
275 @Produces({MediaType.APPLICATION_JSON})
276 public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
277 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
278 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
280 LoggingUtil.initMdcContext(req, headers);
282 logger.debug("Incoming request..." + content);
283 Response response = null;
286 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
287 EdgePayload payload = EdgePayload.fromJson(content);
288 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
289 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
291 if (payload.getId() != null && !payload.getId().equals(id)) {
292 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
295 ImmutablePair<EntityTag, String> result = graphDataService.patchEdge(version, id, type, payload);
296 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
298 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
300 } catch (CrudException ce) {
301 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
302 } catch (Exception e) {
303 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
306 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
311 @Path("/{version}/{type}/{id}")
312 @Consumes({MediaType.APPLICATION_JSON})
313 @Produces({MediaType.APPLICATION_JSON})
314 public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
315 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
316 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
318 LoggingUtil.initMdcContext(req, headers);
320 logger.debug("Incoming request..." + content);
321 Response response = null;
324 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
325 VertexPayload payload = VertexPayload.fromJson(content);
326 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
327 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
329 if (payload.getId() != null && !payload.getId().equals(id)) {
330 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
333 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
335 ImmutablePair<EntityTag, String> result;
336 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
337 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
338 result = graphDataService.patchVertex(version, id, type, payload);
339 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
341 result = graphDataService.updateVertex(version, id, type, payload);
342 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
346 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
348 } catch (CrudException ce) {
349 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
350 } catch (Exception e) {
351 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
354 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
359 @Path("/{version}/{type}/{id}")
360 @Consumes({"application/merge-patch+json"})
361 @Produces({MediaType.APPLICATION_JSON})
362 public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
363 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
364 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
366 LoggingUtil.initMdcContext(req, headers);
368 logger.debug("Incoming request..." + content);
369 Response response = null;
372 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
373 VertexPayload payload = VertexPayload.fromJson(content);
374 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
375 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
377 if (payload.getId() != null && !payload.getId().equals(id)) {
378 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
381 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
383 ImmutablePair<EntityTag, String> result = graphDataService.patchVertex(version, id, type, payload);
384 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
386 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
388 } catch (CrudException ce) {
389 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
390 } catch (Exception e) {
391 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
394 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
399 @Path("/{version}/{type}/")
400 @Consumes({MediaType.APPLICATION_JSON})
401 @Produces({MediaType.APPLICATION_JSON})
402 public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
403 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
404 @Context HttpServletRequest req) {
406 LoggingUtil.initMdcContext(req, headers);
408 logger.debug("Incoming request..." + content);
409 Response response = null;
413 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
414 VertexPayload payload = VertexPayload.fromJson(content);
415 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
416 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
418 if (payload.getId() != null) {
419 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
422 if (payload.getType() != null && !payload.getType().equals(type)) {
423 throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
426 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
428 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, type, payload);
429 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
431 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
433 } catch (CrudException ce) {
434 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
435 } catch (Exception e) {
436 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
439 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
443 private void validateBulkPayload(BulkPayload payload) throws CrudException {
444 List<String> vertices = new ArrayList<String>();
445 List<String> edges = new ArrayList<String>();
447 for (JsonElement v : payload.getObjects()) {
448 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
449 v.getAsJsonObject().entrySet());
451 if (entries.size() != 2) {
452 throw new CrudException("", Status.BAD_REQUEST);
454 Map.Entry<String, JsonElement> opr = entries.get(0);
455 Map.Entry<String, JsonElement> item = entries.get(1);
457 if (vertices.contains(item.getKey())) {
458 throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
460 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
461 if (vertexPayload.getType() == null) {
462 throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
465 if (!opr.getKey().equalsIgnoreCase("operation")) {
466 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
469 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
470 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
471 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
472 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
473 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
475 // check if ID is populate for modify/patch/delete operation
476 if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
477 || opr.getValue().getAsString().equalsIgnoreCase("patch")
478 || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
480 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
484 vertices.add(item.getKey());
487 for (JsonElement v : payload.getRelationships()) {
488 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
489 v.getAsJsonObject().entrySet());
491 if (entries.size() != 2) {
492 throw new CrudException("", Status.BAD_REQUEST);
494 Map.Entry<String, JsonElement> opr = entries.get(0);
495 Map.Entry<String, JsonElement> item = entries.get(1);
497 if (edges.contains(item.getKey())) {
498 throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
501 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
503 if (edgePayload.getType() == null) {
504 throw new CrudException("Edge Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
507 if (!opr.getKey().equalsIgnoreCase("operation")) {
508 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
511 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
512 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
513 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
514 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
515 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
517 // check if ID is populate for modify/patch/delete operation
518 if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
519 || opr.getValue().getAsString().equalsIgnoreCase("patch")
520 || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
522 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
525 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
526 if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
527 throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(), Status.BAD_REQUEST);
529 if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
530 throw new CrudException(
531 "Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
535 if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
536 throw new CrudException(
537 "Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
541 edges.add(item.getKey());
548 @Path("/{version}/bulk/")
549 @Consumes({MediaType.APPLICATION_JSON})
550 @Produces({MediaType.APPLICATION_JSON})
551 public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
552 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
553 @Context HttpServletRequest req) {
555 LoggingUtil.initMdcContext(req, headers);
557 logger.debug("Incoming request..." + content);
558 Response response = null;
562 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
563 BulkPayload payload = BulkPayload.fromJson(content);
564 if ((payload.getObjects() == null && payload.getRelationships() == null)
565 || (payload.getObjects() != null && payload.getObjects().isEmpty() && payload.getRelationships() != null
566 && payload.getRelationships().isEmpty())) {
567 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
570 validateBulkPayload(payload);
571 String result = graphDataService.addBulk(version, payload, headers);
572 response = Response.status(Status.OK).entity(result).type(mediaType).build();
574 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
576 } catch (CrudException ce) {
577 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
578 } catch (Exception e) {
579 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
582 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
588 @Consumes({MediaType.APPLICATION_JSON})
589 @Produces({MediaType.APPLICATION_JSON})
590 public Response addVertex(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
591 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
593 LoggingUtil.initMdcContext(req, headers);
595 logger.debug("Incoming request..." + content);
596 Response response = null;
600 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
601 VertexPayload payload = VertexPayload.fromJson(content);
602 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
603 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
605 if (payload.getId() != null) {
606 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
609 if (payload.getType() == null || payload.getType().isEmpty()) {
610 throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
613 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
615 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, payload.getType(), payload);
616 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
618 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
620 } catch (CrudException ce) {
621 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
622 } catch (Exception e) {
623 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
626 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
631 @Path("/relationships/{version}/{type}/")
632 @Consumes({MediaType.APPLICATION_JSON})
633 @Produces({MediaType.APPLICATION_JSON})
634 public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
635 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
636 @Context HttpServletRequest req) {
638 LoggingUtil.initMdcContext(req, headers);
640 logger.debug("Incoming request..." + content);
641 Response response = null;
645 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
646 EdgePayload payload = EdgePayload.fromJson(content);
647 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
648 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
650 if (payload.getId() != null) {
651 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
654 if (payload.getType() != null && !payload.getType().equals(type)) {
655 throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
657 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, type, payload);
658 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
660 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
662 } catch (CrudException ce) {
663 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
664 } catch (Exception e) {
665 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
668 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
673 @Path("/relationships/{version}/")
674 @Consumes({MediaType.APPLICATION_JSON})
675 @Produces({MediaType.APPLICATION_JSON})
676 public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
677 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
679 LoggingUtil.initMdcContext(req, headers);
681 logger.debug("Incoming request..." + content);
682 Response response = null;
686 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
687 EdgePayload payload = EdgePayload.fromJson(content);
688 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
689 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
691 if (payload.getId() != null) {
692 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
695 if (payload.getType() == null || payload.getType().isEmpty()) {
696 throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST);
698 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, payload.getType(), payload);
699 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
701 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
703 } catch (CrudException ce) {
704 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
705 } catch (Exception e) {
706 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
709 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
714 @Path("/{version}/{type}/{id}")
715 @Consumes({MediaType.APPLICATION_JSON})
716 @Produces({MediaType.APPLICATION_JSON})
717 public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
718 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
719 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
721 LoggingUtil.initMdcContext(req, headers);
723 logger.debug("Incoming request..." + content);
724 Response response = null;
728 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
729 String result = graphDataService.deleteVertex(version, id, type);
730 response = Response.status(Status.OK).entity(result).type(mediaType).build();
732 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
734 } catch (CrudException ce) {
735 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
736 } catch (Exception e) {
737 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
740 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
745 @Path("/relationships/{version}/{type}/{id}")
746 @Consumes({MediaType.APPLICATION_JSON})
747 @Produces({MediaType.APPLICATION_JSON})
748 public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
749 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
750 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
752 LoggingUtil.initMdcContext(req, headers);
754 logger.debug("Incoming request..." + content);
755 Response response = null;
758 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
759 String result = graphDataService.deleteEdge(version, id, type);
760 response = Response.status(Status.OK).entity(result).type(mediaType).build();
762 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
764 } catch (CrudException ce) {
765 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
766 } catch (Exception e) {
767 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
770 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
774 protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
775 String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
776 boolean isValid = false;
778 String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
779 String authUser = null;
780 if (cipherSuite != null) {
781 X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
782 X509Certificate clientCert = certChain[0];
783 X500Principal subjectDn = clientCert.getSubjectX500Principal();
784 authUser = subjectDn.toString();
786 isValid = this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName);
787 } catch (Exception e) {
788 logResult(action, uri, e);
792 validateRequestHeader(headers);
797 public void validateRequestHeader(HttpHeaders headers) throws CrudException {
798 String sourceOfTruth = null;
799 if (headers.getRequestHeaders().containsKey("X-FromAppId")) {
800 sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
803 if (sourceOfTruth == null || sourceOfTruth.trim() == "") {
804 throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST);
807 String transId = null;
808 if (headers.getRequestHeaders().containsKey("X-TransactionId")) {
809 transId = headers.getRequestHeaders().getFirst("X-TransactionId");
812 if (transId == null || transId.trim() == "") {
813 throw new CrudException("Invalid request, Missing X-TransactionId header", Status.BAD_REQUEST);
817 void logResult(Action op, String uri, Exception e) {
819 logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString());
821 // Clear the MDC context so that no other transaction inadvertently
822 // uses our transaction id.
826 private Map<String, String> addParams ( UriInfo info, boolean filter, String type, String version ) {
827 String propertiesKey = CrudProperties.get ( CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY );
828 Map<String, String> params = new HashMap<String, String> ();
829 params.put ( CrudServiceConstants.CRD_RESERVED_VERSION, version );
830 params.put ( CrudServiceConstants.CRD_RESERVED_NODE_TYPE, type );
832 for (Map.Entry<String, List<String>> e : info.getQueryParameters ().entrySet ()) {
833 if (!e.getKey ().equals ( propertiesKey )) {
834 params.put ( e.getKey (), e.getValue ().get ( 0 ) );
838 for (Map.Entry<String, List<String>> e : info.getQueryParameters ().entrySet ()) {
839 params.put ( e.getKey (), e.getValue ().get ( 0 ) );