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 com.google.gson.JsonElement;
24 import java.security.cert.X509Certificate;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
31 import javax.security.auth.x500.X500Principal;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.Encoded;
36 import javax.ws.rs.GET;
37 import javax.ws.rs.POST;
38 import javax.ws.rs.PUT;
39 import javax.ws.rs.Path;
40 import javax.ws.rs.PathParam;
41 import javax.ws.rs.Produces;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.EntityTag;
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.ResponseBuilder;
48 import javax.ws.rs.core.Response.Status;
49 import javax.ws.rs.core.UriInfo;
50 import org.apache.commons.lang3.tuple.ImmutablePair;
51 import org.apache.cxf.jaxrs.ext.PATCH;
52 import org.onap.aai.cl.api.Logger;
53 import org.onap.aai.cl.eelf.LoggerFactory;
54 import org.onap.aaiauth.auth.Auth;
55 import org.onap.crud.exception.CrudException;
56 import org.onap.crud.logging.CrudServiceMsgs;
57 import org.onap.crud.logging.LoggingUtil;
58 import org.onap.crud.parser.BulkPayload;
59 import org.onap.crud.parser.EdgePayload;
60 import org.onap.crud.parser.VertexPayload;
61 import org.onap.crud.util.CrudProperties;
62 import org.onap.crud.util.CrudServiceConstants;
63 import org.onap.crud.util.CrudServiceUtil;
66 @Path("/services/inventory")
67 public class CrudRestService {
69 private AbstractGraphDataService graphDataService;
70 Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
71 Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
74 private String mediaType = MediaType.APPLICATION_JSON;
75 public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
76 public static final String TRANSACTIONID_HEADER = "X-TransactionId";
78 public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
79 this.graphDataService = graphDataService;
80 this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
84 public CrudRestService(AbstractGraphDataService graphDataService, Auth auth) throws Exception {
85 this.graphDataService = graphDataService;
90 POST, GET, PUT, DELETE, PATCH
93 public void startup() {
98 @Path("/{version}/{type}/{id}")
99 @Consumes({MediaType.APPLICATION_JSON})
100 @Produces({MediaType.APPLICATION_JSON})
101 public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
102 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
103 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
105 LoggingUtil.initMdcContext(req, headers);
106 logger.debug("Incoming request..." + content);
108 ResponseBuilder responseBuilder;
109 Map<String, String> params = addParams(uriInfo, false, type, version);
112 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
113 ImmutablePair<EntityTag, String> result = graphDataService.getVertex(version, id, type, params);
115 Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
117 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
119 } catch (CrudException ce) {
120 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
121 } catch (Exception e) {
122 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
126 setTxIdOnResponseHeader(headers, responseBuilder);
128 Response response = responseBuilder.build();
129 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
134 @Path("/{version}/{type}/")
135 @Consumes({MediaType.APPLICATION_JSON})
136 @Produces({MediaType.APPLICATION_JSON})
137 public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
138 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
139 @Context HttpServletRequest req) {
141 LoggingUtil.initMdcContext(req, headers);
142 logger.debug("Incoming request..." + content);
144 ResponseBuilder responseBuilder;
146 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
147 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
148 Map<String, String> filter = addParams(uriInfo, true, type, version);
150 HashSet<String> properties;
151 if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
152 properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
154 properties = new HashSet<>();
157 ImmutablePair<EntityTag, String> result =
158 graphDataService.getVertices(version, type, filter, properties);
160 Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
162 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
164 } catch (CrudException ce) {
165 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
166 } catch (Exception e) {
167 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
171 setTxIdOnResponseHeader(headers, responseBuilder);
173 Response response = responseBuilder.build();
174 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
179 @Path("/relationships/{version}/{type}/{id}")
180 @Consumes({MediaType.APPLICATION_JSON})
181 @Produces({MediaType.APPLICATION_JSON})
182 public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
183 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
184 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
186 LoggingUtil.initMdcContext(req, headers);
187 logger.debug("Incoming request..." + content);
189 ResponseBuilder responseBuilder;
190 Map<String, String> params = addParams(uriInfo, false, type, version);
193 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
195 ImmutablePair<EntityTag, String> result = graphDataService.getEdge(version, id, type, params);
197 Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
199 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
201 } catch (CrudException ce) {
202 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
203 } catch (Exception e) {
204 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
207 setTxIdOnResponseHeader(headers, responseBuilder);
209 Response response = responseBuilder.build();
210 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
215 @Path("/relationships/{version}/{type}/")
216 @Consumes({MediaType.APPLICATION_JSON})
217 @Produces({MediaType.APPLICATION_JSON})
218 public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
219 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
220 @Context HttpServletRequest req) {
222 LoggingUtil.initMdcContext(req, headers);
223 logger.debug("Incoming request..." + content);
225 ResponseBuilder responseBuilder;
226 Map<String, String> filter = addParams(uriInfo, true, type, version);
229 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
230 ImmutablePair<EntityTag, String> result = graphDataService.getEdges(version, type, filter);
232 Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType);
234 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
236 } catch (CrudException ce) {
237 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
238 } catch (Exception e) {
239 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
242 setTxIdOnResponseHeader(headers, responseBuilder);
244 Response response = responseBuilder.build();
245 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
250 @Path("/relationships/{version}/{type}/{id}")
251 @Consumes({MediaType.APPLICATION_JSON})
252 @Produces({MediaType.APPLICATION_JSON})
253 public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
254 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
255 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
257 LoggingUtil.initMdcContext(req, headers);
258 logger.debug("Incoming request..." + content);
260 ResponseBuilder responseBuilder;
263 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
264 EdgePayload payload = EdgePayload.fromJson(content);
265 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
266 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
268 if (payload.getId() != null && !payload.getId().equals(id)) {
269 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
271 ImmutablePair<EntityTag, String> result;
272 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
273 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
274 result = graphDataService.patchEdge(version, id, type, payload);
276 Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
278 result = graphDataService.updateEdge(version, id, type, payload);
280 Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
284 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
286 } catch (CrudException ce) {
287 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
288 } catch (Exception e) {
289 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
292 setTxIdOnResponseHeader(headers, responseBuilder);
294 Response response = responseBuilder.build();
295 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
300 @Path("/relationships/{version}/{type}/{id}")
301 @Consumes({"application/merge-patch+json"})
302 @Produces({MediaType.APPLICATION_JSON})
303 public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
304 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
305 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
307 LoggingUtil.initMdcContext(req, headers);
308 logger.debug("Incoming request..." + content);
310 ResponseBuilder responseBuilder;
313 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
314 EdgePayload payload = EdgePayload.fromJson(content);
315 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
316 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
318 if (payload.getId() != null && !payload.getId().equals(id)) {
319 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
322 ImmutablePair<EntityTag, String> result = graphDataService.patchEdge(version, id, type, payload);
324 Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
326 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
328 } catch (CrudException ce) {
329 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
330 } catch (Exception e) {
331 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
334 setTxIdOnResponseHeader(headers, responseBuilder);
336 Response response = responseBuilder.build();
337 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
342 @Path("/{version}/{type}/{id}")
343 @Consumes({MediaType.APPLICATION_JSON})
344 @Produces({MediaType.APPLICATION_JSON})
345 public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
346 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
347 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
349 LoggingUtil.initMdcContext(req, headers);
350 logger.debug("Incoming request..." + content);
352 ResponseBuilder responseBuilder;
355 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
356 VertexPayload payload = VertexPayload.fromJson(content);
357 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
358 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
360 if (payload.getId() != null && !payload.getId().equals(id)) {
361 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
364 payload.setProperties(
365 CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
367 ImmutablePair<EntityTag, String> result;
368 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
369 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
370 result = graphDataService.patchVertex(version, id, type, payload);
372 Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
374 result = graphDataService.updateVertex(version, id, type, payload);
376 Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
380 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
382 } catch (CrudException ce) {
383 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
384 } catch (Exception e) {
385 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
388 setTxIdOnResponseHeader(headers, responseBuilder);
390 Response response = responseBuilder.build();
391 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
396 @Path("/{version}/{type}/{id}")
397 @Consumes({"application/merge-patch+json"})
398 @Produces({MediaType.APPLICATION_JSON})
399 public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
400 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
401 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
403 LoggingUtil.initMdcContext(req, headers);
404 logger.debug("Incoming request..." + content);
406 ResponseBuilder responseBuilder;
409 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
410 VertexPayload payload = VertexPayload.fromJson(content);
411 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
412 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
414 if (payload.getId() != null && !payload.getId().equals(id)) {
415 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
418 payload.setProperties(
419 CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
421 ImmutablePair<EntityTag, String> result = graphDataService.patchVertex(version, id, type, payload);
423 Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey());
425 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
427 } catch (CrudException ce) {
428 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
429 } catch (Exception e) {
430 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
433 setTxIdOnResponseHeader(headers, responseBuilder);
435 Response response = responseBuilder.build();
436 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
441 @Path("/{version}/{type}/")
442 @Consumes({MediaType.APPLICATION_JSON})
443 @Produces({MediaType.APPLICATION_JSON})
444 public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
445 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
446 @Context HttpServletRequest req) {
448 LoggingUtil.initMdcContext(req, headers);
449 logger.debug("Incoming request..." + content);
451 ResponseBuilder responseBuilder;
454 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
455 VertexPayload payload = VertexPayload.fromJson(content);
456 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
457 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
459 if (payload.getId() != null) {
460 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
463 if (payload.getType() != null && !payload.getType().equals(type)) {
464 throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
467 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
469 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, type, payload);
471 Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
473 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
475 } catch (CrudException ce) {
476 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
477 } catch (Exception e) {
478 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
481 setTxIdOnResponseHeader(headers, responseBuilder);
483 Response response = responseBuilder.build();
484 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
488 private void validateBulkPayload(BulkPayload payload) throws CrudException {
489 List<String> vertices = new ArrayList<String>();
490 List<String> edges = new ArrayList<String>();
492 for (JsonElement v : payload.getObjects()) {
493 List<Map.Entry<String, JsonElement>> entries =
494 new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
496 if (entries.size() != 2) {
497 throw new CrudException("", Status.BAD_REQUEST);
499 Map.Entry<String, JsonElement> opr = entries.get(0);
500 Map.Entry<String, JsonElement> item = entries.get(1);
502 if (vertices.contains(item.getKey())) {
503 throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
505 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
506 if (vertexPayload.getType() == null) {
507 throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
510 if (!opr.getKey().equalsIgnoreCase("operation")) {
511 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
514 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
515 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
516 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
517 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
518 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
520 // check if ID is populate for modify/patch/delete operation
521 if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
522 || opr.getValue().getAsString().equalsIgnoreCase("patch")
523 || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
525 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
529 vertices.add(item.getKey());
532 for (JsonElement v : payload.getRelationships()) {
533 List<Map.Entry<String, JsonElement>> entries =
534 new ArrayList<Map.Entry<String, JsonElement>>(v.getAsJsonObject().entrySet());
536 if (entries.size() != 2) {
537 throw new CrudException("", Status.BAD_REQUEST);
539 Map.Entry<String, JsonElement> opr = entries.get(0);
540 Map.Entry<String, JsonElement> item = entries.get(1);
542 if (edges.contains(item.getKey())) {
543 throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
546 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
548 if (!opr.getKey().equalsIgnoreCase("operation")) {
549 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
552 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
553 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
554 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
555 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
556 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
558 // check if ID is populate for modify/patch/delete operation
559 if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
560 || opr.getValue().getAsString().equalsIgnoreCase("patch")
561 || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
563 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
566 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
567 if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
568 throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(),
571 if (edgePayload.getSource().startsWith("$")
572 && !vertices.contains(edgePayload.getSource().substring(1))) {
573 throw new CrudException("Source Vertex " + edgePayload.getSource().substring(1)
574 + " not found for Edge: " + item.getKey(), Status.BAD_REQUEST);
577 if (edgePayload.getTarget().startsWith("$")
578 && !vertices.contains(edgePayload.getTarget().substring(1))) {
579 throw new CrudException("Target Vertex " + edgePayload.getSource().substring(1)
580 + " not found for Edge: " + item.getKey(), Status.BAD_REQUEST);
583 edges.add(item.getKey());
590 @Path("/{version}/bulk/")
591 @Consumes({MediaType.APPLICATION_JSON})
592 @Produces({MediaType.APPLICATION_JSON})
593 public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
594 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
595 @Context HttpServletRequest req) {
597 LoggingUtil.initMdcContext(req, headers);
598 logger.debug("Incoming request..." + content);
600 ResponseBuilder responseBuilder;
603 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
604 BulkPayload payload = BulkPayload.fromJson(content);
605 if ((payload.getObjects() == null && payload.getRelationships() == null)
606 || (payload.getObjects() != null && payload.getObjects().isEmpty()
607 && payload.getRelationships() != null && payload.getRelationships().isEmpty())) {
608 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
611 validateBulkPayload(payload);
612 String result = graphDataService.addBulk(version, payload, headers);
613 responseBuilder = Response.status(Status.OK).entity(result).type(mediaType);
615 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
617 } catch (CrudException ce) {
618 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
619 } catch (Exception e) {
620 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
623 setTxIdOnResponseHeader(headers, responseBuilder);
625 Response response = responseBuilder.build();
626 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
632 @Consumes({MediaType.APPLICATION_JSON})
633 @Produces({MediaType.APPLICATION_JSON})
634 public Response addVertex(String content, @PathParam("version") String version,
635 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
636 @Context HttpServletRequest req) {
638 LoggingUtil.initMdcContext(req, headers);
639 logger.debug("Incoming request..." + content);
641 ResponseBuilder responseBuilder;
645 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
646 VertexPayload payload = VertexPayload.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 Vertex", Status.BAD_REQUEST);
654 if (payload.getType() == null || payload.getType().isEmpty()) {
655 throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
658 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
660 ImmutablePair<EntityTag, String> result =
661 graphDataService.addVertex(version, payload.getType(), payload);
663 Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
665 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
667 } catch (CrudException ce) {
668 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
669 } catch (Exception e) {
670 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
673 setTxIdOnResponseHeader(headers, responseBuilder);
675 Response response = responseBuilder.build();
676 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
681 @Path("/relationships/{version}/{type}/")
682 @Consumes({MediaType.APPLICATION_JSON})
683 @Produces({MediaType.APPLICATION_JSON})
684 public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
685 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
686 @Context HttpServletRequest req) {
688 LoggingUtil.initMdcContext(req, headers);
689 logger.debug("Incoming request..." + content);
691 ResponseBuilder responseBuilder;
694 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
695 EdgePayload payload = EdgePayload.fromJson(content);
696 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
697 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
699 if (payload.getId() != null) {
700 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
703 if (payload.getType() != null && !payload.getType().equals(type)) {
704 throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
706 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, type, payload);
708 Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
710 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
712 } catch (CrudException ce) {
713 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
714 } catch (Exception e) {
715 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
718 setTxIdOnResponseHeader(headers, responseBuilder);
720 Response response = responseBuilder.build();
721 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
726 @Path("/relationships/{version}/")
727 @Consumes({MediaType.APPLICATION_JSON})
728 @Produces({MediaType.APPLICATION_JSON})
729 public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
730 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
732 LoggingUtil.initMdcContext(req, headers);
733 logger.debug("Incoming request..." + content);
735 ResponseBuilder responseBuilder;
738 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
739 EdgePayload payload = EdgePayload.fromJson(content);
740 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
741 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
743 if (payload.getId() != null) {
744 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
747 if (payload.getType() == null || payload.getType().isEmpty()) {
748 payload.setType(CrudServiceUtil.determineEdgeType(payload, version));
751 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, payload.getType(), payload);
753 Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType);
755 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
757 } catch (CrudException ce) {
758 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
759 } catch (Exception e) {
760 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
763 setTxIdOnResponseHeader(headers, responseBuilder);
765 Response response = responseBuilder.build();
766 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
771 @Path("/{version}/{type}/{id}")
772 @Consumes({MediaType.APPLICATION_JSON})
773 @Produces({MediaType.APPLICATION_JSON})
774 public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
775 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
776 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
778 LoggingUtil.initMdcContext(req, headers);
779 logger.debug("Incoming request..." + content);
781 ResponseBuilder responseBuilder;
784 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
785 String result = graphDataService.deleteVertex(version, id, type);
786 responseBuilder = Response.status(Status.OK).entity(result).type(mediaType);
788 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
790 } catch (CrudException ce) {
791 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
792 } catch (Exception e) {
793 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
796 setTxIdOnResponseHeader(headers, responseBuilder);
798 Response response = responseBuilder.build();
799 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
804 @Path("/relationships/{version}/{type}/{id}")
805 @Consumes({MediaType.APPLICATION_JSON})
806 @Produces({MediaType.APPLICATION_JSON})
807 public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
808 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
809 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
811 LoggingUtil.initMdcContext(req, headers);
812 logger.debug("Incoming request..." + content);
814 ResponseBuilder responseBuilder;
817 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
818 String result = graphDataService.deleteEdge(version, id, type);
819 responseBuilder = Response.status(Status.OK).entity(result).type(mediaType);
821 responseBuilder = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON);
823 } catch (CrudException ce) {
824 responseBuilder = Response.status(ce.getHttpStatus()).entity(ce.getMessage());
825 } catch (Exception e) {
826 responseBuilder = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage());
829 setTxIdOnResponseHeader(headers, responseBuilder);
831 Response response = responseBuilder.build();
832 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
836 protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
837 String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
838 boolean isValid = false;
840 String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
841 String authUser = null;
842 if (cipherSuite != null) {
843 X509Certificate[] certChain =
844 (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
845 X509Certificate clientCert = certChain[0];
846 X500Principal subjectDn = clientCert.getSubjectX500Principal();
847 authUser = subjectDn.toString();
849 if (null != authUser) {
850 isValid = this.auth.validateRequest(authUser.toLowerCase(),
851 action.toString() + ":" + authPolicyFunctionName);
853 } catch (Exception e) {
854 logResult(action, uri, e);
858 validateRequestHeader(headers);
863 public void validateRequestHeader(HttpHeaders headers) throws CrudException {
864 String sourceOfTruth = null;
865 if (headers.getRequestHeaders().containsKey("X-FromAppId")) {
866 sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
869 if (sourceOfTruth == null || sourceOfTruth.trim() == "") {
870 throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST);
873 String transId = null;
874 if (headers.getRequestHeaders().containsKey("X-TransactionId")) {
875 transId = headers.getRequestHeaders().getFirst("X-TransactionId");
878 if (transId == null || transId.trim() == "") {
879 throw new CrudException("Invalid request, Missing X-TransactionId header", Status.BAD_REQUEST);
883 void logResult(Action op, String uri, Exception e) {
885 logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri,
886 Arrays.toString(e.getStackTrace()));
888 // Clear the MDC context so that no other transaction inadvertently
889 // uses our transaction id.
893 private Map<String, String> addParams(UriInfo info, boolean filter, String type, String version) {
894 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
895 Map<String, String> params = new HashMap<String, String>();
896 params.put(CrudServiceConstants.CRD_RESERVED_VERSION, version);
897 params.put(CrudServiceConstants.CRD_RESERVED_NODE_TYPE, type);
899 for (Map.Entry<String, List<String>> e : info.getQueryParameters().entrySet()) {
900 if (!e.getKey().equals(propertiesKey)) {
901 params.put(e.getKey(), e.getValue().get(0));
905 for (Map.Entry<String, List<String>> e : info.getQueryParameters().entrySet()) {
906 params.put(e.getKey(), e.getValue().get(0));
912 private void setTxIdOnResponseHeader(HttpHeaders headers, ResponseBuilder responseBuilder) {
913 String txId = headers.getHeaderString(TRANSACTIONID_HEADER);
915 responseBuilder.header(TRANSACTIONID_HEADER, txId);