Cascade producing wrong resutls when auth prevents children

I am not gonna post the full working example of this bug for sake of time, but this should get the picture across.

I have a type Contact that has an edge tags to the type Tag. I have restricted tags so that if a JWT is not privided at all with a valid user, no tags are visible. There are some other rules on Tag as well to control group accessed tags. Looking at this query:

query {
  queryContact @cascade {
    id
    tags {
      id
      access {
        id
        grants {
          isGroup {
            slug
          }
        }
      }
    }
  }
}

This should only get the tags that are in a group access control list (custom defined/managed by auth rules). When I run this with a JWT that has access to tags, it provides the correct empty results when no contacts are present that are tagged with group tags.

However, if I remove the JWT, then I get wrong results that cascade should filter out.

{
  "data": {
    "queryContact": [
      {
        "id": "0x285d"
        "tags": []
      },
      {
        "id": "0x285e"
        "tags": []
      },
      ...
    ]
  }
}

Those results should not be returned because they do not obey the cascade directive because they did not return any tags.

@amaster507 Can you post the schema and auth rules for the Type Contact, Tag, Access, Grant and isGroup? It will help me to better understand and repro the issue and I can quickly get back to you with a solution/fix.

I ran into this again today and here is a very tiny dataset to duplicate:

type Contact {
  id: ID!
  name: String!
  isUser: User
}

type User @auth(
  query: { rule: "{$NO: {eq: \"yes\"}}" }
) {
  username: String! @id
  isContact: Contact! @hasInverse(field: isUser)
}

# No Need for Dgraph.Authorization as we are doing a absolute block where no JWT is accepted.

Here are the queries/mutations to run to test:

mutation AddData {
  addContact(input: [
    {name:"a"}
    {name:"b",isUser:{username:"z"}}
    {name:"c",isUser:{username:"y"}}
    {name:"d"}
  ]) {
    numUids
    contact {
      id
      name
      isUser {
        username
      }
    }
  }
}
mutation Reset {
  deleteUser(filter:{}){numUids}
  deleteContact(filter:{}){numUids}
}
query GetOnlyUsers {
  queryContact @cascade {
    id
    isUser {
      username
    }
  }
}
  1. AddData mutation
  2. GetOnlyUsers query
  3. See result set returned not honoring @cascade
  4. Reset mutation
  5. Repeat as desired

EDIT: Note, this bug seems to be particular to JWT value rules. It is no longer present if the @auth rule is changed to:

@auth(
  query: { rule: "query { queryUser(filter: {username:{eq:\"z\"}}) { username } }" }
)

@amaster507 Thanks for reporting this issue. We seem to be removing fields from query when the auth variables is either absent or if the RBAC is evaluated to false and this is causing the cascade to fail. The above issue only occurs when we have @cascade with auth in the following two cases.

  1. RBAC is evaluated to false.
  2. Auth variables is missing.

This is how the query is being rewrittern which is incorrect.

query {
  queryContact(func: uid(ContactRoot)) @cascade {
    id : uid
  }
  ContactRoot as var(func: uid(Contact2))
  Contact2 as var(func: type(Contact))
}

I have opened an issues and will be looking at it in the coming week. I will update you once we have a fix.

1 Like

This issue is fixed in master.

1 Like