I am trying to create a document in Google Firestore as follows:
const docData = {
name: name,
type: type,
ownerId: this.auth.session!.userUid
}
await addDoc(collection(this.firebase.firestore, "projects"), docData)
I can see (via an onAuthStateChanged(...)
callback), that the user is signed-in and making an authenticated request. The payload is { name: "dfgdfgdfg", type: "CommonV1", ownerId: "5sp...F53" }
(ellipses added for brevity; the full ownerId
is given in the actual request). However, I receive an "FirebaseError: Missing or insufficient permissions." error.
I would like projects
to be accessible to the user who created them, and nobody else (to begin with). To this end, my security rules are as follows:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in and they own the resource.
function OwnsResource() {
return request.auth.uid != null && resource.data.ownerId == request.auth.uid;
}
// By default, no documents may be read.
match /{document=**} {
allow read, write: if false;
}
// Allow a project to be created, read or written by its owner.
match /projects/{project} {
allow create, read, write: if ownsResource();
}
}
}
I believe the problem is in my rules, but I cannot see where.
How can I resolve this problem and create the project, as desired?
2
Answers
I was pointed to the firebase rules editor in the Firebase console. It helped me identify an error (in addition to Phil's comment). Where I had:
It should have had:
This works. For anyone reading this: the Firestore rules playground in the Firebase console is an excellent tool.
Ignoring that
allow create
is redundant withallow write
:resource.data
points to the data in your document as it was when you made the change. So for a document that does not yet exist, this will benull
. You then callnull.ownerId
, which throws an exception and blocks the change.To prevent throwing the exception, you’d need to check for this first:
However, this rule won’t handle a newly created document (as
resource.data
will benull
), you’d need to either add to the above function, or create a new one:It is important to note that in the above rules that the prior state of the document is checked. By using just
request.resource.data.ownerId
overresource.data.ownerId
, the new write can change the oldownerId
of the document. SouserB
could take overuserA
‘s project.Additionally, note that
request.auth.uid != null
has been corrected torequest.auth != null
. The former statement will throw an exception when a user is not logged in.This then allows your rules to become:
or