6
votes

I'm trying to create an application which allows users to collaborate on lists. Every user needs to be invited in order to be able to work on the list.

I structured my data like that (loosely based on this blog post). Also this structure can be changed if needed.

list
  list_1:
    users:
      owner:
        [email protected]: true
      shared:
        [email protected]: true
        [email protected]: true
    id
    name
    items:
      item_1:
        id:
        name:
      ...

What I'm trying to achieve: Everyone should be able to create lists. They creator then becomes the owner of the created list. Only the owner and users in the "shared" document should be able to read and write to this list.

I guess that the permission settings should look something like this. But this isn't working:

service cloud.firestore {
  match /databases/{database}/documents {
    match /lists/{listId}/{anything=**} {
        allow read, write: if !exists(resource.data.users.owner) ||
                               resource.data.users.owner == request.auth.token.email ||
                               request.auth.token.email in resource.data.users.shared
    }
  }
}
1

1 Answers

4
votes

I was able to figure it out.

I changed the data structure to this:

list
  list_1
    owner: [email protected]
    writeAccess: [[email protected], [email protected]]
    id
    name
    items:
      item_1:
        id:
        name:
      ...

Then the database rules like this are working:

service cloud.firestore {
  match /databases/{database}/documents {
    match /lists/{listId} {
        // Allow RW on lists for owner, shared user or for everyone if it's a new list
      allow read, write: if resource.data.owner == request.auth.token.email ||
                            request.auth.token.email in resource.data.writeAccess ||
                            !exists(/databases/$(database)/documents/lists/$(listId))
    }
    match /lists/{listId}/items/{itemId} {
        // Allow RW on item for owner or shared user of parent list
        allow read, write: if get(/databases/$(database)/documents/lists/$(listId)).data.owner == request.auth.token.email ||
                              request.auth.token.email in get(/databases/$(database)/documents/lists/$(listId)).data.writeAccess ||
                             !exists(/databases/$(database)/documents/lists/$(listId)) // Needed for new lists. Because lists and items are created in a batch
    }
  }
}