Index read authorization with predicate condition and multiple terms

I have this index:

{
  name: "user_game_view_by_game_and_user",
  unique: true,
  serialized: true,
  source: "user-game-views",
  terms: [
    {
      field: ["data", "game"]
    },
    {
      field: ["data", "user"]
    }
  ]
}

where game and user should both be references to documents in their respective collections.

I am attempting to set my authorization up so that users can only query the index for their own user. I have created this role:

{
  "ref": Role("UserRole"),
  "ts": 1688418068610000,
  "name": "UserRole",
  "privileges": [
    {
      "resource": Collection("users"),
      "actions": {
        "read": Query(Lambda("ref", Equals(CurrentIdentity(), Var("ref")))),
      }
    },
    {
      "resource": Index("user_game_view_by_game_and_user"),
      "actions": {
        "unrestricted_read": Query(Lambda("terms", Equals(Select(1, Var("terms")), CurrentIdentity()))),
      }
    }
  ],
  "membership": [
    {
      "resource": Collection("users"),
    }
  ]
}

I would expect the read predicate for the user_game_view_by_game_and_user index to look at the terms passed into the index query (a game ref and a user ref) and return true if the second term (the user ref) is equal to the current user. However, running this query in the fauna shell (with an appropriate secret):

Get(
  Match(Index("user_game_view_by_game_and_user"), [
    Ref(Collection("games"), "368262571308875857"),
    CurrentIdentity()
  ])
)

returns

Error: [
  {
    "position": [],
    "code": "permission denied",
    "description": "Insufficient privileges to perform the action."
  }
]

I have confirmed that the relevant user-game-view document exists and that CurrentIdentity() is returning the appropriate user reference. I can run the query with admin permissions (substituting the CurrentIdentity() call for a direct reference to the corresponding user) and it returns the correct document.

I would greatly appreciate some help debugging this predicate. I’ve tried a variety of approaches to this predicate, but it really feels like I’m stabbing in the dark. Debugging the function through the console has been extremely frustrating - it provides no feedback at all other than “permission granted/denied” or an error saving if my syntax is incorrect, and I’ve found the documentation to be extremely anemic (Attribute-based access control (ABAC) - Fauna Documentation and, to a lesser extent, User-defined functions - Fauna Documentation).

Thank you in advance for any help with this. Please let me know if there’s anything I can provide to help.

I was able to get this to work if I add read permissions for the user-game-views collection to the user role. My understanding was that unrestricted read on an index should work without read permissions on underlying collections, and I have seen that behavior for other indexes. Am I missing something here?

The unrestricted_read permission doesn’t give you read access to the collection, it just gives you read access to all index entries.

All index entries are associated with their respective Document. Without unrestricted_read Fauna will filter out index entries for which you do not have read access. Therefore, unrestricted_read simply skips that step. But again read and unrestricted_read for indexes do not impact the access to the documents themselves.

You received permission denied because you tried to Get the document. I expect you should be able to run the following without read access on the Collection, because it only returns the index entries.

Paginate(
  Match(
    Index("user_game_view_by_game_and_user"),
    [Ref(Collection("games"), "368262571308875857"), CurrentIdentity()]
  )
)

Ah gotcha, that makes sense. Thanks for the help and sorry for the dumb question :joy:

Only dumb question is one not asked :slight_smile:

We’re glad to help!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.