Search code examples
firebasegoogle-cloud-firestorefirebase-security

Firestore allow creation of doc if docId matches uid of user


I see that there are answers for this question from 2019: Allow User To Create Doc Only If New Doc ID is same as User ID and they don't work for me

I want to restrict the creation of a doc in the userAccounts collection only to those who are authenticated and the docId needs to match the uid of the logged in user.

here are three versions of rules I have tried that do not work:

    match /userAccounts/{userId} {
      allow create: if request.auth.uid == userId;
      allow create: if request.auth.uid == request.resource.id;
      allow create: if path("/databases/$(database)/documents/userAccounts/" + request.auth.uid) == request.path;
    }

i also tried

    match /userAccounts/{document=**} {
      allow create: if request.auth.uid == userId;
      allow create: if request.auth.uid == request.resource.id;
      allow create: if path("/databases/$(database)/documents/userAccounts/" + request.auth.uid) == request.path;
    }

I tried the rules one at a time and no combination works for my scenario. Has the rules engine changed since 2019 so that this is not possible?

EDIT 1:

here is my current rules:

    match /userAccounts/{userId}/{documents=**} {
      allow read, update: if if request.auth != null && request.auth.uid == resource.data.userId;
      allow create: if request.auth != null && request.auth.uid == userId;
    }

Here is the jest unit test that is testing against the rules in a local emulator:

 currentUser = testEnv.authenticatedContext('testUserId123');

  it('only current user can CREATE userAccount for current user', async () => {
    const createByUser = currentUser
      .firestore()
      .collection('userAccounts')
      .add({ userId: 'testUserId123', displayName: 'test name' });

    await assertSucceeds(createByUser);
  });

How can I make a rule that only allows the current user to create a doc with an id that matches the auth.uid?


Solution

  • Okay,

    It turns out that I had a spelling mistake in my unit tests. I had some places where I used userAccount/ instead of userAccounts/ missing the plural. Once I got that sorted the following rules give me exactly what I need:

        match /userAccounts/{userId}/{documents=**} {
          allow read, update: if isAuthenticated() && request.auth.uid == resource.data.userId;
          allow create: if request.auth.uid == userId;
        }
    

    SMH