0
votes

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.

1

1 Answers

0
votes

The query fails because the roles field was declared as required in your schema, but your resolver obviously returns no roles for the user.

To pass the validation, you need to change the field spec to optional in both GraphQL and Prisma schemas (remove the !s):

  roles: [UserRoles]