What I am trying to achieve is very simple. I need to create a user entry in the database only if it doesn't exist.
The app flow:
- Create a user with Firebase Auth (obtain UID)
- Create a user document in the database using UID as the key
The client code (create operation):
this.db.doc('users/' + uid).set({username: Santa})
The firestore rules:
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid} {
allow create: if
request.auth != null &&
request.auth.uid == uid &&
!exists(/databases/$(database)/documents/users/$(uid));
allow update: if request.auth != null && request.auth.uid == uid;
}
}
}
Additional info:
As you may already know the code doesn't work. Everytime I run the client-side code the current user is completely replaced with a new document. However, if I delete the following line from the rules everything works as expected:
allow update: if request.auth != null && request.auth.uid == uid;
But now the question arises, how do I secure data inside user document from unauthorised modifications? Any advice?
this.db.doc('users/' + uid).set({username: Santa}, {merge: true}) It should merge and not replace. Fields omitted will remain untouched. https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference#set
If you want to allow creating a document only if it doesn't already exist, just use the
allow create
rule that you already have. Because you also have anallow update
rule, updating the existing data is also allowed.The following rules should be sufficient:
You don't need the
exists()
call, becauseallow create
only applies if the data does not exist.Now to your question: You should clarify what you mean exactly. Now only the authenticated user can modify its own record. If you don't want to allow arbitrary data to be written, check for it.
Here are some examples: https://firebase.google.com/docs/firestore/security/rules-conditions#authentication
Use logic in your code, but not in rules. Add addOnCompleteListener to user collection and after get the result do some actions.
}
Rules: