0
votes

Im trying to set up rules for a Firestore Database.

Im having some trouble setting up rules for nested objects.

The database structure looks like this:

Users ( collection of User objects )

-----userDocument ( the name of the document matches the auth-users uid )

-----------------users ( subcollection of users )

-------------------------userdocument ( the name of the document matches the auth-users uid )

note: the last userDocument does not contain any references.

He has his own document in the main Users collection.

I want every user to have read/write access to every user in the Users collection, who has a matching ID of the users in his subcollection of users. Furthermore, any user should be able to create a new user on the database, as long as they are authenticated with firebase Auth.

I have tried following solutions, it doesnt work:

    service cloud.firestore {
  match /databases/{database}/documents {
  match /users/{userId}{
  allow read, write: if exists(/databases/$(database)/documents/users/userId/users/$(request.auth.uid)) || userId == request.auth.uid;
  }
}
}

What i need is:

  • A way to get all document names from the logged in userĀ“s subcollection of users
  • A way to grant access to ONLY these users

Example:

The user has 1 user in his subcollection, so the user should have access to read/write his own user, and qb2pa1TWXHZr0NZUREealgWrOYb2.

1

1 Answers

2
votes

I found a solution that works, i hope this helps someone in the future.

Everything is fully tested, commented and working.

service cloud.firestore {

//This is the "root" of the database. From here we can match into our collections.
  match /databases/{database}/documents {

    //matching the collection "users", the wildcard "userId" is used for the user we will be working with.
    match /users/{userId} 
    {
    //Everyone is allowed to write, if they are logged in.
    allow write: if request.auth.uid != null;
    //A user is allowed to read, update and delete his own account.
    allow read, update, delete: if request.auth.uid == userId;
    //A user is allowed to read a user, if the user matching "userId" exists in the logged in users own subcollection of users.
    allow read: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/users/$(userId));

                 //Matching the subcollection "users", still in the user matching userId.
           match /{users=**}{
           //A user is allowed to read, write, update, delete in the subcollection on his own account.
                 allow read, write, update, delete: if request.auth.uid == userId;
           //A user is allowed to read, write, update, delete in the subcollection, 
           //if the user matching "userId" exists in the logged in users own subcollection of users.
           allow read, write, update, delete: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/users/$(userId));
                 }
    }

    //matching the collection "duties", the wildcard "dutyId" is used for the duty we will be working with.
    match /duties/{dutyId}{
    //Everyone is allowed to write, if they are logged in.
    allow read, write: if request.auth.uid != null;
    // A user is allowed to read, write and update if the string in the field "ownerId" in the duty matching "dutyId" == the users Uid.
    allow read, update: if resource.data.ownerId == request.auth.uid;
    //A user is allowed, if the user matching "ownerId" exists in the logged in users subcollection of users.
    allow read, update, delete: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/users/$(resource.data.ownerId));
    }
  }
}