question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Adapter-knex: Wrong handling of 'where' parameter for relationships in QueryBuilder._addWheres

See original GitHub issue

Bug report

Describe the bug

Non-many relationships get wrong “where” condition object passed to recursive call in _addWheres, which later leads to the fact that the fieldAdapter is not found and the code goes into the “Many relationships” codeblock, leading finally to the error:

"GraphQL error: Cannot destructure property `rel` of 'undefined' or 'null'. GraphQL error: Cannot destructure property `rel` of 'undefined' or 'null'. GraphQL error: Cannot destructure property `rel` of 'undefined' or 'null'."

This error is directly displayed in the Admin UI in such cases (see screenshot below).

To Reproduce

1. Create a simple app with 'User" list and any object which has an “owner” property:

// User object as in example app
keystone.createList('User', {
    fields: {
      // the usual
    },
    // List-level access controls
    access: {
      read: access.userIsAdminOrOwner,
      update: access.userIsAdminOrOwner,
      create: access.userIsAdmin,
      delete: access.userIsAdmin,
      auth: true,
    },
  })

// declare access check which returns a GraphQL query on the related User list
// (as described in tutorials)
const userOwnsItem = ({ authentication: { item: user } }) => {
  if (!user) {
    return false
  }

  // Instead of a boolean, you can return a GraphQL query:
  // https://www.keystonejs.com/api/access-control#graphqlwhere
  return { owner: user.id }
}

// Create another list with "owner" access control
keystone.createList('SomeList', {
    fields: {
      owner: { type: AuthedRelationship, ref: 'User', isRequired: true },
      // other fields
    },
    // List-level access controls
    access: {
      read: userOwnsItem, // use access check returning subquery
      update: userOwnsItem,
      create: true,
      delete: userOwnsItem,
    },
  })

2.) Start admin UI and try to access the “SomeList”. You will see above error, because the

{ owner: user.id } access query triggers the bug described above.

Expected behaviour

Fix where condition

Looking through the code, I believe the code needs to be changed as:

adapter-knex.js

   line 769:  { id: where[path] },    // instead of just where[path]

because where = { owner: “1” }, so ‘where[path]’ will just evaluate to “1”, which is not a valid input for the next _addWheres call. It needs to be wrapped into a proper where condition. Assuming that the name of the primary key column is always “id”, this should be as given above.

Fix tableAlias parameter

Apart from that, I think also the following needs to be changed:

adapter-knex.js

  line 683: path => !this._getQueryConditionByPath(listAdapter, path, tableAlias) // add 'tableAlias' to parameters

The tableAlias was missing here, which sometimes lead to ‘undefined.’ alias declarations down the line

Screenshots

Screen Shot 2020-04-25 at 3 38 02 PM

System information

  • OS: MacOs
  • Node 12

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
timlesliecommented, Apr 28, 2020

Hi @stefankirchfeld, I’ve drilled into this and I’ve found the problem:

  return { owner: user.id }

should be:

  return { owner: { id: user.id } }

If we try to perform the same query directly against the graphQL API:

{
  allThings(where: { owner: "1" }) {
    id
    name
  }
}

we get the error:

"Expected type UserWhereInput, found \"1\".",

Unfortunately during the access control phase we circumvent the GraphQL type checking, which means the invalid type ends up deep in the resolver and triggers the error messages that you saw.

So I don’t think this is technically a bug, but it does highlight a less than ideal developer experience. We should probably try to solve this by pushing this category of access control through the server side of the graphQL so that we can get consistent error messaging, rather than directly accessing the resolvers, which can have rather obscure failure modes when given unexpected data.

0reactions
bladeycommented, Apr 8, 2021

Keystone 5 has officially moved into active maintenance mode as we push towards the next major new version Keystone Next, you can find out more information about this transition here.

In an effort to sustain the project going forward, we’re cleaning up and closing old issues such as this one. If you feel this issue is still relevant for Keystone Next, please let us know.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found