sangria.parser.QueryParser Scala Examples
The following examples show how to use sangria.parser.QueryParser.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: GraphQLHandler.scala From daml with Apache License 2.0 | 5 votes |
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. // SPDX-License-Identifier: Apache-2.0 package com.daml.navigator import akka.actor.ActorRef import akka.http.scaladsl.model.StatusCode import akka.http.scaladsl.model.StatusCodes._ import com.daml.navigator.graphql._ import com.daml.navigator.graphql.SprayMarshallers._ import com.daml.navigator.model.PartyState import com.daml.navigator.store.Store.StoreException import com.typesafe.scalalogging.LazyLogging import sangria.ast.Document import sangria.execution._ import sangria.parser.QueryParser import sangria.renderer.SchemaRenderer import sangria.schema.Schema import spray.json._ import scala.concurrent.{ExecutionContext, Future} import scala.util.Try case class ParseResult(ast: Document, operationName: Option[String], variables: JsValue) trait GraphQLHandler { def schema: Schema[GraphQLContext, Unit] def parse(request: String): Try[ParseResult] def parse(request: JsValue): Try[ParseResult] def executeQuery(parsed: ParseResult, party: PartyState): Future[(StatusCode, JsValue)] def renderSchema: String } object GraphQLHandler { type ParseQuery = JsValue => Try[ParseResult] type ExecuteQuery = (ParseResult, PartyState) => Future[(StatusCode, JsValue)] type CustomEndpoints = Set[CustomEndpoint[_]] } case class DefaultGraphQLHandler( customEndpoints: GraphQLHandler.CustomEndpoints, platformStore: Option[ActorRef])( implicit executionContext: ExecutionContext ) extends GraphQLHandler with LazyLogging { def schema: Schema[GraphQLContext, Unit] = new GraphQLSchema(customEndpoints).QuerySchema def parse(request: String): Try[ParseResult] = Try(request.parseJson).flatMap(parse) def parse(request: JsValue): Try[ParseResult] = for { fields <- Try(request.asJsObject.fields) JsString(query) <- Try(fields("query")) operationName = fields.get("operationName").collect { case JsString(value) => value } vars: JsValue = fields.get("variables") match { case Some(obj: JsObject) => obj case _ => JsObject.empty } ast <- QueryParser.parse(query) } yield ParseResult(ast, operationName, vars) def executeQuery(parsed: ParseResult, party: PartyState): Future[(StatusCode, JsValue)] = { platformStore.fold[Future[(StatusCode, JsValue)]]( Future.successful(InternalServerError -> JsString("Platform store not available")) )(store => { val context = GraphQLContext(party, store) Executor .execute( schema, parsed.ast, context, variables = parsed.variables, operationName = parsed.operationName, exceptionHandler = ExceptionHandler { case (_, StoreException(message)) => HandledException(message) } ) .map(OK -> _) .recover { case error: QueryAnalysisError => logger.warn(s"GraphQL analysis error ${error.getMessage}.") BadRequest -> error.resolveError case error: ErrorWithResolver => logger.error("Failed to execute GraphQL query", error) InternalServerError -> error.resolveError } }) } def renderSchema: String = SchemaRenderer.renderSchema(schema) }
Example 2
Source File: GraphQLSchemaSpec.scala From daml with Apache License 2.0 | 5 votes |
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. // SPDX-License-Identifier: Apache-2.0 package com.daml.navigator.graphql import org.scalatest.{Matchers, WordSpec} import sangria.parser.QueryParser import sangria.schema.SchemaChange.DescriptionChange import sangria.schema.Schema import scala.io.Source class GraphQLSchemaSpec extends WordSpec with Matchers { "The rendered schema" should { "match the expected schema definition" in { val idl = Source.fromInputStream(getClass.getResourceAsStream("/schema.graphql"), "UTF-8").mkString val schema = Schema.buildFromAst(QueryParser.parse(idl).get) // Compare schemata but ignore description changes. val changes = schema .compare(new GraphQLSchema(Set()).QuerySchema) .filter(!_.isInstanceOf[DescriptionChange]) if (changes.nonEmpty) { fail( s"Schema definition does not match:\n- ${changes.map(_.description).mkString("\n- ")}\n") } } } }
Example 3
Source File: SangriaGraphQLSupport.scala From incubator-s2graph with Apache License 2.0 | 5 votes |
package org.apache.s2graph.http import java.nio.charset.Charset import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} import akka.http.scaladsl.model._ import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller} import akka.util.ByteString import sangria.ast.Document import sangria.parser.QueryParser import sangria.renderer.{QueryRenderer, QueryRendererConfig} trait SangriaGraphQLSupport { private val mediaTypes: Seq[MediaType.WithFixedCharset] = Seq(MediaType.applicationWithFixedCharset("graphql", HttpCharsets.`UTF-8`, "graphql")) private val unmarshallerContentTypes: Seq[ContentTypeRange] = mediaTypes.map(ContentTypeRange.apply) implicit def documentMarshaller(implicit config: QueryRendererConfig = QueryRenderer.Compact): ToEntityMarshaller[Document] = { Marshaller.oneOf(mediaTypes: _*) { mediaType ⇒ Marshaller.withFixedContentType(ContentType(mediaType)) { json ⇒ HttpEntity(mediaType, QueryRenderer.render(json, config)) } } } implicit val documentUnmarshaller: FromEntityUnmarshaller[Document] = { Unmarshaller.byteStringUnmarshaller .forContentTypes(unmarshallerContentTypes: _*) .map { case ByteString.empty ⇒ throw Unmarshaller.NoContentException case data ⇒ import sangria.parser.DeliveryScheme.Throw QueryParser.parse(data.decodeString(Charset.forName("UTF-8"))) } } }
Example 4
Source File: FilterTest.scala From naptime with Apache License 2.0 | 5 votes |
package org.coursera.naptime.ari.graphql.controllers.filters import org.coursera.naptime.ari.graphql.GraphqlSchemaProvider import org.coursera.naptime.ari.graphql.Models import org.coursera.naptime.ari.graphql.SangriaGraphQlContext import org.coursera.naptime.ari.graphql.SangriaGraphQlSchemaBuilder import org.coursera.naptime.ari.graphql.models.MergedCourse import org.coursera.naptime.ari.graphql.models.MergedInstructor import org.coursera.naptime.ari.graphql.models.MergedPartner import org.mockito.Mockito.when import org.scalatest.concurrent.IntegrationPatience import org.scalatest.concurrent.ScalaFutures import org.scalatest.junit.AssertionsForJUnit import org.scalatest.mockito.MockitoSugar import play.api.libs.json.Json import play.api.test.FakeRequest import sangria.parser.QueryParser import sangria.schema.Schema import scala.concurrent.Future trait FilterTest extends AssertionsForJUnit with MockitoSugar with ScalaFutures with IntegrationPatience { val baseOutgoingQuery = OutgoingQuery(Json.obj(), None) def noopFilter(incomingQuery: IncomingQuery) = { Future.successful(baseOutgoingQuery) } def exceptionThrowingFilter(incomingQuery: IncomingQuery): Future[OutgoingQuery] = { assert(false, "This filter should not be run") Future.successful(baseOutgoingQuery) } val filter: Filter val defaultQuery = """ |query { | __schema { | queryType { | name | } | } |} """.stripMargin val graphqlSchemaProvider = mock[GraphqlSchemaProvider] val allResources = Set(Models.courseResource, Models.instructorResource, Models.partnersResource) val schemaTypes = Map( "org.coursera.naptime.ari.graphql.models.MergedCourse" -> MergedCourse.SCHEMA, "org.coursera.naptime.ari.graphql.models.MergedPartner" -> MergedPartner.SCHEMA, "org.coursera.naptime.ari.graphql.models.MergedInstructor" -> MergedInstructor.SCHEMA) val builder = new SangriaGraphQlSchemaBuilder(allResources, schemaTypes) val schema = builder.generateSchema().data.asInstanceOf[Schema[SangriaGraphQlContext, Any]] when(graphqlSchemaProvider.schema).thenReturn(schema) def generateIncomingQuery(query: String = defaultQuery) = { val document = QueryParser.parse(query).get val header = FakeRequest("POST", s"/graphql").withBody(query) val variables = Json.obj() val operation = None IncomingQuery(document, header, variables, operation, debugMode = false) } def run(incomingQuery: IncomingQuery): Future[OutgoingQuery] = { filter.apply(noopFilter)(incomingQuery) } def ensureNotPropagated(incomingQuery: IncomingQuery): Future[OutgoingQuery] = { filter.apply(exceptionThrowingFilter)(incomingQuery) } }
Example 5
Source File: TestExecutorHelper.scala From naptime with Apache License 2.0 | 5 votes |
package org.coursera.naptime.ari.graphql.schema import com.linkedin.data.DataMap import org.coursera.naptime.ari.graphql.Models import org.coursera.naptime.ari.graphql.SangriaGraphQlContext import org.coursera.naptime.ari.graphql.SangriaGraphQlSchemaBuilder import org.coursera.naptime.ari.graphql.marshaller.NaptimeMarshaller._ import org.coursera.naptime.ari.graphql.models.RecordWithUnionTypes import org.coursera.naptime.ari.graphql.models.MergedCourse import org.coursera.naptime.ari.graphql.models.MergedInstructor import org.coursera.naptime.ari.graphql.models.MergedPartner import org.coursera.naptime.ari.graphql.resolvers.NaptimeResolver import play.api.libs.json.JsObject import sangria.execution.Executor import sangria.parser.QueryParser import sangria.schema.Schema import scala.concurrent.Await import scala.concurrent.ExecutionContext import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration.Duration class TestExecutorHelper { def executeQuery( queryString: String, resourceData: Map[String, Map[String, List[DataMap]]]): JsObject = { val schemaTypes = Map( "org.coursera.naptime.ari.graphql.models.MergedCourse" -> MergedCourse.SCHEMA, "org.coursera.naptime.ari.graphql.models.FakeModel" -> RecordWithUnionTypes.SCHEMA, "org.coursera.naptime.ari.graphql.models.MergedPartner" -> MergedPartner.SCHEMA, "org.coursera.naptime.ari.graphql.models.MergedInstructor" -> MergedInstructor.SCHEMA) val allResources = Set( Models.courseResource, Models.instructorResource, Models.partnersResource, Models.fakeModelResource) val builder = new SangriaGraphQlSchemaBuilder(allResources, schemaTypes) val schema = builder.generateSchema().data.asInstanceOf[Schema[SangriaGraphQlContext, Any]] val queryAst = QueryParser.parse(queryString).get val context = SangriaGraphQlContext( FakeFetcherApi(resourceData), null, ExecutionContext.global, debugMode = true) Await .result( Executor .execute( schema, queryAst, context, variables = JsObject(Map.empty[String, JsObject]), deferredResolver = new NaptimeResolver()), Duration.Inf) .asInstanceOf[JsObject] } }
Example 6
Source File: ParseMacro.scala From sangria with Apache License 2.0 | 5 votes |
package sangria.macros import sangria.parser.{SyntaxError, QueryParser} import scala.reflect.macros.blackbox class ParseMacro(context: blackbox.Context) extends { val c = context } with MacroAstLiftable { import c.universe._ def impl(args: Expr[Any]*) = if (args.nonEmpty) c.abort(c.enclosingPosition, "String interpolation is not supported for `graphql`/`gql` macro at the moment.") else c.prefix.tree match { // Expects a string interpolation that doesn't contain any // expressions, thus containing only a single tree case Apply(_, List(Apply(_, t :: Nil))) => val q"${gql: String}" = t try { q"${QueryParser.parse(gql).get}" } catch { case error: SyntaxError => syntaxError(error) } case _ => c.abort(c.enclosingPosition, "Invalid `graphql` invocation syntax.") } def implInput(args: Expr[Any]*) = if (args.nonEmpty) c.abort(c.enclosingPosition, "String interpolation is not supported for `graphqlInput`/`gqlInp` macro at the moment.") else c.prefix.tree match { // Expects a string interpolation that doesn't contain any // expressions, thus containing only a single tree case Apply(_, List(Apply(_, t :: Nil))) => val q"${gql: String}" = t try { q"${QueryParser.parseInput(gql).get}" } catch { case error: SyntaxError => syntaxError(error) } case _ => c.abort(c.enclosingPosition, "Invalid `graphql` invocation syntax.") } def implInputDoc(args: Expr[Any]*) = if (args.nonEmpty) c.abort(c.enclosingPosition, "String interpolation is not supported for `gqlInpDoc` macro at the moment.") else c.prefix.tree match { // Expects a string interpolation that doesn't contain any // expressions, thus containing only a single tree case Apply(_, List(Apply(_, t :: Nil))) => val q"${gql: String}" = t try { q"${QueryParser.parseInputDocument(gql).get}" } catch { case error: SyntaxError => syntaxError(error) } case _ => c.abort(c.enclosingPosition, "Invalid `graphql` invocation syntax.") } def syntaxError(error: SyntaxError) = { val errorPos = error.originalError.position val enclosingCol = if (errorPos.line == 1) calcStringStart else 0 val source = c.enclosingPosition.source val line = source.lineToOffset(c.enclosingPosition.line + (errorPos.line - 2)) val col = line + enclosingCol + (errorPos.column - 1) val pos = c.enclosingPosition.withPoint(col) c.abort(pos, error.formattedError(showPosition = false)) } def calcStringStart: Int = { val source = c.enclosingPosition.source val content = source.lineToString(c.enclosingPosition.line - 1) val contentStart = content.substring(c.enclosingPosition.column - 1) val offset = "(\\w+\"+)".r.findFirstMatchIn(contentStart).fold(0)(_.end) c.enclosingPosition.column - 1 + offset } }
Example 7
Source File: ContextPassingSpec.scala From sangria with Apache License 2.0 | 5 votes |
package sangria.execution import sangria.parser.QueryParser import sangria.schema._ import sangria.util.FutureResultSupport import scala.util.Success import scala.concurrent.ExecutionContext.Implicits.global import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec class ContextPassingSpec extends AnyWordSpec with Matchers with FutureResultSupport { trait ColorComponent { def color = "green" } trait NameComponent { def name = "foo" } trait PersonComponent { this: NameComponent => def fullName = name + " bar" } class Cake extends ColorComponent with NameComponent with PersonComponent val ColorType = ObjectType("Color", fields[ColorComponent with NameComponent, Unit]( Field("colorName", StringType, resolve = _.ctx.color), Field("name", StringType, resolve = _.ctx.name))) val NameType = ObjectType("Name", fields[NameComponent, Unit]( Field("name", StringType, resolve = _.ctx.name))) val PersonType = ObjectType("Person", fields[PersonComponent, Unit]( Field("fullName", StringType, resolve = _.ctx.fullName), Field("name", NameType, resolve = _ => ()))) def colorField[Ctx <: ColorComponent with NameComponent] = Field("color", ColorType, None, resolve = (ctx: Context[Ctx, Unit]) => ()) val QueryType = ObjectType("Query", fields[Cake, Unit]( colorField, Field("person", PersonType, resolve = _ => ()) )) val schema = Schema(QueryType) "Context" should { "should respect inheritance" in { val Success(doc) = QueryParser.parse(""" { color {name, colorName} person { name {name} fullName } } """) Executor.execute(schema, doc, userContext = new Cake).await should be (Map( "data" -> Map( "color" -> Map( "name" -> "foo", "colorName" -> "green"), "person" -> Map( "name" -> Map("name" -> "foo"), "fullName" -> "foo bar")))) } } }
Example 8
Source File: FileUtil.scala From sangria with Apache License 2.0 | 5 votes |
package sangria.util import java.io.File import io.github.classgraph.ClassGraph import sangria.parser.QueryParser import sangria.parser.DeliveryScheme.Throw import spray.json._ import scala.io.Source import net.jcazevedo.moultingyaml._ import scala.collection.JavaConverters._ object FileUtil extends StringMatchers { def loadQuery(name: String) = loadResource("queries/" + name) def loadYaml(name: String, root: String = "scenarios") = loadResource(root + "/" + name).parseYaml def loadScenarios(path: String, root: String = "scenarios") = this.synchronized { val yamlResources = new ClassGraph() .whitelistPackages(root + "." + path) .scan() .getResourcesWithExtension("yaml") .asScala .groupBy(_.getPath).mapValues(_.head) // deduplicate (`ClassGraph` gives duplicates for some reason) .values .toVector yamlResources.map { resource => val name = resource.getPath.substring(resource.getPath.lastIndexOf("/") + 1) val relativePath = resource.getPathRelativeToClasspathElement val stream = this.getClass.getResourceAsStream("/" + relativePath) val contents = Source.fromInputStream(stream, "UTF-8").mkString.parseYaml ScenarioFile(name, relativePath, contents) } } def loadSchema(path: String) = QueryParser.parse(loadResource(path)) def loadTestData(path: String): Either[YamlValue, JsValue] = { val text = loadResource(path) if (path endsWith ".yaml") Left(text.parseYaml) else if (path endsWith ".json") Right(text.parseJson) else throw new IllegalArgumentException(s"Unsupported file format for test data '$path'. Only `*.json` and `*.yaml` files are supported.") } def loadResource(path: String) = Option(this.getClass.getResourceAsStream("/" + path)) match { case Some(res) => stripCarriageReturns(Source.fromInputStream(res, "UTF-8").mkString) case None => throw new IllegalArgumentException("Resource not found: /" + path) } case class ScenarioFile(fileName: String, path: String, scenario: YamlValue) { def folder = path.substring(0, path.lastIndexOf("/")) } }
Example 9
Source File: GraphQlController.scala From tap with Apache License 2.0 | 5 votes |
package controllers import javax.inject.Inject import models.GraphqlSchema import models.graphql.GraphqlActions import play.api.Logger import play.api.libs.json.{JsObject, JsValue, Json} import play.api.mvc.{Action, AnyContent, InjectedController, Result} import sangria.ast.Document import sangria.execution.{ErrorWithResolver, Executor, QueryAnalysisError} import sangria.marshalling.playJson.{PlayJsonInputUnmarshallerJObject, PlayJsonResultMarshaller} import sangria.parser.{QueryParser, SyntaxError} import sangria.schema.Schema import views.GraphiqlPage import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Failure, Success} class GraphQlController @Inject() (assets: AssetsFinder, gqlSchema: GraphqlSchema, actions: GraphqlActions) extends InjectedController { val schema:Schema[GraphqlActions,Unit] = gqlSchema.create def graphiql:Action[AnyContent] = Action { request => Logger.info("Got Any content request from:" + request.remoteAddress) //Ok(views.html.graphiql(assets)) Ok(GraphiqlPage.render("Explore TAP with GraphiQL")) } def graphql:Action[JsValue] = Action.async(parse.json) { request => val query = (request.body \ "query").as[String] val operation = (request.body \ "operationName").asOpt[String] val variables = (request.body \ "variables").asOpt[JsObject].getOrElse(Json.obj()) Logger.info(s"Query received from ${request.remoteAddress} >>> ${operation.getOrElse("No query")}") Logger.info(s"Variables: $variables") process(query,operation,variables) } def process(query:String,name:Option[String],variables:JsObject):Future[Result] = QueryParser.parse(query) match { case Success(queryAst) => executeGraphQLQuery(queryAst, name, variables) case Failure(error: SyntaxError) => Future.successful(BadRequest(error.getMessage)) case _ => Future.successful(BadRequest("There was a problem with the request to TAP graphql.")) } def executeGraphQLQuery(query: Document, name: Option[String], vars: JsObject):Future[Result] = { Executor.execute(schema, query, actions, operationName = name, variables = vars) .map(Ok(_)) .recover { case error: QueryAnalysisError => BadRequest(error.resolveError) case error: ErrorWithResolver => InternalServerError(error.resolveError) } } }
Example 10
Source File: DocumentLoader.scala From sbt-graphql with Apache License 2.0 | 5 votes |
package rocks.muki.graphql.codegen import java.io.File import cats.implicits._ import rocks.muki.graphql.instances.monoidDocument import sangria.ast.Document import sangria.parser.QueryParser import sangria.schema._ import sangria.validation.QueryValidator import scala.io.Source object DocumentLoader { def single(schema: Schema[_, _], file: File): Result[Document] = for { document <- parseDocument(file) violations = QueryValidator.default.validateQuery(schema, document) _ <- Either.cond( violations.isEmpty, document, Failure(s"Invalid query in ${file.getAbsolutePath}:\n${violations.map(_.errorMessage).mkString(", ")}") ) } yield document private def parseSchema(file: File): Result[Schema[_, _]] = for { document <- parseDocument(file) schema <- Either.catchNonFatal(Schema.buildFromAst(document)).leftMap { error => Failure(s"Failed to read schema $file: ${error.getMessage}") } } yield schema private def parseDocument(file: File): Result[Document] = for { input <- Either.catchNonFatal(Source.fromFile(file).mkString).leftMap { error => Failure(s"Failed to read $file: ${error.getMessage}") } document <- Either.fromTry(QueryParser.parse(input)).leftMap { error => Failure(s"Failed to parse $file: ${error.getMessage}") } } yield document }
Example 11
Source File: MutationCallbackSchemaExecutor.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.deprecated.actions import com.typesafe.scalalogging.LazyLogging import cool.graph.client.ClientInjector import cool.graph.client.database.{DeferredResolverProvider, SimpleManyModelDeferredResolver, SimpleToManyDeferredResolver} import cool.graph.cuid.Cuid.createCuid import cool.graph.deprecated.actions.schemas.{ActionUserContext, MutationMetaData} import cool.graph.shared.models.{Model, Project} import cool.graph.shared.schema.JsonMarshalling._ import sangria.execution.Executor import sangria.parser.QueryParser import sangria.schema.Schema import spray.json.{JsObject, JsString} import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Failure, Success} case class Event(id: String, url: String, payload: Option[JsObject]) class MutationCallbackSchemaExecutor(project: Project, model: Model, schema: Schema[ActionUserContext, Unit], nodeId: String, fragment: String, url: String, mutationId: String)(implicit injector: ClientInjector) extends LazyLogging { def execute: Future[Event] = { implicit val inj = injector.toScaldi val dataFut = QueryParser.parse(fragment) match { case Success(queryAst) => Executor.execute( schema, queryAst, deferredResolver = new DeferredResolverProvider( new SimpleToManyDeferredResolver, new SimpleManyModelDeferredResolver, skipPermissionCheck = true ), userContext = ActionUserContext( requestId = "", project = project, nodeId = nodeId, mutation = MutationMetaData(id = mutationId, _type = "Create"), log = (x: String) => logger.info(x) ) ) case Failure(error) => Future.successful(JsObject("error" -> JsString(error.getMessage))) } dataFut .map { case JsObject(dataMap) => Event(id = createCuid(), url = url, payload = Some(dataMap("data").asJsObject)) case json => sys.error(s"Must only receive JsObjects here. But got instead: ${json.compactPrint}") } } }
Example 12
Source File: QueryPermissionValidator.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.client.authorization.queryPermissions import akka.actor.ActorSystem import akka.stream.ActorMaterializer import cool.graph.client.database.{DeferredResolverProvider, SimpleManyModelDeferredResolver, SimpleToManyDeferredResolver} import cool.graph.client.{ClientInjector, UserContext} import cool.graph.metrics.ClientSharedMetrics import cool.graph.shared.errors.UserAPIErrors.InsufficientPermissions import cool.graph.shared.models.{AuthenticatedRequest, Project} import cool.graph.shared.queryPermissions.PermissionSchemaResolver import sangria.ast._ import sangria.execution.deferred.DeferredResolver import sangria.execution.{DeprecationTracker, Executor} import sangria.marshalling.queryAst._ import sangria.marshalling.{InputUnmarshaller, QueryAstResultMarshaller} import sangria.parser.QueryParser import sangria.schema.Schema import sangria.validation.QueryValidator import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future import scala.util.{Failure, Success} class QueryPermissionValidator(project: Project)(implicit injector: ClientInjector, system: ActorSystem, materializer: ActorMaterializer) { lazy val schema: Schema[UserContext, Unit] = PermissionSchemaResolver.permissionSchema(project)(injector.toScaldi) lazy val deferredResolverProvider: DeferredResolver[Any] = new DeferredResolverProvider(new SimpleToManyDeferredResolver, new SimpleManyModelDeferredResolver, skipPermissionCheck = true) .asInstanceOf[DeferredResolver[Any]] lazy val executor = Executor( schema = schema.asInstanceOf[Schema[Any, Any]], queryValidator = QueryValidator.default, deferredResolver = deferredResolverProvider, exceptionHandler = PartialFunction.empty, deprecationTracker = DeprecationTracker.empty, middleware = Nil, maxQueryDepth = None, queryReducers = Nil ) def validate( query: String, variables: Map[String, Any], authenticatedRequest: Option[AuthenticatedRequest], alwaysQueryMasterDatabase: Boolean ): Future[Boolean] = { injector.onPermissionQuery(project.id) ClientSharedMetrics.queryPermissionCounter.inc(project.id) val context = new UserContext( project = project, authenticatedRequest = authenticatedRequest, requestId = "grap-permission-query", requestIp = "graph-permission-query", project.ownerId, (x: String) => Unit, alwaysQueryMasterDatabase = alwaysQueryMasterDatabase )(injector.toScaldi) val dataFut: Future[QueryAstResultMarshaller#Node] = QueryParser.parse(query) match { case Success(_queryAst) => executor .execute(queryAst = _queryAst, userContext = context, root = (), variables = InputUnmarshaller.mapVars(variables)) .recover { case e: Throwable => throw InsufficientPermissions(s"Permission Query is invalid. Could not be executed. Error Message: ${e.getMessage}") } case Failure(error) => throw InsufficientPermissions(s"Permission Query is invalid. Could not be parsed. Error Message: ${error.getMessage}") } dataFut.map(traverseAndCheckForLeafs) } private def traverseAndCheckForLeafs(root: AstNode): Boolean = { root match { case ObjectValue(fields, _, _) => fields.forall(field => traverseAndCheckForLeafs(field)) case ObjectField(_, value, _, _) => traverseAndCheckForLeafs(value) case x: BooleanValue => x.value case _ => sys.error(s"Received unknown type of AstNode. Could not handle: $root") //triggered by NullValue(Vector(),None) } } }
Example 13
Source File: SubscriptionQueryValidator.scala From graphcool-framework with Apache License 2.0 | 5 votes |
package cool.graph.subscriptions.schemas import cool.graph.shared.models.{Model, ModelMutationType, Project} import org.scalactic.{Bad, Good, Or} import sangria.ast.Document import sangria.parser.QueryParser import sangria.validation.QueryValidator import scaldi.Injector import scala.util.{Failure, Success} case class SubscriptionQueryError(errorMessage: String) case class SubscriptionQueryValidator(project: Project)(implicit inj: Injector) { def validate(query: String): Model Or Seq[SubscriptionQueryError] = { queryDocument(query).flatMap(validate) } def validate(queryDoc: Document): Model Or Seq[SubscriptionQueryError] = { for { modelName <- modelName(queryDoc) model <- modelFor(modelName) _ <- validateSubscriptionQuery(queryDoc, model) } yield model } def queryDocument(query: String): Document Or Seq[SubscriptionQueryError] = QueryParser.parse(query) match { case Success(doc) => Good(doc) case Failure(_) => Bad(Seq(SubscriptionQueryError("The subscription query is invalid GraphQL."))) } def modelName(queryDoc: Document): String Or Seq[SubscriptionQueryError] = QueryTransformer.getModelNameFromSubscription(queryDoc) match { case Some(modelName) => Good(modelName) case None => Bad(Seq(SubscriptionQueryError("The provided query doesn't include any known model name. Please check for the latest subscriptions API."))) } def modelFor(model: String): Model Or Seq[SubscriptionQueryError] = project.getModelByName(model) match { case Some(model) => Good(model) case None => Bad(Seq(SubscriptionQueryError("The provided query doesn't include any known model name. Please check for the latest subscriptions API."))) } def validateSubscriptionQuery(queryDoc: Document, model: Model): Unit Or Seq[SubscriptionQueryError] = { val schema = SubscriptionSchema(model, project, None, ModelMutationType.Created, None, true).build val violations = QueryValidator.default.validateQuery(schema, queryDoc) if (violations.nonEmpty) { Bad(violations.map(v => SubscriptionQueryError(v.errorMessage))) } else Good(()) } }
Example 14
Source File: GraphQLRequestUnmarshaller.scala From graphql-gateway with Apache License 2.0 | 5 votes |
package sangria.gateway.http import java.nio.charset.Charset import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller} import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.server.Directive0 import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller} import akka.util.ByteString import sangria.ast.Document import sangria.parser.QueryParser import sangria.renderer.{QueryRenderer, QueryRendererConfig} import scala.collection.immutable.Seq object GraphQLRequestUnmarshaller { val `application/graphql` = MediaType.applicationWithFixedCharset("graphql", HttpCharsets.`UTF-8`, "graphql") def explicitlyAccepts(mediaType: MediaType): Directive0 = headerValuePF { case Accept(ranges) if ranges.exists(range ⇒ !range.isWildcard && range.matches(mediaType)) ⇒ ranges }.flatMap(_ ⇒ pass) def includeIf(include: Boolean): Directive0 = if (include) pass else reject def unmarshallerContentTypes: Seq[ContentTypeRange] = mediaTypes.map(ContentTypeRange.apply) def mediaTypes: Seq[MediaType.WithFixedCharset] = List(`application/graphql`) implicit final def documentMarshaller(implicit config: QueryRendererConfig = QueryRenderer.Compact): ToEntityMarshaller[Document] = Marshaller.oneOf(mediaTypes: _*) { mediaType ⇒ Marshaller.withFixedContentType(ContentType(mediaType)) { json ⇒ HttpEntity(mediaType, QueryRenderer.render(json, config)) } } implicit final val documentUnmarshaller: FromEntityUnmarshaller[Document] = Unmarshaller.byteStringUnmarshaller .forContentTypes(unmarshallerContentTypes: _*) .map { case ByteString.empty ⇒ throw Unmarshaller.NoContentException case data ⇒ import sangria.parser.DeliveryScheme.Throw QueryParser.parse(data.decodeString(Charset.forName("UTF-8"))) } }
Example 15
Source File: SchemaLoader.scala From graphql-gateway with Apache License 2.0 | 5 votes |
package sangria.gateway.schema import better.files.File import sangria.ast.Document import sangria.execution.Executor import sangria.execution.deferred.DeferredResolver import sangria.gateway.AppConfig import sangria.gateway.file.FileUtil import sangria.gateway.http.client.HttpClient import sangria.gateway.schema.materializer.{GatewayContext, GatewayMaterializer} import sangria.gateway.util.Logging import sangria.parser.QueryParser import sangria.schema.Schema import sangria.marshalling.circe._ import scala.concurrent.{ExecutionContext, Future} import scala.util.control.NonFatal import scala.util.{Failure, Success} class SchemaLoader(config: AppConfig, client: HttpClient, mat: GatewayMaterializer)(implicit ec: ExecutionContext) extends Logging { def loadSchema: Future[Option[SchemaInfo[GatewayContext, Any]]] = { val files = FileUtil.loadFiles(config.watch.allFiles, config.watch.allGlobs) if (files.nonEmpty) { val parsed = files.map { case (path, content) ⇒ path → QueryParser.parse(content) } val failed = parsed.collect {case (path, Failure(e)) ⇒ path → e} if (failed.nonEmpty) { failed.foreach { case (path, error) ⇒ logger.error(s"Can't parse file '$path':\n${error.getMessage}") } Future.successful(None) } else { val successful = parsed.collect {case (path, Success(doc)) ⇒ path → doc} val document = Document.merge(successful.map(_._2)) try { val info = for { ctx ← GatewayContext.loadContext(config, client, document) schema = Schema.buildFromAst(document, mat.schemaBuilder(ctx).validateSchemaWithException(document)) intro ← executeIntrospection(schema, ctx) } yield Some(SchemaInfo( schema, ctx, (), Nil, DeferredResolver.empty, schema.renderPretty, intro, files.map(_._1))) info.recover(handleError(files)) } catch { case e if handleError(files).isDefinedAt(e) ⇒ Future.successful(handleError(files)(e)) } } } else { logger.error("No schema files found!") Future.successful(None) } } private def handleError(files: Vector[(File, String)]): PartialFunction[Throwable, Option[SchemaInfo[GatewayContext, Any]]] = { case NonFatal(e) ⇒ logger.error(s"Can't create the schema from files: ${files.map(_._1).mkString(", ")}. " + e.getMessage) None } private def executeIntrospection(schema: Schema[GatewayContext, Any], ctx: GatewayContext) = Executor.execute(schema, sangria.introspection.introspectionQuery(schemaDescription = false, directiveRepeatableFlag = false), ctx) }
Example 16
Source File: StarWarsMutationSpec.scala From sangria-relay with Apache License 2.0 | 5 votes |
package sangria.relay.starWars import sangria.execution.Executor import sangria.parser.QueryParser import sangria.relay.starWars.StarWarsData.ShipRepo import sangria.relay.util.AwaitSupport import sangria.marshalling.InputUnmarshaller.mapVars import scala.concurrent.ExecutionContext.Implicits.global import scala.util.Success import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec class StarWarsMutationSpec extends AnyWordSpec with Matchers with AwaitSupport { "Mutation" should { "Correctly mutates the data set" in { val Success(doc) = QueryParser.parse( """ mutation AddBWingQuery($input: IntroduceShipInput!) { introduceShip(input: $input) { ship { id name } faction { name } clientMutationId } } """) val vars = mapVars( "input" -> Map( "shipName" -> "B-Wing", "factionId" -> "RmFjdGlvbjox", "clientMutationId" -> "abcde" ) ) Executor.execute(StarWarsSchema.schema, doc, variables = vars, userContext = new ShipRepo).await should be( Map( "data" -> Map( "introduceShip" -> Map( "ship" -> Map( "id" -> "U2hpcDo5", "name" -> "B-Wing" ), "faction" -> Map( "name" -> "Alliance to Restore the Republic" ), "clientMutationId" -> "abcde" )))) } } }