Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

The following path cannot be queried: status","data":[{"path":"status"}]}]

default discord avatar
wiesson2 years ago
46

Has anyone seen this message? I have updated to 1.7.1 and my request doesn't work anymore



/api/round-trips/62be80ce39974d8a7aaa22c1?publish=true&locale=all

I don't have API authentication enabled, maybe thats the reason?

  • discord user avatar
    jmikrut
    2 years ago

    so we released a new feature that

    validates

    queries



    you may be wanting to query on

    _status

    but are actually querying on

    status

    which might not exist



    (the field that we inject into your config for drafts / autosave is called

    _status

    )

  • default discord avatar
    wiesson2 years ago

    hmm, let me check



    This is interesting - I'm logged-in in the yellow browser but not in incognito

  • discord user avatar
    jmikrut
    2 years ago

    queries also now respect access control



    for security reasons



    you should not be able to query a field if field-level access control prevents you from reading the field



    this may be related

  • default discord avatar
    wiesson2 years ago

    hmm, so how can I quickly add a token that can read everything so that our pages are working again? 😅



    I think I have


      access: {
        read: () => true,
      },

    everywhere, but I'm double checking



    aha! Found it!



    Thanks

    @364124941832159242
  • discord user avatar
    jmikrut
    2 years ago

    beautiful

  • default discord avatar
    wiesson2 years ago

    I was migrating from a custom implementation to

    versions

    so these hard-rules are a bit unfortunate because there maybe docs that are not migrated or still have the old value

  • discord user avatar
    jmikrut
    2 years ago

    well, we don't throw any errors based on if a doc

    has a value

    we only will throw where query validation errors if you 1. don't have access to the field or 2. the field doesn't exist in the schema itself

  • default discord avatar
    lucaceck95last year

    Hi, i keep getting the same error. what i'm doing wrong?


    that's my code



    const DataRooms: CollectionConfig = {
    slug: "sponsors",


    fields: [...],
    access: DefaultAuthConfig,
    ...
    }

    const DefaultAuthConfig = {
    create: ({ req }) => {
    return DenyApiKeyOrNotLogged(req);
    },
    read: ({ req }) => {
    ` return DenyApiKeyOrNotLogged(req, true);
    },
    ...
    }

    const DenyApiKeyOrNotLogged = (req: any, isReading?: boolean) => {
    if (req.user == null) {
    return false;
    } else {
    if (req.user.role == "APIKEY" && req.user.apiKey) {
    if (isReading) {
    const canRead =
    req.collection?.config?.slug != null &&
    readableCollections.includes(req.collection.config.slug);
    if (canRead)
    return {
    or: [
    {
    _status: {
    equals: "published",
    },
    },
    {
    _status: {
    exists: false,
    },
    },
    ],
    };
    return canRead;
    } else {
    return false;
    }
    } else if (req.user.role == "administrator") {
    return true;
    }
    }
    };

    if i remove the "querying" filter on access control, i'm able to querying collection by request querystring like

    ?where[_status][equals]=published
  • default discord avatar
    wiessonlast year

    First of all I'd say that you could improve the readability by using early returns, so the level of nesting descreases.



    Is

    canRead

    true?



    const denyApiKeyOrNotLogged = (req: any, isReading?: boolean) => {
        if (req.user === null) {
            return false;
        }
    
        if (req.user.role == 'administrator') {
            return true;
        }
    
        if (!isReading) {
            return false;
        }
    
        if (req.user.role === 'APIKEY' && req.user.apiKey) {
            const canRead =
                req.collection?.config?.slug !== null &&
                readableCollections.includes(req.collection.config.slug);
    
            if (!canRead) {
                return false;
            }
    
            return {
                or: [
                    {
                        _status: {
                            equals: 'published'
                        }
                    },
                    {
                        _status: {
                            exists: false
                        }
                    }
                ]
            };
        }
    };
  • default discord avatar
    lucaceck95last year

    thanks for the refactor 😉



    btw, same error is returned


    {
        "errors": [
            {
                "name": "QueryError",
                "message": "The following paths cannot be queried: _status, _status",
                "data": [
                    {
                        "path": "_status"
                    },
                    {
                        "path": "_status"
                    }
                ]
            }
        ]
    }


    in that case, yes. it is true

  • default discord avatar
    wiessonlast year

    Hmm, not sure then



    and


    _status: {
      exists: false,
    },

    works as well?



    What happens if you return true after canRead? 😄 (just for testing purposes)

  • default discord avatar
    lucaceck95last year

    same error



    user with API-KEY can access collection

  • default discord avatar
    wiessonlast year

    and


        if (req.user.role === 'APIKEY' && req.user.apiKey) {
          return true;
        }
  • default discord avatar
    lucaceck95last year

    i tryed to filter on that single collection too


    const DataRooms: CollectionConfig = {
      slug: "sponsors",
      fields: [...],
      access: {
        read ({ req: { user } }) => {
            if (user) {
              return true;
            }      
          return {        
            _status: {
               equals: 'published'
            }
          }
      }
    }
    
    ...
    }
  • default discord avatar
    wiessonlast year

    Doesn't work either?



    Are you using the latest version of payload?

  • default discord avatar
    lucaceck95last year

    i'm using 1.7.4


    "dependencies": {
        "@payloadcms/plugin-seo": "^1.0.14-canary.0",
        "@websolutespa/payload-plugin-localization": "^0.0.3",
        "axios": "^1.3.6",
        "express": "^4.17.1",
        "payload": "^1.7.4",
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
      }

    nothing seems work.


    i'll try to update payload



    payload update 1.11.3


    Yep, it works



    update: it works always, except for apiKey users


    const DataRooms: CollectionConfig = {
      slug: "sponsors", 
      access: {
        read: ({ req: { user } }) => {
          if (user == null) return false;
          return {
            or: [
              {
                _status: {
                  equals: "published",
                },
              },
              {
                _status: {
                  exists: false,
                },
              },
            ],
          };
        },
      },
    ...
  • default discord avatar
    wiessonlast year

    Then two questions



    How do you know what the user is an API user if you have this check

    req.user.role === 'APIKEY'

    And second question


    req.user.apiKey

    - how is the apiKey added to the request? Is it a http header, or a query parameter?

  • default discord avatar
    lucaceck95last year

    apikey is added on header



    I added a radio field on my Users collection that specify my "role"


    Values can be "administrator", "APIKEY", others

  • default discord avatar
    wiessonlast year

    yes, but how does the incoming request know if the role is API user (if we don't have a cookie / JWT or sth else)



    you log

    req.user.role

    and

    req.user.apiKey

    and see if they are defined?

  • default discord avatar
    lucaceck95last year

    there's the "enableAPIKey" on User



    APIKEY user


    {
      id: '6453ae2a8200c13a0fe97464',
      role: 'APIKEY',
      enableAPIKey: true,
      apiKey: 'a8861d6e-315a-4351-8fbb-da2447d0838f',
      email: 'xxxxxxx@xxxxxxx.xx',
      createdAt: '2023-05-04T13:07:54.919Z',
      updatedAt: '2023-05-04T13:07:54.919Z',
      collection: 'users',
      _strategy: 'api-key'
    }


    administrator user


    {
      id: '6452232f749f4190c8547ed1',
      role: 'administrator',
      enableAPIKey: false,
      apiKey: '1936273e-c16a-413a-9aa7-9bbaf536cec8',
      email: 'xxxxxxx@xxxxxxx.xx',
      createdAt: '2023-05-03T09:02:39.814Z',
      updatedAt: '2023-07-21T10:08:18.712Z',
      collection: 'users',
      _strategy: 'local-jwt'
    }
  • default discord avatar
    wiessonlast year

    ah ok, thank you!



    and if you console.log

    req.role.user

    and

    req.user.apiKey

    are they defined?

  • default discord avatar
    lucaceck95last year

    yes. they're defined

  • default discord avatar
    wiessonlast year

    But if this works, then the other case with the api user should work as well

  • default discord avatar
    lucaceck95last year

    it

    should

    , but it doesn't 😕

  • default discord avatar
    wiessonlast year
    const DataRooms: CollectionConfig = {
      slug: "sponsors", 
      access: {
        read: ({ req: { user } }) => {
          if (user == null) return false;
          if (req.role.user && req.user.apiKey) {
          return {
            or: [
              {
                _status: {
                  equals: "published",
                },
              },
              {
                _status: {
                  exists: false,
                },
              },
            ],
          }
         };
        },
      },
    ...


    this doesn't work?

  • default discord avatar
    lucaceck95last year

    wait wait...


    req is PayloadRequest


    role and apiKey are properties of user



    if (user.role && user.apiKey) {
  • default discord avatar
    wiessonlast year

    You are right



    Technically if both are defined (as you said) then there should be no difference



    just another conditional check between

  • default discord avatar
    lucaceck95last year

    exactly


    same error

  • default discord avatar
    wiessonlast year

    Error means - no filtering?

  • default discord avatar
    lucaceck95last year
    {
        "errors": [
            {
                "name": "QueryError",
                "message": "The following paths cannot be queried: _status, _status",
                "data": [
                    {
                        "path": "_status"
                    },
                    {
                        "path": "_status"
                    }
                ]
            }
        ]
    }
  • default discord avatar
    wiessonlast year

    Is draft enabled?

  • default discord avatar
    lucaceck95last year
    versions: {
        // maxPerDoc: 50,
        drafts: true,
      },
  • default discord avatar
    wiessonlast year

    have you saved (and published) a document after enabling it?

  • default discord avatar
    lucaceck95last year

    i added all documents after enabling it

  • default discord avatar
    wiessonlast year

    just to be sure, the error happens with and without this line:



    if (user.role && user.apiKey) { ... }
  • default discord avatar
    lucaceck95last year

    correct

  • default discord avatar
    wiessonlast year

    Interesting



    As

    @364124941832159242

    wrote


    we only will throw where query validation errors if you 1. don't have access to the field or 2. the field doesn't exist in the schema itself

    If you have drafts and (versions) enabled, I can't see why it should not work



    import { CollectionConfig } from 'payload/types';
    
    export const Pages: CollectionConfig = {
      slug: 'pages',
      access: {
        read: ({ req }) => {
          // If there is a user logged in,
          // let them retrieve all documents
          if (req.user) return true;
    
          // If there is no user,
          // restrict the documents that are returned
          // to only those where `_status` is equal to `published`
          return {
            _status: {
              equals: 'published',
            },
          };
        },
      },
      versions: {
        drafts: true
      },
      //.. the rest of the Pages config here
    }



    Like this example



    Out of curiosity - if you apply the example code, you still see the same error? (just once, not twice)

  • Can I just jump in here and have you clarify that, the collection variable name is “DataRooms”, but the

    slug

    is “sponsors”, is that correct? i.e. you don’t have 2 collections with the same slug do you? (Can’t remember if we throw an error or not if this happens)

  • default discord avatar
    lucaceck95last year

    yes, it is correct. collection "sponsors" is unique



    update


    i'm trying filter another collection.


    this is my "auth config" now


    ...
    switch (req.user.role) {
        case "administrator":
          return true;    
        case "APIKEY":
          if (!req.user.enableAPIKey || req.user.apiKey == null) return false;
          if (!isReading) return false;
          if ( req.baseUrl.startsWith("/media") || req.baseUrl == "/api/globals/siteconfigs" )
            return true;
          if (
            req.collection?.config?.slug != null &&
            APIKeyAllowedCollections.includes(req.collection.config.slug)
          ) {
            switch (req.collection.config.slug) {
              case "vetrine":
                let today = new Date();
                return {
                  and: [
                    {
                      startVisibility: {
                        less_than_equal: today,
                      },
                    },
                    {
                      endVisibility: {
                        greater_than_equal: today,
                      },
                    },
                  ],
                };
              default:
                return true;
            }
          }


    i'm working on the auto filter on items in collection "vetrine"


    apiKey users need to get the list of vetrine where today is between startVisibility and endVisibility



    that's the result


    {
        "errors": [
            {
                "name": "QueryError",
                "message": "The following paths cannot be queried: startVisibility, endVisibility",
                "data": [
                    {
                        "path": "startVisibility"
                    },
                    {
                        "path": "endVisibility"
                    }
                ]
            }
        ]
    }


    UPDATE



    i found out that if a "vetrina" doesn't match the filter, everything works


    example 1:

    today = 2023-08-03;
     startVisibility = 2023-09-01; 
    endVisibility = 2023-09-10

    http://myaddress:3030/api/vetrine

    ->

    {
        "docs": [],
        "totalDocs": 0,
        "limit": 10,
        "totalPages": 1,
        "page": 1,
        "pagingCounter": 1,
        "hasPrevPage": false,
        "hasNextPage": false,
        "prevPage": null,
        "nextPage": null
    }


    example :2

    today = 2023-08-03;
     startVisibility = 2023-08-01; 
    endVisibility = 2023-09-10

    http://myaddress:3030/api/vetrine

    ->

    {
        "errors": [
            {
                "name": "QueryError",
                "message": "The following paths cannot be queried: startVisibility, endVisibility",
                "data": [
                    {
                        "path": "startVisibility"
                    },
                    {
                        "path": "endVisibility"
                    }
                ]
            }
        ]
    }


    UPDATE


    I can filter by doc.id


    i'm still not able to filter by other fields



    that's my collection


    const Vetrine: CollectionConfig = {
      slug: "vetrine",  
      admin: {
        useAsTitle: "title",
      },
      access: DefaultAuthConfig,
      fields: [    
        {
          type: "row",
          fields: [
            {
              name: "badge",
              type: "text",          
            },
            {
              name: "target",
              required: true,
              type: "text",
            },
          ],
        },
        {
          type: "row",
          fields: [
            {
              name: "imageUrl",
              type: "text",          
            },
            {
              name: "customImage",
              type: "upload",
              relationTo: "media",         
            },
          ],
        },
        {
          name: "title",
          required: true,
          localized: true,
          type: "text",
        },
        {
          name: "text",
          localized: true,
          type: "text",
        },    
        {
          type: "row",
          admin: {
            position: "sidebar",
          },
          fields: [
            {
              name: "startVisibility",
              type: "date",
              required: true,
              admin: {
                date: {
                  pickerAppearance: "dayAndTime",
                  timeFormat: "HH:mm",
                  displayFormat: "dd MMM yyyy - HH:mm",
                },
              },
            },
            {
              name: "endVisibility",
              type: "date",
              required: true,
              admin: {
                date: {
                  pickerAppearance: "dayAndTime",
                  timeFormat: "HH:mm",
                  displayFormat: "dd MMM yyyy - HH:mm",
                },
              },
            },
          ],
        },
      ],
      versions: {
        maxPerDoc: 1,
        drafts: true,
      },
    };


    i can filter by id, title


    i cannot filter by startVisibility, badge...



    idk if this can help



    guys, i think i've found the problem.



    payload let me filter by title and id because also collection "Tribunali" (in relationship) has id and title.


    i was debugging find.js and buildQuery.js and notice that


    it gives me error because startVisibility is not a field of collection "tribunali"



    same thing for the past messages.


    collection sponsors has status field, but the collection of relationship field, doesn't have status



    i want to filter only the collection "vetrine"


    how can i do it?

  • discord user avatar
    dribbens
    last year
    @443492031021580288

    I wonder if we have a bug where nesting the field in the rows is breaking query validation. If you move the visibility fields out of the row wrapping them does it work?


    This might have been fixed in an earlier version, I can't remember.

  • default discord avatar
    lucaceck95last year

    I tried but no. It doesn't work

  • discord user avatar
    dribbens
    last year

    Oh! I see the issue.


    You are using one access function for many collections.


    In that code you shared you have a switch on the req.collection.


    This doesn't work because this logic is applying to relations that don't have those fields.


    That's why it works when results don't match.


    Your media collection doesn't have startVisibility.



    The req.colletion is always bound to the API of the request so you are getting incorrect access based queries returned for relationships.



    Did that make sense

    @443492031021580288

    ?

  • default discord avatar
    lucaceck95last year

    Exactly


    The "auth" function is used in all my collections


    Debugging those files, I got to your point.



    Im now trying to replace the req.collection.config.access.read, based on slug, but nothing... That is another wrong workaround.



    So, Is It possibile having a single access function filtering results based on collection or should i implement those access functions in every collection?

  • discord user avatar
    dribbens
    last year

    You could verify that this the issue by removing the relationship field and making sure your query works.


    I'm trying to think of a way you could do the switch on a different property...



    You would have to wrap your access function in a function that passes in the slug.



    That way in your collection config you can call the getDefaultAccess('vetrine') and use that arg instead of the req.collection to get the slug

  • default discord avatar
    lucaceck95last year

    i tried



    it works



    collection ->
    ...
      access: DefaultAuthConfig("contentpages"),
    ...

    const DefaultAuthConfig = (col: string) => {
    return {
        ...
        read: ({ req }) => {
          return DenyApiKeyOrNotLogged(req, col, true);
        },
    ...
    }


    const DenyApiKeyOrNotLogged = (req: any, coll: string, isReading?: boolean) => {
    ...
    switch (coll) {
              case "vetrine":
                let today = new Date();
                return {
                  and: [
                    {
                      startVisibility: {
                        less_than_equal: today,
                      },
                    },
                    {
                      endVisibility: {
                        greater_than_equal: today,
                      },
                    },
                  ],
                };
                
              default:
                return true;
            }
    ...
    }
  • discord user avatar
    dribbens
    last year

    🎉

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.