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.util.CrudProperties;
57 import org.onap.crud.util.CrudServiceConstants;
58 import org.onap.crud.util.CrudServiceUtil;
60 import com.google.gson.JsonElement;
62 @Path("/services/inventory")
63 public class CrudRestService {
65 private AbstractGraphDataService graphDataService;
66 Logger logger = LoggerFactory.getInstance().getLogger(CrudRestService.class.getName());
67 Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(CrudRestService.class.getName());
70 private String mediaType = MediaType.APPLICATION_JSON;
71 public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override";
73 public CrudRestService(AbstractGraphDataService graphDataService) throws Exception {
74 this.graphDataService = graphDataService;
75 this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE);
79 public CrudRestService(AbstractGraphDataService graphDataService, Auth auth) throws Exception {
80 this.graphDataService = graphDataService;
85 POST, GET, PUT, DELETE, PATCH
88 public void startup() {
93 @Path("/{version}/{type}/{id}")
94 @Consumes({MediaType.APPLICATION_JSON})
95 @Produces({MediaType.APPLICATION_JSON})
96 public Response getVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
97 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
98 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
99 LoggingUtil.initMdcContext(req, headers);
101 logger.debug("Incoming request..." + content);
102 Response response = null;
104 Map<String, String> params = addParams ( uriInfo, false, type, version );
107 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
108 ImmutablePair<EntityTag, String> result = graphDataService.getVertex(version, id, type, params);
109 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
111 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
113 } catch (CrudException ce) {
114 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
115 } catch (Exception e) {
116 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
120 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
125 @Path("/{version}/{type}/")
126 @Consumes({MediaType.APPLICATION_JSON})
127 @Produces({MediaType.APPLICATION_JSON})
128 public Response getVertices(String content, @PathParam("version") String version, @PathParam("type") String type,
129 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
130 @Context HttpServletRequest req) {
132 LoggingUtil.initMdcContext(req, headers);
134 logger.debug("Incoming request..." + content);
135 Response response = null;
137 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
138 String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY);
139 Map<String, String> filter = addParams ( uriInfo, true, type, version );
141 HashSet<String> properties;
142 if (uriInfo.getQueryParameters().containsKey(propertiesKey)) {
143 properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey));
145 properties = new HashSet<>();
148 ImmutablePair<EntityTag, String> result = graphDataService.getVertices(version, type, filter, properties);
149 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
151 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
153 } catch (CrudException ce) {
154 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
155 } catch (Exception e) {
156 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
160 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
165 @Path("/relationships/{version}/{type}/{id}")
166 @Consumes({MediaType.APPLICATION_JSON})
167 @Produces({MediaType.APPLICATION_JSON})
168 public Response getEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
169 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
170 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
171 LoggingUtil.initMdcContext(req, headers);
173 logger.debug("Incoming request..." + content);
174 Response response = null;
176 Map<String, String> params = addParams ( uriInfo, false, type, version );
179 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
181 ImmutablePair<EntityTag, String> result = graphDataService.getEdge(version, id, type, params);
182 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
184 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
186 } catch (CrudException ce) {
187 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
188 } catch (Exception e) {
189 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
192 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
197 @Path("/relationships/{version}/{type}/")
198 @Consumes({MediaType.APPLICATION_JSON})
199 @Produces({MediaType.APPLICATION_JSON})
200 public Response getEdges(String content, @PathParam("version") String version, @PathParam("type") String type,
201 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
202 @Context HttpServletRequest req) {
204 LoggingUtil.initMdcContext(req, headers);
206 logger.debug("Incoming request..." + content);
207 Response response = null;
208 Map<String, String> filter = addParams ( uriInfo, true, type, version );
211 if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
212 ImmutablePair<EntityTag, String> result = graphDataService.getEdges(version, type, filter);
213 response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
215 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
217 } catch (CrudException ce) {
218 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
219 } catch (Exception e) {
220 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
223 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
228 @Path("/relationships/{version}/{type}/{id}")
229 @Consumes({MediaType.APPLICATION_JSON})
230 @Produces({MediaType.APPLICATION_JSON})
231 public Response updateEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
232 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
233 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
235 LoggingUtil.initMdcContext(req, headers);
237 logger.debug("Incoming request..." + content);
238 Response response = null;
242 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
243 EdgePayload payload = EdgePayload.fromJson(content);
244 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
245 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
247 if (payload.getId() != null && !payload.getId().equals(id)) {
248 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
250 ImmutablePair<EntityTag, String> result;
251 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
252 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
253 result = graphDataService.patchEdge(version, id, type, payload);
254 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
256 result = graphDataService.updateEdge(version, id, type, payload);
257 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
261 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
263 } catch (CrudException ce) {
264 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
265 } catch (Exception e) {
266 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
269 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
274 @Path("/relationships/{version}/{type}/{id}")
275 @Consumes({"application/merge-patch+json"})
276 @Produces({MediaType.APPLICATION_JSON})
277 public Response patchEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
278 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
279 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
281 LoggingUtil.initMdcContext(req, headers);
283 logger.debug("Incoming request..." + content);
284 Response response = null;
287 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
288 EdgePayload payload = EdgePayload.fromJson(content);
289 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
290 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
292 if (payload.getId() != null && !payload.getId().equals(id)) {
293 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
296 ImmutablePair<EntityTag, String> result = graphDataService.patchEdge(version, id, type, payload);
297 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
299 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
301 } catch (CrudException ce) {
302 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
303 } catch (Exception e) {
304 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
307 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
312 @Path("/{version}/{type}/{id}")
313 @Consumes({MediaType.APPLICATION_JSON})
314 @Produces({MediaType.APPLICATION_JSON})
315 public Response updateVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
316 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
317 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
319 LoggingUtil.initMdcContext(req, headers);
321 logger.debug("Incoming request..." + content);
322 Response response = null;
325 if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
326 VertexPayload payload = VertexPayload.fromJson(content);
327 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
328 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
330 if (payload.getId() != null && !payload.getId().equals(id)) {
331 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
334 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
336 ImmutablePair<EntityTag, String> result;
337 if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null
338 && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) {
339 result = graphDataService.patchVertex(version, id, type, payload);
340 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
342 result = graphDataService.updateVertex(version, id, type, payload);
343 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
347 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
349 } catch (CrudException ce) {
350 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
351 } catch (Exception e) {
352 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
355 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
360 @Path("/{version}/{type}/{id}")
361 @Consumes({"application/merge-patch+json"})
362 @Produces({MediaType.APPLICATION_JSON})
363 public Response patchVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
364 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
365 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
367 LoggingUtil.initMdcContext(req, headers);
369 logger.debug("Incoming request..." + content);
370 Response response = null;
373 if (validateRequest(req, uri, content, Action.PATCH, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
374 VertexPayload payload = VertexPayload.fromJson(content);
375 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
376 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
378 if (payload.getId() != null && !payload.getId().equals(id)) {
379 throw new CrudException("ID Mismatch", Status.BAD_REQUEST);
382 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false));
384 ImmutablePair<EntityTag, String> result = graphDataService.patchVertex(version, id, type, payload);
385 response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build();
387 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
389 } catch (CrudException ce) {
390 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
391 } catch (Exception e) {
392 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
395 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
400 @Path("/{version}/{type}/")
401 @Consumes({MediaType.APPLICATION_JSON})
402 @Produces({MediaType.APPLICATION_JSON})
403 public Response addVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
404 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
405 @Context HttpServletRequest req) {
407 LoggingUtil.initMdcContext(req, headers);
409 logger.debug("Incoming request..." + content);
410 Response response = null;
414 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
415 VertexPayload payload = VertexPayload.fromJson(content);
416 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
417 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
419 if (payload.getId() != null) {
420 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
423 if (payload.getType() != null && !payload.getType().equals(type)) {
424 throw new CrudException("Vertex Type mismatch", Status.BAD_REQUEST);
427 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
429 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, type, payload);
430 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
432 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
434 } catch (CrudException ce) {
435 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
436 } catch (Exception e) {
437 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
440 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
444 private void validateBulkPayload(BulkPayload payload) throws CrudException {
445 List<String> vertices = new ArrayList<String>();
446 List<String> edges = new ArrayList<String>();
448 for (JsonElement v : payload.getObjects()) {
449 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
450 v.getAsJsonObject().entrySet());
452 if (entries.size() != 2) {
453 throw new CrudException("", Status.BAD_REQUEST);
455 Map.Entry<String, JsonElement> opr = entries.get(0);
456 Map.Entry<String, JsonElement> item = entries.get(1);
458 if (vertices.contains(item.getKey())) {
459 throw new CrudException("duplicate vertex in payload: " + item.getKey(), Status.BAD_REQUEST);
461 VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
462 if (vertexPayload.getType() == null) {
463 throw new CrudException("Vertex Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
466 if (!opr.getKey().equalsIgnoreCase("operation")) {
467 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
470 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
471 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
472 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
473 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
474 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
476 // check if ID is populate for modify/patch/delete operation
477 if ((opr.getValue().getAsString().equalsIgnoreCase("modify")
478 || opr.getValue().getAsString().equalsIgnoreCase("patch")
479 || opr.getValue().getAsString().equalsIgnoreCase("delete")) && (vertexPayload.getId() == null)) {
481 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
485 vertices.add(item.getKey());
488 for (JsonElement v : payload.getRelationships()) {
489 List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
490 v.getAsJsonObject().entrySet());
492 if (entries.size() != 2) {
493 throw new CrudException("", Status.BAD_REQUEST);
495 Map.Entry<String, JsonElement> opr = entries.get(0);
496 Map.Entry<String, JsonElement> item = entries.get(1);
498 if (edges.contains(item.getKey())) {
499 throw new CrudException("duplicate Edge in payload: " + item.getKey(), Status.BAD_REQUEST);
502 EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
504 if (edgePayload.getType() == null) {
505 throw new CrudException("Edge Type cannot be null for: " + item.getKey(), Status.BAD_REQUEST);
508 if (!opr.getKey().equalsIgnoreCase("operation")) {
509 throw new CrudException("operation missing in item: " + item.getKey(), Status.BAD_REQUEST);
512 if (!opr.getValue().getAsString().equalsIgnoreCase("add")
513 && !opr.getValue().getAsString().equalsIgnoreCase("modify")
514 && !opr.getValue().getAsString().equalsIgnoreCase("patch")
515 && !opr.getValue().getAsString().equalsIgnoreCase("delete")) {
516 throw new CrudException("Invalid operation at item: " + item.getKey(), Status.BAD_REQUEST);
518 // check if ID is populate for modify/patch/delete operation
519 if ((edgePayload.getId() == null) && (opr.getValue().getAsString().equalsIgnoreCase("modify")
520 || opr.getValue().getAsString().equalsIgnoreCase("patch")
521 || opr.getValue().getAsString().equalsIgnoreCase("delete"))) {
523 throw new CrudException("Mising ID at item: " + item.getKey(), Status.BAD_REQUEST);
526 if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
527 if (edgePayload.getSource() == null || edgePayload.getTarget() == null) {
528 throw new CrudException("Source/Target cannot be null for edge: " + item.getKey(), Status.BAD_REQUEST);
530 if (edgePayload.getSource().startsWith("$") && !vertices.contains(edgePayload.getSource().substring(1))) {
531 throw new CrudException(
532 "Source Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
536 if (edgePayload.getTarget().startsWith("$") && !vertices.contains(edgePayload.getTarget().substring(1))) {
537 throw new CrudException(
538 "Target Vertex " + edgePayload.getSource().substring(1) + " not found for Edge: " + item.getKey(),
542 edges.add(item.getKey());
549 @Path("/{version}/bulk/")
550 @Consumes({MediaType.APPLICATION_JSON})
551 @Produces({MediaType.APPLICATION_JSON})
552 public Response addBulk(String content, @PathParam("version") String version, @PathParam("type") String type,
553 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
554 @Context HttpServletRequest req) {
556 LoggingUtil.initMdcContext(req, headers);
558 logger.debug("Incoming request..." + content);
559 Response response = null;
563 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
564 BulkPayload payload = BulkPayload.fromJson(content);
565 if ((payload.getObjects() == null && payload.getRelationships() == null)
566 || (payload.getObjects() != null && payload.getObjects().isEmpty() && payload.getRelationships() != null
567 && payload.getRelationships().isEmpty())) {
568 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
571 validateBulkPayload(payload);
572 String result = graphDataService.addBulk(version, payload, headers);
573 response = Response.status(Status.OK).entity(result).type(mediaType).build();
575 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
577 } catch (CrudException ce) {
578 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
579 } catch (Exception e) {
580 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
583 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
589 @Consumes({MediaType.APPLICATION_JSON})
590 @Produces({MediaType.APPLICATION_JSON})
591 public Response addVertex(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
592 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
594 LoggingUtil.initMdcContext(req, headers);
596 logger.debug("Incoming request..." + content);
597 Response response = null;
601 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
602 VertexPayload payload = VertexPayload.fromJson(content);
603 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
604 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
606 if (payload.getId() != null) {
607 throw new CrudException("ID specified , use Http PUT to update Vertex", Status.BAD_REQUEST);
610 if (payload.getType() == null || payload.getType().isEmpty()) {
611 throw new CrudException("Missing Vertex Type ", Status.BAD_REQUEST);
614 payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true));
616 ImmutablePair<EntityTag, String> result = graphDataService.addVertex(version, payload.getType(), payload);
617 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
619 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
621 } catch (CrudException ce) {
622 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
623 } catch (Exception e) {
624 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
627 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
632 @Path("/relationships/{version}/{type}/")
633 @Consumes({MediaType.APPLICATION_JSON})
634 @Produces({MediaType.APPLICATION_JSON})
635 public Response addEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
636 @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo,
637 @Context HttpServletRequest req) {
639 LoggingUtil.initMdcContext(req, headers);
641 logger.debug("Incoming request..." + content);
642 Response response = null;
646 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
647 EdgePayload payload = EdgePayload.fromJson(content);
648 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
649 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
651 if (payload.getId() != null) {
652 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
655 if (payload.getType() != null && !payload.getType().equals(type)) {
656 throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST);
658 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, type, payload);
659 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
661 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
663 } catch (CrudException ce) {
664 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
665 } catch (Exception e) {
666 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
669 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
674 @Path("/relationships/{version}/")
675 @Consumes({MediaType.APPLICATION_JSON})
676 @Produces({MediaType.APPLICATION_JSON})
677 public Response addEdge(String content, @PathParam("version") String version, @PathParam("uri") @Encoded String uri,
678 @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) {
680 LoggingUtil.initMdcContext(req, headers);
682 logger.debug("Incoming request..." + content);
683 Response response = null;
687 if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
688 EdgePayload payload = EdgePayload.fromJson(content);
689 if (payload.getProperties() == null || payload.getProperties().isJsonNull()) {
690 throw new CrudException("Invalid request Payload", Status.BAD_REQUEST);
692 if (payload.getId() != null) {
693 throw new CrudException("ID specified , use Http PUT to update Edge", Status.BAD_REQUEST);
696 if (payload.getType() == null || payload.getType().isEmpty()) {
697 throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST);
699 ImmutablePair<EntityTag, String> result = graphDataService.addEdge(version, payload.getType(), payload);
700 response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build();
702 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
704 } catch (CrudException ce) {
705 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
706 } catch (Exception e) {
707 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
710 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
715 @Path("/{version}/{type}/{id}")
716 @Consumes({MediaType.APPLICATION_JSON})
717 @Produces({MediaType.APPLICATION_JSON})
718 public Response deleteVertex(String content, @PathParam("version") String version, @PathParam("type") String type,
719 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
720 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
722 LoggingUtil.initMdcContext(req, headers);
724 logger.debug("Incoming request..." + content);
725 Response response = null;
729 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
730 String result = graphDataService.deleteVertex(version, id, type);
731 response = Response.status(Status.OK).entity(result).type(mediaType).build();
733 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
735 } catch (CrudException ce) {
736 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
737 } catch (Exception e) {
738 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
741 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
746 @Path("/relationships/{version}/{type}/{id}")
747 @Consumes({MediaType.APPLICATION_JSON})
748 @Produces({MediaType.APPLICATION_JSON})
749 public Response deleteEdge(String content, @PathParam("version") String version, @PathParam("type") String type,
750 @PathParam("id") String id, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers,
751 @Context UriInfo uriInfo, @Context HttpServletRequest req) {
753 LoggingUtil.initMdcContext(req, headers);
755 logger.debug("Incoming request..." + content);
756 Response response = null;
759 if (validateRequest(req, uri, content, Action.DELETE, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) {
760 String result = graphDataService.deleteEdge(version, id, type);
761 response = Response.status(Status.OK).entity(result).type(mediaType).build();
763 response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build();
765 } catch (CrudException ce) {
766 response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build();
767 } catch (Exception e) {
768 response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
771 LoggingUtil.logRestRequest(logger, auditLogger, req, response);
775 protected boolean validateRequest(HttpServletRequest req, String uri, String content, Action action,
776 String authPolicyFunctionName, HttpHeaders headers) throws CrudException {
777 boolean isValid = false;
779 String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite");
780 String authUser = null;
781 if (cipherSuite != null) {
782 X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
783 X509Certificate clientCert = certChain[0];
784 X500Principal subjectDn = clientCert.getSubjectX500Principal();
785 authUser = subjectDn.toString();
787 if(null != authUser) {
788 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, Arrays.toString(e.getStackTrace()));
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 ) );