Page Russell
Page Russell

Reputation: 43

Firestore secuirty error: missing or insuffiecent for update method

With the rules below I am getting a missing or insuffiecient permissions error, but only for updates. I can create new documents, but any update writes are denied. What am I missing?

match /msgs/{msgs} {
allow create: if request.resource.data.keys().hasAll(["name", "msg", "status", "time"]) &&
                request.resource.data.size() == 4 &&
                request.resource.data.name is string &&
                request.resource.data.msg is string &&
                request.resource.data.status is string &&
                request.resource.data.status == "new" || "viewed" &&
                request.resource.data.time is timestamp;
allow update: if request.resource.data.size() == 1 &&
                request.resource.data.keys().hasAll(["status"]) &&
                request.resource.data.status is string &&
                request.resource.data.status == "new" || "viewed";
}

My update code is about as straightforward as it gets:

docRef.update({
        status: "viewed"
    })

Upvotes: 1

Views: 78

Answers (2)

Page Russell
Page Russell

Reputation: 43

Received the solution from the Firebase support team. It turns out that you need to make each .data.key value declaration separate and distinct. So the correct wat to accomplish this rule:

request.resource.data.status == "new" || "viewed";

is like this:

request.resource.data.status == "new" || request.resource.data.status == "viewed";

Thanks for the help everyone.

Upvotes: 0

Mike McDonald
Mike McDonald

Reputation: 15963

I think the issue here is that on update, the size isn't "the number of fields being updated" but rather "the size of the object after the update is applied to the request, but before the update is committed". This means that request.resource.data is "hydrated" with existing fields/values in addition to what's being written. You'll then check to ensure that only one field is changing.

This means your rules might look like:

allow update: if request.resource.data.size() == resource.data.size() &&
                 request.resource.data.name == resource.data.name &&
                 request.resource.data.msg == resource.data.msg &&
                 request.resource.data.time == resource.data.time &&
                 request.resource.data.status == "new" || "viewed";

Upvotes: 1

Related Questions