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.parser.BulkPayload;
56 import org.onap.crud.parser.EdgePayload;
57 import org.onap.crud.parser.VertexPayload;
58 import org.onap.crud.util.CrudProperties;
59 import org.onap.crud.util.CrudServiceConstants;
60 import org.onap.crud.util.CrudServiceUtil;
62 import com.google.gson.JsonElement;
64 @Path("/services/inventory")
65 public class CrudRestService {
67 private AbstractGraphDataService graphDataService;
68 Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
69 Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
72 private String mediaType = MediaType.APPLICATION_JSON;
73 public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
75 public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
76 this.graphDataService = graphDataService;
77 this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
81 public CrudRestService(AbstractGraphDataService graphDataService, Auth auth) throws Exception {
82 this.graphDataService = graphDataService;
87 POST, GET, PUT, DELETE, PATCH
90 public void startup() {
95 @Path("/{version}/{type}/{id}")
96 @Consumes({MediaType.APPLICATION_JSON})
97 @Produces({MediaType.APPLICATION_JSON})
98 public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
99 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
100 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
101 LoggingUtil.initMdcContext(req, headers);
103 logger.debug("Incoming request..." + content);
104 Response response = null;
106 Map<String, String> params = addParams ( uriInfo, false, type, version );
109 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
110 ImmutablePair<EntityTag, String> result = graphDataService.getVertex(version, id, type, params);
111 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
113 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
115 } catch (CrudException ce) {
116 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
117 } catch (Exception e) {
118 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
122 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
127 @Path("/{version}/{type}/")
128 @Consumes({MediaType.APPLICATION_JSON})
129 @Produces({MediaType.APPLICATION_JSON})
130 public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
131 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
132 @Context HttpServletRequest req) {
134 LoggingUtil.initMdcContext(req, headers);
136 logger.debug("Incoming request..." + content);
137 Response response = null;
139 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
140 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
141 Map<String, String> filter = addParams ( uriInfo, true, type, version );
143 HashSet<String> properties;
144 if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
145 properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
147 properties = new HashSet<>();
150 ImmutablePair<EntityTag, String> result = graphDataService.getVertices(version, type, filter, properties);
151 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
153 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
155 } catch (CrudException ce) {
156 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
157 } catch (Exception e) {
158 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
162 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
167 @Path("/relationships/{version}/{type}/{id}")
168 @Consumes({MediaType.APPLICATION_JSON})
169 @Produces({MediaType.APPLICATION_JSON})
170 public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
171 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
172 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
173 LoggingUtil.initMdcContext(req, headers);
175 logger.debug("Incoming request..." + content);
176 Response response = null;
178 Map<String, String> params = addParams ( uriInfo, false, type, version );
181 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
183 ImmutablePair<EntityTag, String> result = graphDataService.getEdge(version, id, type, params);
184 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
186 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
188 } catch (CrudException ce) {
189 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
190 } catch (Exception e) {
191 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
194 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
199 @Path("/relationships/{version}/{type}/")
200 @Consumes({MediaType.APPLICATION_JSON})
201 @Produces({MediaType.APPLICATION_JSON})
202 public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
203 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
204 @Context HttpServletRequest req) {
206 LoggingUtil.initMdcContext(req, headers);
208 logger.debug("Incoming request..." + content);
209 Response response = null;
210 Map<String, String> filter = addParams ( uriInfo, true, type, version );
213 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
214 ImmutablePair<EntityTag, String> result = graphDataService.getEdges(version, type, filter);
215 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
217 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
219 } catch (CrudException ce) {
220 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
221 } catch (Exception e) {
222 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
225 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
230 @Path("/relationships/{version}/{type}/{id}")
231 @Consumes({MediaType.APPLICATION_JSON})
232 @Produces({MediaType.APPLICATION_JSON})
233 public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
234 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
235 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
237 LoggingUtil.initMdcContext(req, headers);
239 logger.debug("Incoming request..." + content);
240 Response response = null;
244 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
245 EdgePayload payload = EdgePayload.fromJson(content);
246 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
247 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
249 if (payload.getId() != null && !payload.getId().equals(id)) {
250 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
252 ImmutablePair<EntityTag, String> result;
253 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
254 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
255 result = graphDataService.patchEdge(version, id, type, payload);
256 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
258 result = graphDataService.updateEdge(version, id, type, payload);
259 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
263 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
265 } catch (CrudException ce) {
266 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
267 } catch (Exception e) {
268 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
271 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
276 @Path("/relationships/{version}/{type}/{id}")
277 @Consumes({"application/merge-patch+json"})
278 @Produces({MediaType.APPLICATION_JSON})
279 public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
280 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
281 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
283 LoggingUtil.initMdcContext(req, headers);
285 logger.debug("Incoming request..." + content);
286 Response response = null;
289 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
290 EdgePayload payload = EdgePayload.fromJson(content);
291 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
292 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
294 if (payload.getId() != null && !payload.getId().equals(id)) {
295 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
298 ImmutablePair<EntityTag, String> result = graphDataService.patchEdge(version, id, type, payload);
299 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
301 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
303 } catch (CrudException ce) {
304 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
305 } catch (Exception e) {
306 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
309 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
314 @Path("/{version}/{type}/{id}")
315 @Consumes({MediaType.APPLICATION_JSON})
316 @Produces({MediaType.APPLICATION_JSON})
317 public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
318 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
319 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
321 LoggingUtil.initMdcContext(req, headers);
323 logger.debug("Incoming request..." + content);
324 Response response = null;
327 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
328 VertexPayload payload = VertexPayload.fromJson(content);
329 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
330 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
332 if (payload.getId() != null && !payload.getId().equals(id)) {
333 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
336 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
338 ImmutablePair<EntityTag, String> result;
339 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
340 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
341 result = graphDataService.patchVertex(version, id, type, payload);
342 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
344 result = graphDataService.updateVertex(version, id, type, payload);
345 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
349 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
351 } catch (CrudException ce) {
352 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
353 } catch (Exception e) {
354 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
357 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
362 @Path("/{version}/{type}/{id}")
363 @Consumes({"application/merge-patch+json"})
364 @Produces({MediaType.APPLICATION_JSON})
365 public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
366 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
367 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
369 LoggingUtil.initMdcContext(req, headers);
371 logger.debug("Incoming request..." + content);
372 Response response = null;
375 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
376 VertexPayload payload = VertexPayload.fromJson(content);
377 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
378 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
380 if (payload.getId() != null && !payload.getId().equals(id)) {
381 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
384 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
386 ImmutablePair<EntityTag, String> result = graphDataService.patchVertex(version, id, type, payload);
387 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
389 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
391 } catch (CrudException ce) {
392 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
393 } catch (Exception e) {
394 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
397 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
402 @Path("/{version}/{type}/")
403 @Consumes({MediaType.APPLICATION_JSON})
404 @Produces({MediaType.APPLICATION_JSON})
405 public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
406 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
407 @Context HttpServletRequest req) {
409 LoggingUtil.initMdcContext(req, headers);
411 logger.debug("Incoming request..." + content);
412 Response response = null;
416 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
417 VertexPayload payload = VertexPayload.fromJson(content);
418 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
419 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
421 if (payload.getId() != null) {
422 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
425 if (payload.getType() != null && !payload.getType().equals(type)) {
426 throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
429 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
431 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, type, payload);
432 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
434 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
436 } catch (CrudException ce) {
437 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
438 } catch (Exception e) {
439 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
442 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
446 private void validateBulkPayload(BulkPayload payload) throws CrudException {
447 List<String> vertices = new ArrayList<String>();
448 List<String> edges = new ArrayList<String>();
450 for (JsonElement v : payload.getObjects()) {
451 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
452 v.getAsJsonObject().entrySet());
454 if (entries.size() != 2) {
455 throw new CrudException("", Status.BAD_REQUEST);
457 Map.Entry<String, JsonElement> opr = entries.get(0);
458 Map.Entry<String, JsonElement> item = entries.get(1);
460 if (vertices.contains(item.getKey())) {
461 throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
463 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
464 if (vertexPayload.getType() == null) {
465 throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
468 if (!opr.getKey().equalsIgnoreCase("operation")) {
469 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
472 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
473 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
474 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
475 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
476 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
478 // check if ID is populate for modify/patch/delete operation
479 if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
480 || opr.getValue().getAsString().equalsIgnoreCase("patch")
481 || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
483 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
487 vertices.add(item.getKey());
490 for (JsonElement v : payload.getRelationships()) {
491 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
492 v.getAsJsonObject().entrySet());
494 if (entries.size() != 2) {
495 throw new CrudException("", Status.BAD_REQUEST);
497 Map.Entry<String, JsonElement> opr = entries.get(0);
498 Map.Entry<String, JsonElement> item = entries.get(1);
500 if (edges.contains(item.getKey())) {
501 throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
504 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
506 if (edgePayload.getType() == null) {
507 throw new CrudException("Edge 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 ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
522 || opr.getValue().getAsString().equalsIgnoreCase("patch")
523 || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
525 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
528 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
529 if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
530 throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(), Status.BAD_REQUEST);
532 if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
533 throw new CrudException(
534 "Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
538 if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
539 throw new CrudException(
540 "Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
544 edges.add(item.getKey());
551 @Path("/{version}/bulk/")
552 @Consumes({MediaType.APPLICATION_JSON})
553 @Produces({MediaType.APPLICATION_JSON})
554 public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
555 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
556 @Context HttpServletRequest req) {
558 LoggingUtil.initMdcContext(req, headers);
560 logger.debug("Incoming request..." + content);
561 Response response = null;
565 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
566 BulkPayload payload = BulkPayload.fromJson(content);
567 if ((payload.getObjects() == null && payload.getRelationships() == null)
568 || (payload.getObjects() != null && payload.getObjects().isEmpty() && payload.getRelationships() != null
569 && payload.getRelationships().isEmpty())) {
570 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
573 validateBulkPayload(payload);
574 String result = graphDataService.addBulk(version, payload, headers);
575 response = Response.status(Status.OK).entity(result).type(mediaType).build();
577 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
579 } catch (CrudException ce) {
580 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
581 } catch (Exception e) {
582 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
585 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
591 @Consumes({MediaType.APPLICATION_JSON})
592 @Produces({MediaType.APPLICATION_JSON})
593 public Response addVertex(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
594 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
596 LoggingUtil.initMdcContext(req, headers);
598 logger.debug("Incoming request..." + content);
599 Response response = null;
603 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
604 VertexPayload payload = VertexPayload.fromJson(content);
605 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
606 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
608 if (payload.getId() != null) {
609 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
612 if (payload.getType() == null || payload.getType().isEmpty()) {
613 throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
616 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
618 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, payload.getType(), payload);
619 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
621 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
623 } catch (CrudException ce) {
624 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
625 } catch (Exception e) {
626 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
629 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
634 @Path("/relationships/{version}/{type}/")
635 @Consumes({MediaType.APPLICATION_JSON})
636 @Produces({MediaType.APPLICATION_JSON})
637 public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
638 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
639 @Context HttpServletRequest req) {
641 LoggingUtil.initMdcContext(req, headers);
643 logger.debug("Incoming request..." + content);
644 Response response = null;
648 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
649 EdgePayload payload = EdgePayload.fromJson(content);
650 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
651 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
653 if (payload.getId() != null) {
654 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
657 if (payload.getType() != null && !payload.getType().equals(type)) {
658 throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
660 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, type, payload);
661 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
663 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
665 } catch (CrudException ce) {
666 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
667 } catch (Exception e) {
668 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
671 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
676 @Path("/relationships/{version}/")
677 @Consumes({MediaType.APPLICATION_JSON})
678 @Produces({MediaType.APPLICATION_JSON})
679 public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
680 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
682 LoggingUtil.initMdcContext(req, headers);
684 logger.debug("Incoming request..." + content);
685 Response response = null;
689 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
690 EdgePayload payload = EdgePayload.fromJson(content);
691 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
692 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
694 if (payload.getId() != null) {
695 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
698 if (payload.getType() == null || payload.getType().isEmpty()) {
699 throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST);
701 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, payload.getType(), payload);
702 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
704 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
706 } catch (CrudException ce) {
707 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
708 } catch (Exception e) {
709 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
712 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
717 @Path("/{version}/{type}/{id}")
718 @Consumes({MediaType.APPLICATION_JSON})
719 @Produces({MediaType.APPLICATION_JSON})
720 public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
721 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
722 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
724 LoggingUtil.initMdcContext(req, headers);
726 logger.debug("Incoming request..." + content);
727 Response response = null;
731 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
732 String result = graphDataService.deleteVertex(version, id, type);
733 response = Response.status(Status.OK).entity(result).type(mediaType).build();
735 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
737 } catch (CrudException ce) {
738 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
739 } catch (Exception e) {
740 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
743 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
748 @Path("/relationships/{version}/{type}/{id}")
749 @Consumes({MediaType.APPLICATION_JSON})
750 @Produces({MediaType.APPLICATION_JSON})
751 public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
752 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
753 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
755 LoggingUtil.initMdcContext(req, headers);
757 logger.debug("Incoming request..." + content);
758 Response response = null;
761 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
762 String result = graphDataService.deleteEdge(version, id, type);
763 response = Response.status(Status.OK).entity(result).type(mediaType).build();
765 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
767 } catch (CrudException ce) {
768 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
769 } catch (Exception e) {
770 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
773 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
777 protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
778 String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
779 boolean isValid = false;
781 String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
782 String authUser = null;
783 if (cipherSuite != null) {
784 X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
785 X509Certificate clientCert = certChain[0];
786 X500Principal subjectDn = clientCert.getSubjectX500Principal();
787 authUser = subjectDn.toString();
789 isValid = this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName);
790 } catch (Exception e) {
791 logResult(action, uri, e);
795 validateRequestHeader(headers);
800 public void validateRequestHeader(HttpHeaders headers) throws CrudException {
801 String sourceOfTruth = null;
802 if (headers.getRequestHeaders().containsKey("X-FromAppId")) {
803 sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
806 if (sourceOfTruth == null || sourceOfTruth.trim() == "") {
807 throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST);
810 String transId = null;
811 if (headers.getRequestHeaders().containsKey("X-TransactionId")) {
812 transId = headers.getRequestHeaders().getFirst("X-TransactionId");
815 if (transId == null || transId.trim() == "") {
816 throw new CrudException("Invalid request, Missing X-TransactionId header", Status.BAD_REQUEST);
820 void logResult(Action op, String uri, Exception e) {
822 logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString());
824 // Clear the MDC context so that no other transaction inadvertently
825 // uses our transaction id.
829 private Map<String, String> addParams ( UriInfo info, boolean filter, String type, String version ) {
830 String propertiesKey = CrudProperties.get ( CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY );
831 Map<String, String> params = new HashMap<String, String> ();
832 params.put ( CrudServiceConstants.CRD_RESERVED_VERSION, version );
833 params.put ( CrudServiceConstants.CRD_RESERVED_NODE_TYPE, type );
835 for (Map.Entry<String, List<String>> e : info.getQueryParameters ().entrySet ()) {
836 if (!e.getKey ().equals ( propertiesKey )) {
837 params.put ( e.getKey (), e.getValue ().get ( 0 ) );
841 for (Map.Entry<String, List<String>> e : info.getQueryParameters ().entrySet ()) {
842 params.put ( e.getKey (), e.getValue ().get ( 0 ) );