Access userId without having it as a field - firebase

I'm writing Firestore security rules for my project. I want to allow users to edit information in their own user page, but not in anyone else's. Right now I don't save userId as a field in each user, only as the reference to the user document. I know how to access fields in each user, but not the reference to them. See picture:
match /Users/{document} {
allow update: if request.auth.uid == userId; //how do I reach the userId without having it as a field
}
I do not want to add userId as a field in each user, there must be an easy way of accessing the path.

As mentioned in the Firestore docs you get the document id from the match query.
In your case this would be document from match /Users/{document}. You could also rename this query to match /Users/{userId} to make it work.

Check the second example in the documentation on using authentication information in security rules:
Another common pattern is to make sure users can only read and write their own data:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
allow read, update, delete: if request.auth.uid == userId;
allow create: if request.auth.uid != null;
}
}
}
So in your case that'd be if request.auth.uid == document.

Related

What rules should I set in my firestore rules to only let the users with that userID view the book with the same userID?

I want the user to only see books with the same userID as its own userID. What do I set rules to? For reference here is my current rules but it allows access to everyoes books once logged in.
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /booklist/{documents=**} {
allow read, write: if request.auth != null
}
}
}
I want to add the request.auth.uid == userID feature but it is not working when I try to add it.
For reference, here is my collection 'booklist' where you can see the userID field indicated.
Your rules for that would be:
allow read: if request.auth != null && request.auth.uid == resource.data.userID
Combined with this query in your code (because rules are not filters on their own):
db.collection("booklist").where("userID", "==", user.uid).get()
I highly recommend reading the documentation on content-owner only access and securely querying data, specifically securing and querying documents based on a field

Firebase Security Rule with attribute in database

I need security rules for my firebase-app.
My Data looks like this
{
owner = "djskjfskdjf",
data = "some data"
}
Collection Path is /Data/
I want that users that are authenticated users can read and create documents in this collection. To edit or delete documents, I want that the uid in the field owner is the same as the request.auth.id.
According to firebase documentation this should work:
service cloud.firestore {
match /databases/{database}/documents {
match /Data/{document=**} {
allow read, create: if request.auth.uid != null;
allow delete, write: if request.auth.uid == request.resource.data.owner;
}
}
}
But when I try to update a field in simulation it gives me the error:
Error: simulator.rules line [5], column [51]. Property resource is undefined on object.
I hope you can help me with this problem.
If your request isn't sending the all the required fields you're checking in rules, then request.resource.data.owner wont work (like if you are just sending data but not owner with the request).
You should use the below style to match an existing object in the database. It won't matter if the request omits the owner info.
allow delete: if resource.data.owner == request.auth.uid;

Firestore write security rule for specific user using auth names

New to Firestore security rules and is trying to understand it. I'm trying to write a security rule that allow only admins in my collection to write data and every one to read it.
The collection of admins has document ids as admin names, that is for example, "Mary Lane". Within the documents I've fields:
email: "userMailId#mail.com"
uId: "firestore_user_Id"
The uId is the id of Firestore user id. The data to write is an object Message and is:
new Message(uId, title, messageBody, timestamp)
Currently I'm trying to match the request.auth.uid with the id of the admins that are stored within the collection:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read;
allow write: if request.auth.uid == resource.data.uId;
}
}
}
Is this is write or am I doing something wrong. Any help is appreciated.
Since the admin's name is not available in this rule allow write: if request.auth.uid == resource.data.uId;, there is no way to look up the document to check it they're an admin.
You'll need a collection where you keep a document for each admin with their UID as the document key/name. Once you have that, you can check for the existence of such a document in the rule with:
allow write: if exists(/databases/$(database)/documents/admins/$(request.auth.uid));
Also see the documentation on accessing other documents.

firebase - setting specific fields as private

I want to set up certain fields to be private on my user profiles. I have a user documents with name, email, etc but I want to make the gold field read only as I plan to use a cloud function to update this value when a user makes an in app purchase. I've not done in app purchases before so this is the only way I can think of doing it.
I understand I can use wildcard vars in the path when using Firestore security rules, however as far as I'm aware, I can only use wildcard vars in place of the documents and collections.
You are correct that wildards can only be used to identify collections and documents, but not fields. However one option you could have is to create an additional 'private collection' which you could secure with the standard security rules. For example -
users
user1
email
name
gold
user1
goldValue
Then in your security could look something like -
service cloud.firestore {
match /databases/{database}/documents {
match /gold/{userId} {
allow read, update, delete: if request.auth.uid == userId
allow create: if request.auth.uid != null;
}
match /users/{document=**} {
allow read;
allow write: if request.auth.uid != null;
}
}
}

Configuring rules for Firestore so user only gets records they own

This is a followup to this question
Firestore permissions
I'm trying to set rules on my firestore
service cloud.firestore {
match /databases/{database}/documents {
match /analysis/{analysis} {
allow read, write: if request.auth.uid == resource.data.owner_uid;
}
}
}
My goal is
a. When doing a list operation only those documents belonging to a user are returned
b. only documents a user owns can be read or written by that user.
With the above configuration b. is accomplished.
how do I do accomplish a. ?
Remember that firestore rules are not filters, they're a server-side validation of your queries.
You should always make your queries match your rules, or else you'll get permission errors.
In your case you already made the rule to enforce reading/listing on user owned documents. Now you simply have to make the corresponding query with the right filters :
const userId = firebase.auth().currentUser.uid
db.collection("analysis").where("owner_uid", "==", userId)
Another thing.
With your current rules, your users won't be able to create a new document, only edit an existing one, here are the updated rules to allow that :
allow read: if request.auth.uid == resource.data.owner_uid;
allow write: if request.auth.uid == resource.data.owner_uid
|| request.auth.uid == request.resource.data.owner_uid;

Resources