Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom User fields work in currentUser query but not login mutation #41

Open
nolandg opened this issue Sep 3, 2018 · 2 comments
Open

Comments

@nolandg
Copy link

nolandg commented Sep 3, 2018

I've added the field roles to my User type:

type User {
  roles: [Role!]!
  id: ID! @unique
  email: String! @unique
  password: String!
  name: String!
  inviteToken: String
  inviteAccepted: Boolean! @default(value: "true")
  emailConfirmed: Boolean! @default(value: "true")
  emailConfirmToken: String
  resetToken: String
  resetExpires: DateTime
  deletedAt: DateTime
  lastLogin: DateTime
  joinedAt: DateTime!
}

and it works great when calling the currentUser query:

{
  "data": {
    "currentUser": {
      "id": "cjl452gr600fr0a80uutqyuz9",
      "email": "[email protected]",
      "roles": [
        {
          "title": "Administer"
        }
      ]
    }
  }
}

but even though it's a required field, it returns null with the AuthPayload of login mutation:

mutation {
 login(email: "[email protected]", password: "testadmin9875") {
  token
  user {
    name
    email
    roles{
      id
      name
      title
    }
  }
 }
}

{
  "data": {
    "login": {
      "token": "xxx",
      "user": {
        "name": "Test Admin",
        "email": "[email protected]",
        "roles": null
      }
    }
  }
}

Any thoughts on why this is? Both the return types of currentUser and login reference the same User type. The resolvers for each handles them a bit differently.

currentUser: findUserById(ctx, id, info)
login: findUserByEmail(ctx, email)

info is an optional arg to findUserByEmail and it's not passed. Is this why it does not include other fields on the returned user? I'm having trouble following the flow...

Thanks!

@nolandg
Copy link
Author

nolandg commented Sep 4, 2018

The problem is indeed info not being handled at all by findUserByEmail. Any fields specified in the login query are completely ignored. I solved this by adding code to check if the user specified additional fields on User and merging them into the graphql selections required by this package. See below.

@SpaceK33z Do you want a PR for this? Without this functionality, a 2nd query is always required on login to get the actual desired User object which seems kinda pointless since login is supposed to return the logged in user.

findUserByEmail(ctx: object, email: string, info?: any) {
    // Build query AST of fields required/expected by this package
    const query = gql`
      {
        id
        email
        password
        name
        inviteToken
        inviteAccepted
        emailConfirmed
        emailConfirmToken
        resetToken
        resetExpires
        deletedAt
        lastLogin
        joinedAt
      }
    `;

    // Check if application requested any additional fields of the User object
    // If so, merge them in with the selections required above
    if(info){
      const requiredSelections = query.definitions[0].selectionSet.selections;
      const topLevelSelections = info.operation.selectionSet.selections[0].selectionSet.selections;
      const userSelections = topLevelSelections.find(s => s.name.value === 'user');
      if(userSelections){
        query.definitions[0].selectionSet.selections = [...requiredSelections, ...userSelections.selectionSet.selections];
      }
    }

    return this.db(ctx).query.user({ where: { email } }, query);
  }

@nolandg
Copy link
Author

nolandg commented Sep 4, 2018

Update to support any fragments passed to login mutation:

  findUserByEmail(ctx: object, email: string, info?: any) {
    // Build query AST of fields required/expected by this package
    const query = gql`
      {
        id
        email
        password
        name
        inviteToken
        inviteAccepted
        emailConfirmed
        emailConfirmToken
        resetToken
        resetExpires
        deletedAt
        lastLogin
        joinedAt
      }
    `;

    // Check if application requested any additional fields of the User object
    // or supplied any fragments.
    // If so, merge them in with the required above
    if(info){
      const requiredSelections = query.definitions[0].selectionSet.selections;
      const topLevelSelections = info.operation.selectionSet.selections[0].selectionSet.selections;
      const userSelections = topLevelSelections.find(s => s.name.value === 'user');
      if(userSelections){
        query.definitions[0].selectionSet.selections = [...requiredSelections, ...userSelections.selectionSet.selections];
      }

      if(info.fragments){
        for(const fragmentName in info.fragments){
          const fragment = info.fragments[fragmentName];
          query.definitions.push(fragment);
        }
      }
    }

    return this.db(ctx).query.user({ where: { email } }, query);
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant