Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Nick Hudkins
@nickhudkins
https://github.com/sangria-graphql/sangria-relay-playground/blob/main/app/models/SchemaDefinition.scala take a look here for how that behaves. The information about type name is encoded in the ID requested.
Nick Hudkins
@nickhudkins
For example, how would you expect this query to behave? The way GraphQL would deal with this is that the server would return either a UnionTypeA or a UnionTypeB, and you would receive a response for just that type. If you are hoping to have the type defined by the user, you would either need some sort of input arg to someUnionField or, better yet, split this into two distinct fields rather than 1 that is a union type. Am I understanding correctly?
{
     someUnionField {
          ... on UnionTypeA {
                someFieldOfTypeA
           }
           ... on UnionTypeB {
                someFieldOfTypeB           
            }
     }
}
JayalakshmiH
@JayalakshmiH
For the scenario, that you mentioned above, i wanted to return both UnionTypeA and UnionTypeB. For example, if client requests only for UnionTypeA, then I wanted to return only UnionTypeA. In order to implement that, I wanted to know which UnionType the client is requesting for. Is there a way to get that?
{
someUnionField {
... on UnionTypeA {
someFieldOfTypeA
}
}
Nick Hudkins
@nickhudkins
Not that I can think of. The issue is that you could spread multiple fragments, so how would you decide what to send in the case of multiple. This SOUNDS like two distinct fields to me. Alternatively, take some sort of input to “someUnionField” but the fragment itself is not “input” so to speak
Léonard Marques
@keuhdall
Hello everyone,
I'm trying to setup access control in Sangria, basically I'm authenticating on client side through Auth0 and then make the query with the bearer as Authorization header, I then validate the token and retrieve the user's identity from the database (all this happens before call Executor.execute), but so now that I have my user's identity and its roles, I don't really know what to do...
I tried following Sangria's documentation (https://sangria-graphql.github.io/learn/#authentication-and-authorisation), however the part about that SecureContext really confuses me.
If my understanding is correct, I should first create a SecureContext that holds an Option[Identity] defaulting to None, and update that context after I retrieved my user's Identity, and then perform my access control against that updated context.
Sorry if my question sounds a little silly, but can someone confirm / correct my understanding of the process ?
Thank you !
Nick Hudkins
@nickhudkins
If you have an Option[Identity] before you call Executor.execute, you can add that as a field on whatever you’re constructing for userContext. No need to do any context updates, simply build it before you execute!
2 replies
Nick Hudkins
@nickhudkins
Because I’m a dummy 😂
Léonard Marques
@keuhdall
Hello again,
I made good progress on my authorization middleware, but I have a few more questions.
So far I went with a middleware-based auth instead of a resolve-based auth.
However, this seem to cause issues for me for the following use case:
Let's assume I have a Book entity, that has a userId attached to it, and a user can only query his books, how can I ensure that the Identity I'm holding from the Bearer token is matching the Id given in the query ?
Since beforeField has my Context as parameter, my guess is that I can check the arguments passed, as one of them would be my userId , but let's assume the argument I want to check varies from one query to another (like, not necessarily called 'Id', or 'userId'), is there a way to use Middleware-based authorization anyway, or should I use Resolve-based authorization ?
Thank you !
Yann Simon
@yanns

I don't think it's middleware VS resolve-based auth. We are using both for example.
The middleware checks that we are logged in.
The middleware also checks permissions based on tags:

val permissions = ctx.field.tags.collect { case Permission(p) => p }
      if (permissions.nonEmpty && !secureContext.hasPermissions(permissions))
        throw GraphQLOAuthException(OAuthError.insufficientScope(permissions))

And then, in some resolve functions, we also check the permissions:

      resolve = (c: Context[SecureContext, Unit]) => {
        if (!c.ctx.hasPermissions(....))
          throw GraphQLOAuthException(OAuthError.insufficientScope)
1 reply
Justin Reeves
@clutch-justin
Trying to make a ScalarType[JsValue] to merge an arbitrary JsValue into a response ({} or {"foo": "bar"}) for example , but getting java.lang.IllegalArgumentException: "Unsupported scalar value: {}"
  case object JsonCoercionViolation extends ValueCoercionViolation("Not valid JSON")

  implicit val JsonType: ScalarType[Any] = ScalarType[Any]("Json",
    description = Some("Raw JSON value"),
    coerceOutput = {
      case (value: JsValue, c) => value
    },
    coerceUserInput = {
      case v: String => Right(JsString(v))
      case v: Boolean => Right(JsBoolean(v))
      case v: Int => Right(JsNumber(v))
      case v: Long => Right(JsNumber(v))
      case v: Float => Right(JsNumber(v))
      case v: Double => Right(JsNumber(v))
      case v: BigInt => Right(JsNumber(BigDecimal(v)))
      case v: BigDecimal => Right(JsNumber(v))
      case v: JsValue => Right(v)
      case _ => Left(JsonCoercionViolation)
    },
    coerceInput = {
      case ast.StringValue(s, _, _, _, _) =>
        Right(Json.parse(s))
      case _ =>
        Left(JsonCoercionViolation)
    })
Justin Reeves
@clutch-justin
I'm just proxying another service.
I found this https://gist.github.com/OlegIlyenko/5b96f4b54f656aac226d3c4bc33fd2a6 and tried it but for Play Json, but still get the above result...(or issues trying to use two ResultMappers at once)
I get this can be an issue, but is there away to make a particular field just returns some json?
Justin Reeves
@clutch-justin
I got it by adding the same case v: JsValue => v to the ResultMarshaller...which is the opposite of what Ithought I had to do
Performant Data
@performantdata

I'm puzzled as to why this variables field in GraphQLHttpRequest has a type parameter (and thus why GraphQLHttpRequest itself does). It seems like this should just be represented as a Map[String,String], possibly empty.

case class GraphQLHttpRequest[T](
    query: Option[String],
    variables: Option[T],
    operationName: Option[String])

https://github.com/sangria-graphql/sangria-akka-http/blob/5411bedfc7a4d6c07deebb424d0cc5a4db33baf5/core/src/main/scala/sangria/http/akka/GraphQLHttpRequest.scala#L5

3 replies
Rishi Khandelwal
@rishckt_twitter

How can we pass List[List[caseClass]] as argument ? When I am trying to do so, I am getting the following error: "spray.json.JsArray cannot be cast to scala.collection.Seq"

val fdsInputRequestFilter: InputObjectType[RequestFilter] = deriveInputObjectTypeRequestFilter

val requestFilter = Argument("filters", OptionInputType(ListInputType(ListInputType(fdsInputRequestFilter))))

Any help will be appriciated.
Michael Kieran O'Reilly
@SoTeKie
Hi, I was wondering if anybody had a clear example of how to do a enum input or a union type input? It's not in the documentation sadly and I'm having some trouble even getting started on this one
2 replies
Mike Reidy
@mike_reidy_twitter
Hello all, I was wondering are there examples of how to support sorting of results.
1 reply
Vitya Chyzhyk
@6juara9

Hi guys, thanks in advance for reading this. Does everyone know how to solve my problem?

I have a product data type in my code that looks like this:

final case class Choice(id: Int, name: String, option: ChoiceOption)

sealed trait ChoiceOption

object ChoiceOption {
  final case class SingularChoiceOption(checked: Boolean) extends ChoiceOption
  final case class MultipleChoiceOption(possibleValues: Seq[String], defaultValue: String) extends ChoiceOption
}

I want to represent this code in sangria as an interface:

interface Choice {
  id: Int!
  name: String!
}

type SingularChoice implements Choice {
  id: Int!
  name: String!
  checked: Boolean!
}

type MultipleChoiceOption implements Choice {
  id: Int!
  name: String!
  possibleValues: [String!]!
  defaultValue: String!
}

but I don't want to write my code like this:

sealed trait Choice {
  val id: Int
  val name: String
}
final case class SingularChoiceOption(id: Int, name: String, checked: Boolean) extends Choice
final case class MultipleChoiceOption(id: Int, name: String, possibleValues: Seq[String], defaultValue: String) extends Choice

I'm using InterfaceType for describing my Choice, but there're no constructors that resolve value as an interface subtype. In other words, I want to view product data type as a sum data type.

Does anyone know workarounds for this case? Thank you =).

1 reply
Performant Data
@performantdata
I'm publishing a Giter8 template for quickly setting up an end-to-end Sangria project: https://github.com/performantdata/sangria-example.g8
It's in a very raw state, still, but it now compiles and runs. :tada:
Dragutin Marjanović
@drmarjanovic
Hi everyone, is there any way to implement response compression? Thanks in advance! I found a similar question here but no answer.
1 reply
Performant Data
@performantdata

In developing a Sangria example, I'm having difficulty in demonstrating even the most basic use of an SDL-based schema materialization. I'm getting

sangria.schema.SchemaMaterializationException: Can't extract value for a field 'User.id': not a map-like value.

when I use an SDL file containing

type User {
  id: Long!
  name: String!
  person: Person!
}

I find it odd that ScalaInputUnmarshaller.isMapNode()is true only for Maps, not for case classes, or that my User case class doesn't get treated like a map. Wondering whether there's some linkage in the Scala code that I need.

The examples that I see tend to define the schema in Scala code. That has worked for me, but it obfuscates the schema's design. So it seems a real shame to do it that way.

Anyway, just mentioning the error for now, in case someone else has seen it. I'll have a clean example of the failure published soon.

Nick Hudkins
@nickhudkins
@performantdata what serialization library are you using?
28 replies
Yann Simon
@yanns
Hi, please test the new release candidate: https://github.com/sangria-graphql/sangria/releases/tag/v3.0.0-RC1 .
Josh Soref
@jsoref
Hi yanns
Yann Simon
@yanns
Please welcome a new release candidate: https://github.com/sangria-graphql/sangria/releases/tag/v3.0.0-RC2. Feedback welcome!
Yann Simon
@yanns
Ups, I spoke too fast - the artifact is not published on maven central yet.
Ishan Shah
@nullptr7
Is it possible to have InputObjectType as traits. I understand that InputObjectType allows only scala case class But any suggestions on how can be achieved?
Yann Simon
@yanns
InputObjectType is used to represent a GraphQL type that can be used as an input, for example for an argument.
People usually use that with a scala case class as it's convenient. But you can use it with a trait, that you have to instantiate yourself at some point.
But if you are using a trait, we may have different implementations in scala. In that case, it may be better to expose a GraphQL interface and some concrete types of it.
Performant Data
@performantdata
Do we know why DeliveryScheme exists? Seems like Try could have been used instead.
Yann Simon
@yanns
In AlternativeDeliverySchemes, you can find different implementation of it. I personally have never changed it. So I don't know the value of it.
rney-lookout
@rney-lookout
Question: Is there an implementation of the Schema Reporting Protocol for Sangria? We're starting to try and keep a schema registry and would like to have publishing automated as we deploy new versions.
Abhishek Gupta
@abhigp27
Question: Is there a way to remove the path and location values from Exception, Only interested in error message and extentions values. A little further, is it possible to overwrite the whole structure and replace with only errorCode, Description and a custom message?
2 replies
Yann Simon
@yanns
Hi everyone, I made a online talk about how we use sangria for a platform with intense GraphQL usage. Maybe you'll be interested: https://yanns.github.io/blog/2021/10/28/graphql-conf/
Longyang Zhang
@zhanglongyang
Hi everyone, I'm doing some spike around Sangria stream-based subscriptions and from the doc, looks like multiple top-level fields are supported. However, checking graphql spec, Subscription operations must have exactly one root field. Also some graphql clients, like GraphiQL, don't support that either. Just wondering is Sangria doc not up-to-date? OR it does not follow the spec? Thanks
Yann Simon
@yanns
Subscriptions in sangria have been implemented when the spec was still in discussion / beta. It's possible that it's not following the spec fully.
Please welcome a new RC release: https://github.com/sangria-graphql/sangria/releases/tag/v3.0.0-RC7
The modularization is in progress: the AST and the parser are now in separated modules.
Thanks @performantdata for this!
We add deprecations in the v2 releases to make the upgrading path easier. Make sure to fix those deprecations before upgrading.
Feedback welcome!
Binh Nguyen
@ngbinh
awesome!
Gryum
@Gryum

hi everybody! Could you please help me. I have graphql query and schema. What is the best way to analyze query and retrieve all requested fileds with proper type? For example in recursive structure:

sealed trait GraphQlFieldType {
val typeName: String
}

final case class GraphQlField(name: String, fieldType: GraphQlFieldType, isArray: Boolean = false)

final case class GraphQlFieldTypeDataClass(typeName: String,
fields: List[GraphQlField]) extends GraphQlFieldType

rolandjohann
@rolandjohann
Hi all,
how do you handle transactions for subscriptions? For normal grahql requests I use a single transaction for queries and mutations. This transaction is part of the context. Using this same mechanism for subscriptions is insane. Do you create a separate SubscriptionContext without transactions or do you guys have another suggestion?
rolandjohann
@rolandjohann
Didn't consider that the types won't match anymore when I use a different context type. So the context should get an optional transaction. Do you see a more elegant solution? Since getting a transaction as option at batch requests is somehow bad: there the transaction is mandatory
rolandjohann
@rolandjohann
Ok, further question: Anyone has experience with sangria subscriptions over websocket and frontend clients like apollo/graphql-ws? Just realized that they implement an additional protocol for session handling between websockets and gql. Already found the relevant issues at github pointing towards apollo server in front of sangria. This means that the session related stuff will be handled externally by manipulating the stream elements emitted by sangria. So the implementation in scala would be to implement the session handling and wrap the sangria stream, so we manipulate the JsValues? This seems kind of hacky... Is there a way to provide a different marshaller for sangria Actions?
rolandjohann
@rolandjohann
Dug into the code and session protocol. Wrapping the sangria stream will be the way to go. Any feedback is highly appreciated.