I'm relatively new to the world of GraphQL / Prisma / Apollo and working on an app where I need login functionality, and access restrictions based upon a User's permissions.
When I run my login mutation it fails if I request the User's "roles" field to be returned and I can't for the life of me figure out why.
If I do a simple query on all Users and request the "roles" field it returns no problem. Likewise if I do a query on a single User and filter by any other field: - id, email, username.
My app is setup as this:
datamodel.graphql (prisma)
type User {
id: ID! @id @unique
name: String!
email: String! @unique
username: String! @unique
password: String!
roles: [UserRoles!]!
}
enum UserRoles {
ADMIN
USER
DIRECTOR
}
schema.graphql (react / apollo)
type User {
id: ID!
name: String!
email: String!
username: String!
password: String!
roles: [UserRoles!]!
}
enum UserRoles {
ADMIN
USER
DIRECTOR
}
Mutation.js (resolvers front end)
async loginUser(parent, args, { prisma }, info) {
const { username, password } = args.data;
const user = await prisma.query.user({ where: { username } });
if (!user) {
throw new Error("Invalid login credentials. Please try again");
}
const passwordIsMatch = await bcrypt.compare(password, user.password);
if (!passwordIsMatch) {
throw new Error("Invalid login credentials. Please try again");
}
return {
user,
token: generateToken(user.id),
};
},
If I run the login mutation as something like this it runs fine.
mutation LoginUser($username: String!, $password: String!){
loginUser(data: {
username: $username
password: $password
}) {
user {
id
name
}
token
}
}
But if I run it like this it fails with a message of "Cannot return null for non-nullable field User.roles."
mutation LoginUser($username: String!, $password: String!){
loginUser(data: {
username: $username
password: $password
}) {
user {
id
name
roles
}
token
}
}
Any ideas on how to fix this? Or should I wait for the response on this mutation and then run a query for a user with the id which is returned and then pull the "roles" field from that? That seems a little superfluous to me, as I thought one of the great benefits of GraphQL was minimising the number of http requests.