enonic / lib-guillotine

Apache License 2.0
3 stars 0 forks source link

Limit how many times a query can be executed in a nested graph #267

Open ComLock opened 1 year ago

ComLock commented 1 year ago

This is related to https://github.com/enonic/lib-graphql/issues/133

But goes beyond it.

Lets say we have two queries

And both these graphs are valid and useful:

getUsers(name: "John") {
    name
    getGroups {} # The groups John has
}
getGroups(name: "Developers") {
    getUsers {
        name # All the names of the developers
    }
}

It's very easy to make a Denial of Service query like this

getUsers{ # All the users
    getGroups{ # All the groups of all the users
        getUsers{ # x ^ 2
            getGroups{ # x ^ "infinity"
            }
        }
    }
}

If we make a passalong object in source which keeps counters for each query, we could limit how many time a query is allowed to exist inside a nested graph.

getUsers.resolver({
    context,
    source
}) {
    if(source.queryCounts.getUsers >= context.queryLimits.getUsers) {
        throw new Error(`You are not allowed to call getUser more than ${context.queryLimits.getUsers} times in a graph`);
    } 
    source.queryCounts.getUsers++;
    return {
        ...results
        queryCounts: source.queryCounts
    };
}

A query such as this, would still work, as source is only passed down a nested graph.

getUsers(name: "John") {
    name
}
alias: getUsers(name: "Jane") {
    name
}