This question already has answers here:
How to allow only particular fields of a firestore document to be accessed publicly
(2 answers)
Can I restrict certain fields in firestore database to be only fetched by firebase admin?
(2 answers)
Closed 2 years ago.
I am trying to implement security rule to limit users to access only specific fields inside a document. My data structure goes like this:
document {
name: John,
dob: 1994,
email: john#hotmail.com
}
I want to limit the name field to read, write by owner; dob field to read by owner, create by owner; email to read by owner, update by owner
I read the documentation, and it seems that I can only control access of a specific document with security rules. It didn't mention anything to allow access to a specific field. What I should do in order to allow access to specific fields inside a document?
Security rules can't be used to limit access to individual fields in a document. If a user has direct read access to a document, they can always read every field in the document.
Your only alternatives here are:
Split the restricted fields into a document in another collection, and protect that collection differently.
Reject direct access to the collection entirely, and force users through an API endpoint that strips out the restricted fields based on the user's identity, which was passed to the endpoint.
Related
I'm trying to secure requests to a collection to allow any single get, but to allow list only if a specific key is matched.
Database structure is like this:
posts
post1
content: "Post 1 content"
uid: "uid1"
post2
content: "Post 2 content"
uid: "uid1"
post3
content: "Post 3 content"
uid: "uid2"
The Firestore query I'm making from Vue:
// Only return posts matching the requested uid
db
.collection("posts")
.where("uid", "==", this.uid)
The security rules I'd like to have would be something like this:
match /posts/{post} {
allow get: if true // this works
allow list: if [** the uid in the query **] != null
I want to do this so you can list the posts of a specific user if you know their uid but can't list all posts of the system.
Is there a way to access the requested .where() in the security rules or how can I write such rule or structure my data in this case?
Relevant & credits:
Seemingly, I can make a request on a query's limit, offset, and orderBy. But there's nothing on where. See: #1 & #2.
I copy-pasted much from this question. I don't see how the accepted answer answers the question. It seems like it answers another case where a user is allowed to list some other users' posts. That is not my case; in my case, what's public is public. So, it doesn't answer the main question in my case, it seems.
There's currently no way, using security rules, to check if a field is being used in query. The only thing you can do is verify that a document field is being used as a filter using only values you allow.
Instead, consider duplicating enough data into another collection organized like this:
user-posts (collection)
{uid} (document using UID as document ID)
posts (subcollection)
{postId} (documents using post ID as document ID)
This will require the client to call out a UID to query in order to get all the posts associated with that user. You can store as much information about the post documents as you like, for the purpose of satisfying the query.
Duplicating data like this is common in NoSQL databases. You might even want to make this your new default structure if you don't want your users to query across all posts at any given moment. Note that a collection group query naming the "posts" subcollection would still query across all posts for all users, so you'd have to make sure your security rules are set up so that this is enabled only when you allow it to happen.
Also note that UIDs are typically not hidden from users, especially if your web site is collaborative in nature, and you combine multiple users' data on a single page.
I am developing an application that needs to search all nearby users WITHOUT sharing their coordinates within 100 miles let's say. The example below I am using GeoHash to help me in calculating the distance.
In FireStore, I have the following document inside collection of users.
{
"userId" : "12345",
"displayName" : "username",
"geoHash" : "gbsuv",
"photoUrl" : "example.com/user.jpg",
"refId" : "0001"
}
The question is: How should I protect the "geoHash" from being retrieved within each document inside the collection?
Firestore security rules grant access on a document level. So either the user can read an entire document, or they can't read anything in that document. There's no way to grant users access to only part of a document.
This means that you can't query something that the client can't read. So in your current structure, if the user needs to query on geoHash, they will be able to read that field too.
The only alternative is to not let the client do the querying, but instead do that querying on a server (such as in Cloud Functions). For this you'd store the geohash for each user in a separate document (say in a collection called locations). The Cloud Function then queries this collection, and returns the real user document(s) (which doesn't contain the geohash anymore) to the user.
This question already has answers here:
Firestore Security Rules - How can I check that a field is/isn't being modified?
(10 answers)
Closed 3 years ago.
I am looking to apply firestore rules to restrict the change (write, update) of a specific field in a document.
From what I understand in the docs you cannot apply rules on read: to document fields as documents need to be read in their entirety, however, it's not stated about writes, updates?
My structure is like the below example;
match /ads/{adDocument} {
//adDocument has a field "price" this needs to only be read not changed/updated.
};
How would I go about implementing this?
You can write a CQRS mediator for all changes, and disallow all write to the documents.
To make a change, the client can add a document to mutate the document on all mutable fields:
/PATCH_ads/{adDocument}:
- itemName: "newItemName"
The mediator should be triggered once a document is added in the PATCH_ads collection. The mediator should reject the change if receiving a command to modify price field, and commit the change if the content of the requested change is valid.
This question already has answers here:
Cloud Firestore: Enforcing Unique User Names
(8 answers)
Closed 3 years ago.
I am currently trying to verify before a user creates data in the database if the data exists. Even unter an other Document id.
Like this: User creates data, firestore rules gets all documents in collection and checks if the property name is the same as from the user provided. If yes, return unauthorized access.
At this point I have:
function checkIfCatExists(){
return get(/databases/$(database)/documents/category/$(documents)).data.name != null;
}
But this does not work. Do you guys have an idea? I could create a function for that but I want to do as much as possible with rules.
There is no way to search a collection for a specific value in security rules, as that operation wouldn't scale.
If you want to ensure unique user names, you'll have to create a collection where you use the user names as the key. You can then use the exists function in your security rules, to check if the name already exists in the collection.
Also see:
Cloud Firestore: Enforcing Unique User Names
Firestore security rule to check if character username already exists
Firestore security rules - can I query for a document with specific fields?
I want to write a rule that will don't allow add same document second time
I have a chat app where users can send photos in private or group chats. Each private or group chat has a unique chat id: /images/<chat id>/image.jpg
How would one secure the access to this files so that only the chat members can view them? In the Firebase database I have a node with a structure like: /members/<chat id>/member1: true.
Is this actually necessary, since the links are only posted to the corressponding chats?
Can any authed user actually browse through the files saved in the Firebase storage? Or is this prevented by design?
The eternal question. It's discussed a few places (Google Group, Storage Docs, Github Gist), but the TL;DR is: at present, there's no way to read data from one service in the Rules of another. For services, you can do one of two things:
Convey group information in a custom token
Convey group information in custom metadata in the service
One example of this:
// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
allow read: if resource.metadata.owner == request.auth.token.groupId;
allow write: if request.auth.token.groupId == groupId;
}