keystonejs / keystone

The superpowered headless CMS for Node.js — built with GraphQL and React
https://keystonejs.com
MIT License
9.25k stars 1.16k forks source link

info.cacheControl is undefined in custom queries #4429

Open SeanDoyleGit opened 3 years ago

SeanDoyleGit commented 3 years ago

Bug report

info.cacheControl is undefined in custom queries that are called from keystone.executeGraphQL

Describe the bug

Custom queries called from keystone.executeGraphQL will have info.cacheControl be undefined. info.cacheControl needs to be defined in all custom queries so the correct cache headers are applied.

For example if a query has a cache scope of PUBLIC and calls another query with a scope of PRIVATE this bug will prevent the PRIVATE scope from being applied and result in the caching of sensitive user information.

To Reproduce

Implement the following changes to the blog example in the keystone repo.

run yarn add apollo-server-express and add const { gql } = require('apollo-server-express'); to the index.js file in the blog example project.

Then add these two custom queries to the schema by adding the following code to the index.js file in the blog example project.

keystone.extendGraphQLSchema({
  queries: [
    {
      schema: 'getHello: String',
      resolver: async (obj, args, auth, info) => {
        info.cacheControl.setCacheHint({ maxAge: 60, scope: 'PUBLIC' });

        const context = keystone.createContext({ skipAccessControl: true });

        const query = gql`
          {
            getWorld
          }
        `;

        const { data, errors } = await keystone.executeGraphQL({ context, query });

        console.log(data, errors);

        return 'hello ' + data.getWorld;
      },
    },
    {
      schema: 'getWorld: String',
      resolver: async (obj, args, auth, info) => {
        info.cacheControl.setCacheHint({ maxAge: 1, scope: 'PRIVATE' });

        return 'world';
      },
    },
  ],
});

Run the blog example project and open the graphql playground http://localhost:3000/admin/graphiql

run the following query in the playground

{
  getHello
  getWorld
}

Expected result:

{
  "data": {
    "getHello": "hello world",
    "getWorld": "world"
  }
}

Actual result:

{
  "data": {
    "getHello": "hello null",
    "getWorld": "world"
  }
}

The getWorld query when run on its own returns the "world" string, however when it is called using keystone.executeGraphQL in the getHello query, the getWorld query returns null and throws the following error, TypeError: Cannot read property 'setCacheHint' of undefined

This is due to info.cacheControl being undefined when a query is called from keystone.executeGraphQL

stale[bot] commented 3 years ago

It looks like there hasn't been any activity here in over 6 months. Sorry about that! We've flagged this issue for special attention. It wil be manually reviewed by maintainers, not automatically closed. If you have any additional information please leave us a comment. It really helps! Thank you for you contribution. :)