All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.stargate.sgv2.graphql.web.resources.DmlResource Maven / Gradle / Ivy

There is a newer version: 2.0.0-ALPHA-17
Show newest version
/*
 * Copyright The Stargate Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.stargate.sgv2.graphql.web.resources;

import graphql.GraphQL;
import graphql.GraphqlErrorException;
import io.stargate.sgv2.common.grpc.StargateBridgeClient;
import io.stargate.sgv2.common.http.CreateStargateBridgeClient;
import io.stargate.sgv2.graphql.web.models.GraphqlJsonBody;
import java.util.Optional;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A collection of GraphQL services for user keyspaces.
 *
 * 

For each keyspace, this is either: * *

    *
  • a custom "GraphQL-first" schema, if the user has provided their own GraphQL. *
  • otherwise, a generic "CQL-first" schema generated from the existing CQL tables. *
*/ @Path(ResourcePaths.DML) @Singleton @CreateStargateBridgeClient public class DmlResource extends GraphqlResourceBase { private static final Logger LOG = LoggerFactory.getLogger(DmlResource.class); static final Pattern KEYSPACE_NAME_PATTERN = Pattern.compile("\\w+"); @Inject private GraphqlCache graphqlCache; @GET public void get( @QueryParam("query") String query, @QueryParam("operationName") String operationName, @QueryParam("variables") String variables, @Context HttpServletRequest httpRequest, @Suspended AsyncResponse asyncResponse, @Context StargateBridgeClient bridge) { GraphQL graphql = getDefaultGraphql(bridge); get(query, operationName, variables, graphql, httpRequest, asyncResponse, bridge); } @GET @Path("/{keyspaceName}") public void get( @PathParam("keyspaceName") String keyspaceName, @QueryParam("query") String query, @QueryParam("operationName") String operationName, @QueryParam("variables") String variables, @Context HttpServletRequest httpRequest, @Suspended AsyncResponse asyncResponse, @Context StargateBridgeClient bridge) { GraphQL graphql = getGraphql(keyspaceName, bridge); get(query, operationName, variables, graphql, httpRequest, asyncResponse, bridge); } @POST @Consumes(MediaType.APPLICATION_JSON) public void postJson( GraphqlJsonBody jsonBody, @QueryParam("query") String queryFromUrl, @Context HttpServletRequest httpRequest, @Suspended AsyncResponse asyncResponse, @Context StargateBridgeClient bridge) { GraphQL graphql = getDefaultGraphql(bridge); postJson(jsonBody, queryFromUrl, graphql, httpRequest, asyncResponse, bridge); } @POST @Path("/{keyspaceName}") @Consumes(MediaType.APPLICATION_JSON) public void postJson( @PathParam("keyspaceName") String keyspaceName, GraphqlJsonBody jsonBody, @QueryParam("query") String queryFromUrl, @Context HttpServletRequest httpRequest, @Suspended AsyncResponse asyncResponse, @Context StargateBridgeClient bridge) { GraphQL graphql = getGraphql(keyspaceName, bridge); postJson(jsonBody, queryFromUrl, graphql, httpRequest, asyncResponse, bridge); } @POST @Consumes(APPLICATION_GRAPHQL) public void postGraphql( String query, @Context HttpServletRequest httpRequest, @HeaderParam("X-Cassandra-Token") String token, @Suspended AsyncResponse asyncResponse, @Context StargateBridgeClient bridge) { GraphQL graphql = getDefaultGraphql(bridge); postGraphql(query, graphql, httpRequest, asyncResponse, bridge); } @POST @Path("/{keyspaceName}") @Consumes(APPLICATION_GRAPHQL) public void postGraphql( @PathParam("keyspaceName") String keyspaceName, String query, @Context HttpServletRequest httpRequest, @HeaderParam("X-Cassandra-Token") String token, @Suspended AsyncResponse asyncResponse, @Context StargateBridgeClient bridge) { GraphQL graphql = getGraphql(keyspaceName, bridge); postGraphql(query, graphql, httpRequest, asyncResponse, bridge); } private GraphQL getGraphql(String keyspaceName, StargateBridgeClient bridge) { if (!KEYSPACE_NAME_PATTERN.matcher(keyspaceName).matches()) { LOG.warn("Invalid keyspace in URI, this could be an XSS attack: {}", keyspaceName); // Do not reflect back the value throw graphqlError(Status.BAD_REQUEST, "Invalid keyspace name"); } if (!isAuthorized(keyspaceName, bridge)) { throw graphqlError(Status.UNAUTHORIZED, "Not authorized"); } try { String decoratedKeyspaceName = bridge.decorateKeyspaceName(keyspaceName); Optional graphql = graphqlCache.getDml(bridge, keyspaceName); return graphql.orElseThrow( () -> graphqlError(Status.NOT_FOUND, String.format("Unknown keyspace '%s'", keyspaceName))); } catch (GraphqlErrorException e) { throw graphqlError(Status.INTERNAL_SERVER_ERROR, e); } catch (Exception e) { LOG.error("Unexpected error while accessing keyspace {}", keyspaceName, e); throw graphqlError( Status.INTERNAL_SERVER_ERROR, "Unexpected error while accessing keyspace: " + e.getMessage()); } } private GraphQL getDefaultGraphql(StargateBridgeClient bridge) { return graphqlCache .getDefaultKeyspaceName(bridge) .map(ks -> getGraphql(ks, bridge)) .orElseThrow(() -> graphqlError(Status.NOT_FOUND, "No default keyspace defined")); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy