Running UDF in ABAC Predicate results in Permission Denied


I’m trying to combine the logging function as declared here: Logging Function, with a predicate check on write for a collection.

As a base case, the predicate of:

Lambda(["oldData", "newData"], true)

works fine, and all write operations are allowed.

When I change this to:

Lambda(["oldData", "newData"], Call("log", { message: "hello", value: true }))

to attempt to log a basic message and return a true value to allow the write, neither the log document is created nor the action allowed, resulting in a

    "errors": [
            "message": "Permission denied"

on the graphql request.

I should also add that running the log UDF from the shell performs as expected, and the log document is created, as well as true being returned:

> Call('log', {message: 'hello', value: true})

I’ve given the role in question the permissions to access the function, as well as to write to the log collection. Am I missing some other permissions? Are UDFs allowed in predicate calls?


Role predicates must be read-only functions. They are used solely to determine privileges, and cannot otherwise influence the execution of, or response from, the current query. What you are attempting cannot work.

Thanks for the answer @ewan

My endgame here was to log oldData and newData, to see what they contained when making partialUpdates as allowed through:

X-Schema-Preview: partial-update-mutation

Is there any other way to inspect/log these values at runtime?


When I’ve tried to debug predicates, I’ve written a UDF that implements the same logic as the predicate, and then call it with an existing document and a new document.

It’s not ideal, because the UDF and predicate cannot share the same implementation; you have to manually ensure that the implementations match. But it is better than nothing.

If anyone reading this thread has tips or solutions that work for you, please share!

For reference, when using the partialUpdate methods through the partial-update-mutation schemas, in the write predicate lambda, do oldData and newData contain all of the fields that are on the document, or just those partial fields that are sent through in the request?

Whether you use partial-update-mutation or not, the newData document contains the fields and values that you have specified in your query.

Does that mean that the oldData will contain all of the fields of the document regardless of which fields are sent across in the case of a partial-update-mutation?

Yes. oldData contains the document as it appears in storage at the time of the transaction. That incurs at least one read operation, but might incur more depending on the size of the document.