Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Performant Data
@performantdata
This message was deleted
1 reply
Performant Data
@performantdata
Shouldn't sangria-akka-http-example have something more like a CC0 license?
Nick Hudkins
@nickhudkins
Hey @performantdata, I didn’t know GraphQL playground was merging. Just saw your PR, I’ll add some comments there
JayalakshmiH
@JayalakshmiH
Hi all, I am pretty new to Sangria. Need some examples for resolving union types. For .js implementation, i see that we need to add __resolveType function to resolve unions. I am wondering how it has to be done in case of Sangria. If someone could provide some examples, it would be great. Thanks!
JayalakshmiH
@JayalakshmiH

Following up on my previous question on union type, have made changes to return all possible types of union as a default case. But I wanted to add check based on the __typename requested for. I see in .js, objects are resolved based on the unique field name that each type has. Am looking for something equivalent in sangria.

__resolveType: obj => {
if (obj.reason) {
return "TimeoutError";
}

  if (obj.field) {
    return "ValidationError";
  }

  return null;
}
Nick Hudkins
@nickhudkins
Can you describe more in detail your use case and maybe what the query would be in the case you need to check for the type being requested? This sounds a lot like implementing the node interface like in the relay spec.
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