Firestore Wildcard Variable Does Not Work - firebase

I'm trying to test Firestore Security Rules using the code I get from Its Docs. But it doesn't work. Even the auto complete for wildcard variable is not working, the strange things is, it works with "{database}" variable.
Notice in this screenshot that variable userid is returning "{userid}", not the id of the user which is "TBfnHh13tCNHmN9aBDhYPNTPsrw1".
Here is the full code:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}
If i replace the above code with this, it can work. So it seems that the problem is the Wildcard Variable.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == "TBfnHh13tCNHmN9aBDhYPNTPsrw1";
allow create: if request.auth != null;
}
}
}
Any help would be very appreciated. Thank You!

Thanks to #Doug Stevenson I've found the solution.
Notice in screenshot below that I've write /users/{userId} in the Location field, which is wrong. I should put an id directly in the field, for example /users/P41jhUbe2SUkgtNUensmypfs3ff1 and that solved the problem.

Related

How to monitor Firestore rules errors?

I just found out that 10% of my Firestore requests go in error:
These are my rules:
service cloud.firestore {
match /databases/{database}/documents {
match /notifications/{notification} {
allow read, delete: if request.auth.uid == resource.data.authUID;
allow create, update: if request.auth.uid == request.resource.data.authUID;
}
match /various/{doc} {
allow read, write: if request.auth != null;
}
}
}
How can I monitor which are these errors?
Or can you see anything particularly wrong in the rules definitions, which can cause errors?
UPDATE:
I have modified the rules according to what #Mises said, but I still get the errors:
service cloud.firestore {
match /databases/{database}/documents {
match /notifications/{notification} {
allow read, delete, update: if request.auth != null && resource.data != null && request.auth.uid == resource.data.authUID;
allow create: if request.auth != null && request.auth.uid == request.resource.data.authUID;
}
match /various/{doc} {
allow read, write: if request.auth != null;
}
}
}
Firebase console only provides an at-a-glance view of rules invocations. Is not possible to get error logs about specific parts of your security rules that fail.
You could enable and disable rules at a time to test which one is producing errors using one of these tools:
Rules playground in the Firebase console.
Emulator suite and its debug function.

In Firestore rules how do you check the id of the requesting document?

I mean I want to check to be sure the document id of the request is the same as the document id in the database.
I tried this but it doesn't work:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.resource.id == userId;
}
}
}
Also tried this and it also didn't work:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.resource.id == resource.id;
}
}
}
I've searched online for hours and every single post is about using authentication uid.
if you want to make sure the uid in request matches name of the user document, then use this:
match /users/{userId} {
allow read, update, delete: if request.auth != null && request.auth.uid == userId;
}
and if you want to allow new users to be created add this too:
allow create: if request.auth != null;
more details : https://firebase.google.com/docs/firestore/security/rules-conditions

Firebase security rules - can't get resources with get()

I'm trying to write a rule in firebase security console with get() but I can't get resource data anyhow... I want documents and their subcollections to be readable to user, if user uid is in document field, array or map.
My collection structure:
/boards/(boardId)/...much more
Fields in (boardId) document:
name: "Board name"
ownerId: "MYID12345"
guestsId(array): ["MYID12345"]
guestsMap(map): [MYID12345: true]
Security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /boards/{boardId=**} {
// rules here
}
}
}
What I have tried so far:
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).data.guestsMap[request.auth.uid] == true;
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsMap;
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsMap[true];
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).request.data.guestsId[request.auth.uid];
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsId;
allow read: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).request.data.guestsId;
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId == request.auth.uid;
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId == "MYID12345";
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).resource.data.ownerId == request.auth.uid;
allow read: if get(/databases/$(database)/documents/boards/$(boardId)).request.data.ownerId == request.auth.uid;
None of these worked, always getting:
ERROR FirebaseError: Missing or insufficient permissions.
allow read: if true, makes the application run normally.
I'm sticking to the documentation but it's not working for me...
#update
match /boards/{boardId=**} {
allow read: if resource.data.ownerId == request.auth.uid;
}
Also can't use it like this, because then, every subcollection is looking for ownerId field in it's documents, and ownerId or friend list array are only in board document.
#update
I tried to do like so, but it didn't help:
match /boards/{boardId} {
allow read, write: if request.auth.uid in resource.data.guestsId || request.auth.uid == resource.data.ownerId;
allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid));
function passResource() {
return request.auth.uid in resource.data.guestsId || request.auth.uid == resource.data.ownerId;
}
match /categoryList/{categoryId} {
allow read, write: if passResource();
}
...
}
What am I missing here?
Okay I found a working solution:
match /databases/{database}/documents {
match /boards/{boardId} {
allow read: if request.auth.uid in resource.data.guestsId || request.auth.uid == resource.data.ownerId;
allow write: if request.auth.uid == resource.data.ownerId;
allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid));
function isAllowed() {
return request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsId || request.auth.uid == get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId;
}
match /categoryList/{category} {
allow read, write: if isAllowed();
match /taskList/{task} {
allow read, write: if isAllowed();
}
}
...
}
Also funny it didn't want to work like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /boards/{boardId=**} {
allow read, write: if request.auth.uid in get(/databases/$(database)/documents/boards/$(boardId)).data.guestsId || request.auth.uid == get(/databases/$(database)/documents/boards/$(boardId)).data.ownerId;
allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid));
}
}
because:
Error: simulator.rules line [5], column [49]. Property guestsId is undefined on object.

How to set Firestore security rules? resource.data: Null value error

I need some help making my security rules for firestore work.
These are my firestore rules:
service cloud.firestore {
match /databases/{database}/documents {
match /orders/{orderID} {
allow read, update: if request.auth.uid == resource.data.buyerId || request.auth.uid == resource.data.sellerId;
}
}
}
my orders collection:
orders: {
sellerId: 'some-id',
createdAt: timestamp,
buyerId: 'some-id'
}
It should return all documents from orders collection which has either buyerId or sellerId equal to authorised user (request.auth.uid).
but the above rule is not working as expected.
firestore collections screenshot
firebase simulator output
That error message is suggesting that the requested document was not actually present in the database. You entered "orders/{orderId}", which looks like you put a wildcard in the Location field in the simulator. That's not going to work. You need to enter the path to an actual document that exists if you want to test your rule that uses its field values.
resource.data: Null - this error happens when you try to create a new entity.
Split write rule, on create and update.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /user/{userId} {
allow read: if request.auth.uid == userId;
function authed() {
return request.auth.uid == userId;
}
allow create: if authed() && request.resource.data.keys().hasOnly(['name']);
allow update: if authed() && request.resource.data.diff(resource.data).changedKeys().hasOnly(['name']);
allow delete: if authed();
}
}
}

Firebase security rules syntax with arrays/list property

Within a Firebase Firestore collection with path 'organizations' each document contains a list of string userID's of users who can update or delete that document.
export interface Organization{
name?: string,
owners: string[]
}
I would like to create a Firebase security rule that ensures that only a logged in user with a uid that is in this list can edit or delete the object. Unsure of the appropriate syntax.
service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{organization} {
allow read: if true;
allow create: if request.auth != null;
/// What should be the syntax here?
allow update, delete: if request.auth != null && (request.auth.uid in resource.data.owners); // <--------- What should be the syntax for this line?
}
Ok, answering my own question here in case it's useful for anyone else.
It looks like the 'in' syntax above actually works even-though it was a complete guess and I wasn't able to find any documentation for it in the firebase security roles documentation.
Final code:
service cloud.firestore {
match /databases/{database}/documents {
match /organizations/{organization} {
allow read: if true;
allow create: if request.auth != null;
allow update, delete: if (request.auth != null) && (request.auth.uid in resource.data.owners);
}

Resources