Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
07-27-2021 11:45 AM
Hey there, I'm not too familiar with JWT token and I can't seems to figure out how to create a new users with the admin token.
I thought you were suppose to modify the GraphQL schema to add
extend type Customer @auth(rules: [{operations: [CREATE, UPDATE, DELETE], roles: ["admin"]}])
But I can't seem to use mutation to create a new Customer still?
Any help?
07-27-2021 01:37 PM
Can you share the request header and the GraphQL mutation you're trying?
07-30-2021 10:52 AM
Yep sure thing.
Http request header:
{
"authorization" :"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJCb2JMb2JsYXc3Njg3Iiwicm9sZXMiOlsiYWRtaW4iXSwiaWF0IjoxNTE2MjM5MDIyfQ.f2GKIu31gz39fMJwj5_byFCMDPDy3ncdWOIhhqcwBxk"
}
GraphQL mutation:
mutation {
createCustomers(
input: [
{
username: "BookWorm"
reviews: {
create: [
{
rating: 10
text: "Why not"
book: { connect: { where: { isbn: "190962151X" } } }
}
]
}
orders: {
create: {
books: {
connect: [
{ where: { title: "Ross Poldark" } }
{ where: { isbn: "1119387507" } }
{ where: { isbn: "1492047686" } }
]
}
shipTo: {
create: {
address: "Nowhere"
location: { latitude: 55.6122270502, longitude: 12.99481772774 }
}
}
}
}
}
]
)
}
Here is my GraphQL Schema for good measures:
type Order {
orderID: ID! @id
placedAt: DateTime @timestamp
shippingCost: Float
shipTo: Address @relationship(type: "SHIPS_TO", direction: OUT)
customer: Customer @relationship(type: "PLACED", direction: IN)
books: [Book] @relationship(type: "CONTAINS", direction: OUT)
}
extend type Order {
subTotal: Float @cypher(statement:"MATCH (this)-[:CONTAINS]->(b:Book) RETURN sum(b.price)")
shippingCost: Float @cypher(statement:"MATCH (this)-[:SHIPS_TO]->(a:Address) RETURN round(0.01 * distance(a.location, Point({latitude: 40.7128, longitude: -74.0060})) / 1000, 2)")
estimatedDelivery: DateTime @ignore
}
extend type Order @auth(rules: [{allow: {customer: {username: "$jwt.sub"}}}, {roles: ["admin"]}])
type Customer {
username: String
orders: [Order] @relationship(type: "PLACED", direction: OUT)
reviews: [Review] @relationship(type: "WROTE", direction: OUT)
recommended(limit: Int = 3): [Book] @cypher(statement: "MATCH (this)-[:PLACED]->(:Order)-[:CONTAINS]->(:Book)<-[:CONTAINS]-(:Order)<-[:PLACED]-(c:Customer) MATCH (c)-[:PLACED]->(:Order)-[:CONTAINS]->(rec:Book) WHERE NOT EXISTS((this)-[:PLACED]->(:Order)-[:CONTAINS]->(rec)) RETURN rec LIMIT toInteger($limit)")
}
extend type Customer @auth(rules: [{where: {username: "$jwt.sub"}}])
extend type Customer @auth(rules: [{operations: [CREATE, UPDATE, DELETE], roles: ["admin"]}])
type Address {
address: String
location: Point
order: Order @relationship(type: "SHIPS_TO", direction: IN)
}
extend type Address {
currentWeather: Weather @cypher(statement:"CALL apoc.load.json('https://www.7timer.info/bin/civil.php?lon=' + this.location.longitude + '&lat=' + this.location.latitude + '&ac=0&unit=metric&output=json&tzshift=0') YIELD value WITH value.dataseries[0] as weather RETURN {temperature: toFloat(weather.temp2m), windSpeed: toFloat(weather.wind10m.speed), windDirection: weather.wind10m.direction, precipitation: weather.prec_type, summary: weather.weather} AS conditions")
}
type Weather {
temperature: Float
windSpeed: Float
windDirection: String
precipitation: String
summary: String
}
type Book {
isbn: ID!
title: String
price: Float
description: String
authors: [Author] @relationship(type: "AUTHOR_OF", direction: IN)
subjects: [Subject] @relationship(type: "ABOUT", direction: OUT)
reviews: [Review] @relationship(type: "REVIEWS", direction: IN)
}
extend type Book @auth(rules: [{operations: [CREATE, UPDATE, DELETE], roles: ["admin"]}])
extend type Book {
similar: [Book] @cypher(statement: """
MATCH (this)-[:ABOUT]->(s:Subject)<-[:ABOUT]-(rec:Book)
WITH rec, COUNT(*) AS num
RETURN rec ORDER BY num DESC
""")
}
type Review {
rating: Int
text: String
createdAt: DateTime @timestamp
book: Book @relationship(type: "REVIEWS", direction: OUT)
author: Customer @relationship(type: "WROTE", direction: IN)
}
extend type Review @auth(rules: [{operations: [CREATE,UPDATE], bind: {author: {username: "$jwt.sub"} }}])
type Author {
name: String!
books: [Book] @relationship(type: "AUTHOR_OF", direction: OUT)
}
type Subject {
name: String!
books: [Book] @relationship(type: "ABOUT", direction: IN)
}
extend type Subject @auth(rules: [{isAuthenticated: true}])
type Mutation {
mergeBookSubjects(subject: String!, bookTitles: [String!]!): Subject @cypher(statement: """
MERGE (s:Subject {name: $subject})
WITH s
UNWIND $bookTitles AS bookTitle
MATCH (t:Book {title: bookTitle})
MERGE (t)-[:ABOUT]->(s)
RETURN s
""")
}
type Query {
bookSearch(searchString: String!): [Book] @cypher(statement: """
CALL db.index.fulltext.queryNodes('bookIndex', $searchString+'~')
YIELD node RETURN node
""")
}
extend type Query {
booksForCurrentUser: [Book] @auth(rules: [{ isAuthenticated: true }]) @cypher(statement: """
MATCH (c:Customer {username: $auth.jwt.sub})-[:PLACED]->(:Order)-[:CONTAINS]->(b:Book)
MATCH (b)-[:ABOUT]->(s:Subject)<-[:ABOUT]-(rec:Book)
WITH rec, COUNT(*) AS score ORDER BY score DESC
RETURN rec
""")
}
error message:
{
"error": {
"errors": [
{
"message": "Field \"createCustomers\" of type \"CreateCustomersMutationResponse!\" must have a selection of subfields. Did you mean \"createCustomers { ... }\"?",
"locations": [
{
"line": 2,
"column": 3
}
],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED",
"exception": {
"stacktrace": [
"GraphQLError: Field \"createCustomers\" of type \"CreateCustomersMutationResponse!\" must have a selection of subfields. Did you mean \"createCustomers { ... }\"?",
" at Object.Field (/sandbox/node_modules/graphql/validation/rules/ScalarLeafsRule.js:40:31)",
" at Object.enter (/sandbox/node_modules/graphql/language/visitor.js:323:29)",
" at Object.enter (/sandbox/node_modules/graphql/utilities/TypeInfo.js:370:25)",
" at visit (/sandbox/node_modules/graphql/language/visitor.js:243:26)",
" at Object.validate (/sandbox/node_modules/graphql/validation/validate.js:69:24)",
" at validate (/sandbox/node_modules/apollo-server-core/dist/requestPipeline.js:233:34)",
" at Object.<anonymous> (/sandbox/node_modules/apollo-server-core/dist/requestPipeline.js:119:42)",
" at Generator.next (<anonymous>)",
" at fulfilled (/sandbox/node_modules/apollo-server-core/dist/requestPipeline.js:5:58)",
" at processTicksAndRejections (internal/process/task_queues.js:93:5)"
]
}
}
}
]
}
}
08-04-2021 02:54 PM
"CreateCustomersMutationResponse!\" must have a selection of subfields. Did you mean \"createCustomers { ... }\"?"
Seems like you're having issues with the mutation itself and not JWT.
did you specify what data should be returned.. Looks like you need to add the fields that need to be returned by the mutation.
add what's inside the '{}
' like this;
mutation{
Customer(
// add you params here
){
username
orders{
orderID
placedAt
shippingCont
...
}
reviews{
rating
text
createdAt
...
}
recommended {
isbn
title
price
...
}
}
}
All the sessions of the conference are now available online