DRing
DRing

Reputation: 7039

Firestore Rules, allow update only certain fields

I have the following database collection '/player_profiles/{userId}'. I want to use the rule that only the request.auth.uid == userId unless they are only updating the field matches which is an array. I tried this, but it denied permissions

match /player_profiles/{userId}{
        allow write: if userId == request.auth.uid; 
      allow update: if (request.resource.data.keys().hasOnly(["matches"]) && request.auth != null);
    }

And here is the Flutter code that runs the update to add in the item to the matches array:

await DatabaseProvider()
        .db
        .collection(PLAYER_COLLECTION)
        .document(widget.userProfile.userId)
        .updateData({
      'matches': FieldValue.arrayUnion([profile.userId])
    });

Im new to firestore rules but i thought this would work

Was able to get the behavior I wanted with this:

match /player_profiles/{userId}{
        allow write: if request.auth.uid == userId || (request.auth != null && request.resource.data.diff(resource.data).affectedKeys().hasOnly(["matches"]));
    }

Looking at @Doug Stevenson's answer though I can add in making sure they only are allowed to put in their own userId into other peoples profiles.

Upvotes: 1

Views: 234

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317808

request.resource.data.keys() always contains every field in the document being written, regardless of whether or not it's being updated. You should use the new MapDiff API instead to compare what's being written with what currently exists.

I think you will want to do something like this:

if
  (request.resource.data.diff(request.resource.data).affectedKeys().hasOnly(["matches"]) &&
  (request.resource.data.matches.toSet().difference(resource.data.matches) == [userId].toSet()) ||
  request.auth == null;

I have not tested, but I think you get the idea. You will need to make liberal use of the linked API documentation for security rules to work with maps, sets, and lists effectively.

Upvotes: 3

Related Questions