use of com.yahoo.elide.core.exceptions.InvalidEntityBodyException in project elide by yahoo.
the class PersistentResource method toResource.
/**
* Convert a persistent resource to a resource.
*
* @param relationships The relationships
* @param attributes The attributes
* @return The Resource
*/
public Resource toResource(final Map<String, Relationship> relationships, final Map<String, Object> attributes) {
final Resource resource = new Resource(typeName, (obj == null) ? uuid.orElseThrow(() -> new InvalidEntityBodyException("No id found on object")) : dictionary.getId(obj));
resource.setRelationships(relationships);
resource.setAttributes(attributes);
if (requestScope.getElideSettings().isEnableJsonLinks()) {
resource.setLinks(requestScope.getElideSettings().getJsonApiLinks().getResourceLevelLinks(this));
}
return resource;
}
use of com.yahoo.elide.core.exceptions.InvalidEntityBodyException in project elide by yahoo.
the class CollectionTerminalState method createObject.
private PersistentResource createObject(RequestScope requestScope) throws ForbiddenAccessException, InvalidObjectIdentifierException {
JsonApiDocument doc = requestScope.getJsonApiDocument();
JsonApiMapper mapper = requestScope.getMapper();
if (doc.getData() == null) {
throw new InvalidEntityBodyException("Invalid JSON-API document: " + doc);
}
Data<Resource> data = doc.getData();
Collection<Resource> resources = data.get();
Resource resource = (resources.size() == 1) ? IterableUtils.first(resources) : null;
if (resource == null) {
try {
throw new InvalidEntityBodyException(mapper.writeJsonApiDocument(doc));
} catch (JsonProcessingException e) {
throw new InternalServerErrorException(e);
}
}
String id = resource.getId();
Type<?> newObjectClass = requestScope.getDictionary().getEntityClass(resource.getType(), requestScope.getApiVersion());
if (newObjectClass == null) {
throw new UnknownEntityException("Entity " + resource.getType() + " not found");
}
if (!entityClass.isAssignableFrom(newObjectClass)) {
throw new InvalidValueException("Cannot assign value of type: " + resource.getType() + " to type: " + entityClass);
}
PersistentResource pResource = PersistentResource.createObject(parent.orElse(null), relationName.orElse(null), newObjectClass, requestScope, Optional.ofNullable(id));
Map<String, Object> attributes = resource.getAttributes();
if (attributes != null) {
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
String fieldName = entry.getKey();
Object val = entry.getValue();
pResource.updateAttribute(fieldName, val);
}
}
Map<String, Relationship> relationships = resource.getRelationships();
if (relationships != null) {
for (Map.Entry<String, Relationship> entry : relationships.entrySet()) {
String fieldName = entry.getKey();
Relationship relationship = entry.getValue();
Set<PersistentResource> resourceSet = (relationship == null) ? null : relationship.toPersistentResources(requestScope);
pResource.updateRelation(fieldName, resourceSet);
}
}
return pResource;
}
use of com.yahoo.elide.core.exceptions.InvalidEntityBodyException in project elide by yahoo.
the class JsonApiPatch method handleReplaceOp.
/**
* Replace data via patch extension.
*/
private Supplier<Pair<Integer, JsonNode>> handleReplaceOp(String path, JsonNode patchVal, PatchRequestScope requestScope, PatchAction action) {
try {
JsonApiDocument value = requestScope.getMapper().readJsonApiPatchExtValue(patchVal);
if (!path.contains("relationships")) {
// Reserved
Data<Resource> data = value.getData();
Collection<Resource> resources = data.get();
// Defer relationship updating until the end
getSingleResource(resources).setRelationships(null);
// Reparse since we mangle it first
action.doc = requestScope.getMapper().readJsonApiPatchExtValue(patchVal);
action.path = path;
action.isPostProcessing = true;
}
// Defer relationship updating until the end
PatchVisitor visitor = new PatchVisitor(new PatchRequestScope(path, value, requestScope));
return visitor.visit(JsonApiParser.parse(path));
} catch (IOException e) {
throw new InvalidEntityBodyException("Could not parse patch extension value: " + patchVal);
}
}
use of com.yahoo.elide.core.exceptions.InvalidEntityBodyException in project elide by yahoo.
the class JsonApiPatch method handleAddOp.
/**
* Add a document via patch extension.
*/
private Supplier<Pair<Integer, JsonNode>> handleAddOp(String path, JsonNode patchValue, PatchRequestScope requestScope, PatchAction action) {
try {
JsonApiDocument value = requestScope.getMapper().readJsonApiPatchExtValue(patchValue);
Data<Resource> data = value.getData();
if (data == null || data.get() == null) {
throw new InvalidEntityBodyException("Expected an entity body but received none.");
}
Collection<Resource> resources = data.get();
if (!path.contains("relationships")) {
// Reserved key for relationships
String id = getSingleResource(resources).getId();
if (StringUtils.isEmpty(id)) {
throw new InvalidEntityBodyException("Patch extension requires all objects to have an assigned " + "ID (temporary or permanent) when assigning relationships.");
}
String fullPath = path + "/" + id;
// Defer relationship updating until the end
getSingleResource(resources).setRelationships(null);
// Reparse since we mangle it first
action.doc = requestScope.getMapper().readJsonApiPatchExtValue(patchValue);
action.path = fullPath;
action.isPostProcessing = true;
}
PostVisitor visitor = new PostVisitor(new PatchRequestScope(path, value, requestScope));
return visitor.visit(JsonApiParser.parse(path));
} catch (HttpStatusException e) {
action.cause = e;
throw e;
} catch (IOException e) {
throw new InvalidEntityBodyException("Could not parse patch extension value: " + patchValue);
}
}
use of com.yahoo.elide.core.exceptions.InvalidEntityBodyException in project elide by yahoo.
the class QueryRunner method executeGraphQLRequest.
private ElideResponse executeGraphQLRequest(String baseUrlEndPoint, ObjectMapper mapper, User principal, String graphQLDocument, GraphQLQuery query, UUID requestId, Map<String, List<String>> requestHeaders) {
boolean isVerbose = false;
String queryText = query.getQuery();
boolean isMutation = isMutation(queryText);
try (DataStoreTransaction tx = isMutation ? elide.getDataStore().beginTransaction() : elide.getDataStore().beginReadTransaction()) {
elide.getTransactionRegistry().addRunningTransaction(requestId, tx);
if (query.getQuery() == null || query.getQuery().isEmpty()) {
return ElideResponse.builder().responseCode(HttpStatus.SC_BAD_REQUEST).body("A `query` key is required.").build();
}
// get variables from request for constructing entityProjections
Map<String, Object> variables = query.getVariables();
// TODO - get API version.
GraphQLProjectionInfo projectionInfo = new GraphQLEntityProjectionMaker(elide.getElideSettings(), variables, apiVersion).make(queryText);
GraphQLRequestScope requestScope = new GraphQLRequestScope(baseUrlEndPoint, tx, principal, apiVersion, elide.getElideSettings(), projectionInfo, requestId, requestHeaders);
isVerbose = requestScope.getPermissionExecutor().isVerbose();
// Logging all queries. It is recommended to put any private information that shouldn't be logged into
// the "variables" section of your query. Variable values are not logged.
log.info("Processing GraphQL query:\n{}", queryText);
ExecutionInput.Builder executionInput = new ExecutionInput.Builder().localContext(requestScope).query(queryText);
if (query.getOperationName() != null) {
executionInput.operationName(query.getOperationName());
}
executionInput.variables(variables);
ExecutionResult result = api.execute(executionInput);
tx.preCommit(requestScope);
requestScope.getPermissionExecutor().executeCommitChecks();
if (isMutation) {
if (!result.getErrors().isEmpty()) {
HashMap<String, Object> abortedResponseObject = new HashMap<>();
abortedResponseObject.put("errors", result.getErrors());
abortedResponseObject.put("data", null);
// Do not commit. Throw OK response to process tx.close correctly.
throw new WebApplicationException(Response.ok(mapper.writeValueAsString(abortedResponseObject)).build());
}
requestScope.saveOrCreateObjects();
}
tx.flush(requestScope);
requestScope.runQueuedPreCommitTriggers();
elide.getAuditLogger().commit();
tx.commit(requestScope);
requestScope.runQueuedPostCommitTriggers();
if (log.isTraceEnabled()) {
requestScope.getPermissionExecutor().logCheckStats();
}
return ElideResponse.builder().responseCode(HttpStatus.SC_OK).body(mapper.writeValueAsString(result)).build();
} catch (JsonProcessingException e) {
log.debug("Invalid json body provided to GraphQL", e);
return buildErrorResponse(mapper, new InvalidEntityBodyException(graphQLDocument), isVerbose);
} catch (IOException e) {
log.error("Uncaught IO Exception by Elide in GraphQL", e);
return buildErrorResponse(mapper, new TransactionException(e), isVerbose);
} catch (RuntimeException e) {
return handleRuntimeException(elide, e, isVerbose);
} finally {
elide.getTransactionRegistry().removeRunningTransaction(requestId);
elide.getAuditLogger().clear();
}
}
Aggregations