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.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
30 import javax.security.auth.x500.X500Principal;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.Encoded;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.EntityTag;
43 import javax.ws.rs.core.HttpHeaders;
44 import javax.ws.rs.core.MediaType;
45 import javax.ws.rs.core.Response;
46 import javax.ws.rs.core.Response.Status;
47 import javax.ws.rs.core.UriInfo;
48 import org.apache.commons.lang3.tuple.ImmutablePair;
49 import org.apache.cxf.jaxrs.ext.PATCH;
50 import org.onap.aai.cl.api.Logger;
51 import org.onap.aai.cl.eelf.LoggerFactory;
52 import org.onap.aaiauth.auth.Auth;
53 import org.onap.crud.exception.CrudException;
54 import org.onap.crud.logging.CrudServiceMsgs;
55 import org.onap.crud.logging.LoggingUtil;
56 import org.onap.crud.parser.BulkPayload;
57 import org.onap.crud.parser.EdgePayload;
58 import org.onap.crud.parser.VertexPayload;
59 import org.onap.crud.util.CrudProperties;
60 import org.onap.crud.util.CrudServiceConstants;
61 import org.onap.crud.util.CrudServiceUtil;
63 import com.google.gson.JsonElement;
65 @Path("/services/inventory")
66 public class CrudRestService {
68 private AbstractGraphDataService graphDataService;
69 Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
70 Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
73 private String mediaType = MediaType.APPLICATION_JSON;
74 public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
76 public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
77 this.graphDataService = graphDataService;
78 this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
82 public CrudRestService(AbstractGraphDataService graphDataService, Auth auth) throws Exception {
83 this.graphDataService = graphDataService;
88 POST, GET, PUT, DELETE, PATCH
91 public void startup() {
96 @Path("/{version}/{type}/{id}")
97 @Consumes({MediaType.APPLICATION_JSON})
98 @Produces({MediaType.APPLICATION_JSON})
99 public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
100 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
101 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
102 LoggingUtil.initMdcContext(req, headers);
104 logger.debug("Incoming request..." + content);
105 Response response = null;
107 Map<String, String> params = addParams ( uriInfo, false, type, version );
110 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
111 ImmutablePair<EntityTag, String> result = graphDataService.getVertex(version, id, type, params);
112 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
114 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
116 } catch (CrudException ce) {
117 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
118 } catch (Exception e) {
119 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
123 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
128 @Path("/{version}/{type}/")
129 @Consumes({MediaType.APPLICATION_JSON})
130 @Produces({MediaType.APPLICATION_JSON})
131 public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
132 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
133 @Context HttpServletRequest req) {
135 LoggingUtil.initMdcContext(req, headers);
137 logger.debug("Incoming request..." + content);
138 Response response = null;
140 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
141 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
142 Map<String, String> filter = addParams ( uriInfo, true, type, version );
144 HashSet<String> properties;
145 if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
146 properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
148 properties = new HashSet<>();
151 ImmutablePair<EntityTag, String> result = graphDataService.getVertices(version, type, filter, properties);
152 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
154 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
156 } catch (CrudException ce) {
157 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
158 } catch (Exception e) {
159 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
163 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
168 @Path("/relationships/{version}/{type}/{id}")
169 @Consumes({MediaType.APPLICATION_JSON})
170 @Produces({MediaType.APPLICATION_JSON})
171 public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
172 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
173 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
174 LoggingUtil.initMdcContext(req, headers);
176 logger.debug("Incoming request..." + content);
177 Response response = null;
179 Map<String, String> params = addParams ( uriInfo, false, type, version );
182 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
184 ImmutablePair<EntityTag, String> result = graphDataService.getEdge(version, id, type, params);
185 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
187 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
189 } catch (CrudException ce) {
190 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
191 } catch (Exception e) {
192 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
195 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
200 @Path("/relationships/{version}/{type}/")
201 @Consumes({MediaType.APPLICATION_JSON})
202 @Produces({MediaType.APPLICATION_JSON})
203 public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
204 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
205 @Context HttpServletRequest req) {
207 LoggingUtil.initMdcContext(req, headers);
209 logger.debug("Incoming request..." + content);
210 Response response = null;
211 Map<String, String> filter = addParams ( uriInfo, true, type, version );
214 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
215 ImmutablePair<EntityTag, String> result = graphDataService.getEdges(version, type, filter);
216 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
218 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
220 } catch (CrudException ce) {
221 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
222 } catch (Exception e) {
223 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
226 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
231 @Path("/relationships/{version}/{type}/{id}")
232 @Consumes({MediaType.APPLICATION_JSON})
233 @Produces({MediaType.APPLICATION_JSON})
234 public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
235 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
236 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
238 LoggingUtil.initMdcContext(req, headers);
240 logger.debug("Incoming request..." + content);
241 Response response = null;
245 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
246 EdgePayload payload = EdgePayload.fromJson(content);
247 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
248 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
250 if (payload.getId() != null && !payload.getId().equals(id)) {
251 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
253 ImmutablePair<EntityTag, String> result;
254 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
255 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
256 result = graphDataService.patchEdge(version, id, type, payload);
257 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
259 result = graphDataService.updateEdge(version, id, type, payload);
260 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
264 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
266 } catch (CrudException ce) {
267 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
268 } catch (Exception e) {
269 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
272 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
277 @Path("/relationships/{version}/{type}/{id}")
278 @Consumes({"application/merge-patch+json"})
279 @Produces({MediaType.APPLICATION_JSON})
280 public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
281 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
282 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
284 LoggingUtil.initMdcContext(req, headers);
286 logger.debug("Incoming request..." + content);
287 Response response = null;
290 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
291 EdgePayload payload = EdgePayload.fromJson(content);
292 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
293 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
295 if (payload.getId() != null && !payload.getId().equals(id)) {
296 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
299 ImmutablePair<EntityTag, String> result = graphDataService.patchEdge(version, id, type, payload);
300 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
302 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
304 } catch (CrudException ce) {
305 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
306 } catch (Exception e) {
307 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
310 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
315 @Path("/{version}/{type}/{id}")
316 @Consumes({MediaType.APPLICATION_JSON})
317 @Produces({MediaType.APPLICATION_JSON})
318 public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
319 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
320 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
322 LoggingUtil.initMdcContext(req, headers);
324 logger.debug("Incoming request..." + content);
325 Response response = null;
328 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
329 VertexPayload payload = VertexPayload.fromJson(content);
330 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
331 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
333 if (payload.getId() != null && !payload.getId().equals(id)) {
334 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
337 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
339 ImmutablePair<EntityTag, String> result;
340 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
341 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
342 result = graphDataService.patchVertex(version, id, type, payload);
343 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
345 result = graphDataService.updateVertex(version, id, type, payload);
346 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
350 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
352 } catch (CrudException ce) {
353 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
354 } catch (Exception e) {
355 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
358 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
363 @Path("/{version}/{type}/{id}")
364 @Consumes({"application/merge-patch+json"})
365 @Produces({MediaType.APPLICATION_JSON})
366 public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
367 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
368 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
370 LoggingUtil.initMdcContext(req, headers);
372 logger.debug("Incoming request..." + content);
373 Response response = null;
376 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
377 VertexPayload payload = VertexPayload.fromJson(content);
378 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
379 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
381 if (payload.getId() != null && !payload.getId().equals(id)) {
382 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
385 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
387 ImmutablePair<EntityTag, String> result = graphDataService.patchVertex(version, id, type, payload);
388 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
390 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
392 } catch (CrudException ce) {
393 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
394 } catch (Exception e) {
395 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
398 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
403 @Path("/{version}/{type}/")
404 @Consumes({MediaType.APPLICATION_JSON})
405 @Produces({MediaType.APPLICATION_JSON})
406 public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
407 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
408 @Context HttpServletRequest req) {
410 LoggingUtil.initMdcContext(req, headers);
412 logger.debug("Incoming request..." + content);
413 Response response = null;
417 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
418 VertexPayload payload = VertexPayload.fromJson(content);
419 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
420 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
422 if (payload.getId() != null) {
423 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
426 if (payload.getType() != null && !payload.getType().equals(type)) {
427 throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
430 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
432 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, type, payload);
433 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
435 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
437 } catch (CrudException ce) {
438 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
439 } catch (Exception e) {
440 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
443 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
447 private void validateBulkPayload(BulkPayload payload) throws CrudException {
448 List<String> vertices = new ArrayList<String>();
449 List<String> edges = new ArrayList<String>();
451 for (JsonElement v : payload.getObjects()) {
452 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
453 v.getAsJsonObject().entrySet());
455 if (entries.size() != 2) {
456 throw new CrudException("", Status.BAD_REQUEST);
458 Map.Entry<String, JsonElement> opr = entries.get(0);
459 Map.Entry<String, JsonElement> item = entries.get(1);
461 if (vertices.contains(item.getKey())) {
462 throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
464 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
465 if (vertexPayload.getType() == null) {
466 throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
469 if (!opr.getKey().equalsIgnoreCase("operation")) {
470 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
473 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
474 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
475 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
476 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
477 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
479 // check if ID is populate for modify/patch/delete operation
480 if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
481 || opr.getValue().getAsString().equalsIgnoreCase("patch")
482 || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
484 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
488 vertices.add(item.getKey());
491 for (JsonElement v : payload.getRelationships()) {
492 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
493 v.getAsJsonObject().entrySet());
495 if (entries.size() != 2) {
496 throw new CrudException("", Status.BAD_REQUEST);
498 Map.Entry<String, JsonElement> opr = entries.get(0);
499 Map.Entry<String, JsonElement> item = entries.get(1);
501 if (edges.contains(item.getKey())) {
502 throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
505 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
507 if (edgePayload.getType() == null) {
508 throw new CrudException("Edge Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
511 if (!opr.getKey().equalsIgnoreCase("operation")) {
512 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
515 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
516 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
517 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
518 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
519 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
521 // check if ID is populate for modify/patch/delete operation
522 if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
523 || opr.getValue().getAsString().equalsIgnoreCase("patch")
524 || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
526 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
529 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
530 if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
531 throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(), Status.BAD_REQUEST);
533 if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
534 throw new CrudException(
535 "Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
539 if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
540 throw new CrudException(
541 "Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
545 edges.add(item.getKey());
552 @Path("/{version}/bulk/")
553 @Consumes({MediaType.APPLICATION_JSON})
554 @Produces({MediaType.APPLICATION_JSON})
555 public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
556 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
557 @Context HttpServletRequest req) {
559 LoggingUtil.initMdcContext(req, headers);
561 logger.debug("Incoming request..." + content);
562 Response response = null;
566 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
567 BulkPayload payload = BulkPayload.fromJson(content);
568 if ((payload.getObjects() == null && payload.getRelationships() == null)
569 || (payload.getObjects() != null && payload.getObjects().isEmpty() && payload.getRelationships() != null
570 && payload.getRelationships().isEmpty())) {
571 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
574 validateBulkPayload(payload);
575 String result = graphDataService.addBulk(version, payload, headers);
576 response = Response.status(Status.OK).entity(result).type(mediaType).build();
578 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
580 } catch (CrudException ce) {
581 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
582 } catch (Exception e) {
583 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
586 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
592 @Consumes({MediaType.APPLICATION_JSON})
593 @Produces({MediaType.APPLICATION_JSON})
594 public Response addVertex(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
595 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
597 LoggingUtil.initMdcContext(req, headers);
599 logger.debug("Incoming request..." + content);
600 Response response = null;
604 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
605 VertexPayload payload = VertexPayload.fromJson(content);
606 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
607 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
609 if (payload.getId() != null) {
610 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
613 if (payload.getType() == null || payload.getType().isEmpty()) {
614 throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
617 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
619 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, payload.getType(), payload);
620 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
622 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
624 } catch (CrudException ce) {
625 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
626 } catch (Exception e) {
627 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
630 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
635 @Path("/relationships/{version}/{type}/")
636 @Consumes({MediaType.APPLICATION_JSON})
637 @Produces({MediaType.APPLICATION_JSON})
638 public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
639 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
640 @Context HttpServletRequest req) {
642 LoggingUtil.initMdcContext(req, headers);
644 logger.debug("Incoming request..." + content);
645 Response response = null;
649 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
650 EdgePayload payload = EdgePayload.fromJson(content);
651 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
652 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
654 if (payload.getId() != null) {
655 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
658 if (payload.getType() != null && !payload.getType().equals(type)) {
659 throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
661 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, type, payload);
662 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
664 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
666 } catch (CrudException ce) {
667 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
668 } catch (Exception e) {
669 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
672 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
677 @Path("/relationships/{version}/")
678 @Consumes({MediaType.APPLICATION_JSON})
679 @Produces({MediaType.APPLICATION_JSON})
680 public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
681 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
683 LoggingUtil.initMdcContext(req, headers);
685 logger.debug("Incoming request..." + content);
686 Response response = null;
690 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
691 EdgePayload payload = EdgePayload.fromJson(content);
692 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
693 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
695 if (payload.getId() != null) {
696 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
699 if (payload.getType() == null || payload.getType().isEmpty()) {
700 throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST);
702 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, payload.getType(), payload);
703 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
705 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
707 } catch (CrudException ce) {
708 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
709 } catch (Exception e) {
710 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
713 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
718 @Path("/{version}/{type}/{id}")
719 @Consumes({MediaType.APPLICATION_JSON})
720 @Produces({MediaType.APPLICATION_JSON})
721 public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
722 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
723 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
725 LoggingUtil.initMdcContext(req, headers);
727 logger.debug("Incoming request..." + content);
728 Response response = null;
732 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
733 String result = graphDataService.deleteVertex(version, id, type);
734 response = Response.status(Status.OK).entity(result).type(mediaType).build();
736 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
738 } catch (CrudException ce) {
739 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
740 } catch (Exception e) {
741 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
744 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
749 @Path("/relationships/{version}/{type}/{id}")
750 @Consumes({MediaType.APPLICATION_JSON})
751 @Produces({MediaType.APPLICATION_JSON})
752 public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
753 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
754 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
756 LoggingUtil.initMdcContext(req, headers);
758 logger.debug("Incoming request..." + content);
759 Response response = null;
762 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
763 String result = graphDataService.deleteEdge(version, id, type);
764 response = Response.status(Status.OK).entity(result).type(mediaType).build();
766 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
768 } catch (CrudException ce) {
769 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
770 } catch (Exception e) {
771 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
774 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
778 protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
779 String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
780 boolean isValid = false;
782 String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
783 String authUser = null;
784 if (cipherSuite != null) {
785 X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
786 X509Certificate clientCert = certChain[0];
787 X500Principal subjectDn = clientCert.getSubjectX500Principal();
788 authUser = subjectDn.toString();
790 if(null != authUser) {
791 isValid = this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName);
793 } catch (Exception e) {
794 logResult(action, uri, e);
798 validateRequestHeader(headers);
803 public void validateRequestHeader(HttpHeaders headers) throws CrudException {
804 String sourceOfTruth = null;
805 if (headers.getRequestHeaders().containsKey("X-FromAppId")) {
806 sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
809 if (sourceOfTruth == null || sourceOfTruth.trim() == "") {
810 throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST);
813 String transId = null;
814 if (headers.getRequestHeaders().containsKey("X-TransactionId")) {
815 transId = headers.getRequestHeaders().getFirst("X-TransactionId");
818 if (transId == null || transId.trim() == "") {
819 throw new CrudException("Invalid request, Missing X-TransactionId header", Status.BAD_REQUEST);
823 void logResult(Action op, String uri, Exception e) {
825 logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, Arrays.toString(e.getStackTrace()));
827 // Clear the MDC context so that no other transaction inadvertently
828 // uses our transaction id.
832 private Map<String, String> addParams ( UriInfo info, boolean filter, String type, String version ) {
833 String propertiesKey = CrudProperties.get ( CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY );
834 Map<String, String> params = new HashMap<String, String> ();
835 params.put ( CrudServiceConstants.CRD_RESERVED_VERSION, version );
836 params.put ( CrudServiceConstants.CRD_RESERVED_NODE_TYPE, type );
838 for (Map.Entry<String, List<String>> e : info.getQueryParameters ().entrySet ()) {
839 if (!e.getKey ().equals ( propertiesKey )) {
840 params.put ( e.getKey (), e.getValue ().get ( 0 ) );
844 for (Map.Entry<String, List<String>> e : info.getQueryParameters ().entrySet ()) {
845 params.put ( e.getKey (), e.getValue ().get ( 0 ) );