Reputation: 181
I want to give write/update access to only one field from my firestore database collection without requesting the auth service. My rules for firestore is:
service cloud.firestore {
match /databases/{database}/documents {
match /businesses/{businessId} {
allow read;
allow write: if request.auth.uid != null;
}
}
}
My database structure for businesses
is:
addedBy: string;
address: string;
category: string;
claim: boolean;
city: string;
email: string;
id: string;
likes: number;
location: {
_lat: number,
_long: number
};
name: string;
ocHours: [{
day: string,
from: string,
status: string,
to: string
}];
phone: number;
sponsored: boolean;
state: string;
status: string;
verificationCode: string;
I want to update only the claim
field without request.auth.uid != null
.
Any suggestions?
Upvotes: 3
Views: 2058
Reputation: 2587
I don't know if this thread is still valid, but searching for a solution I stumbled upon the rules.MapDiff
spec, that does exactly what you are looking for:
// Compare two Map objects and return whether the key "a" has been
// affected; that is, key "a" was added or removed, or its value was updated.
request.resource.data.diff(resource.data).affectedKeys().hasOnly(["a"]);
See here for details https://firebase.google.com/docs/reference/rules/rules.MapDiff
Upvotes: 6
Reputation: 191
As explained in this blog post, request.resource.data
does not contain only the updated fields, but the entire future state if the write would be successful.
So you could simply check if the field in the resource differs from the one in the request and, as the author neatly suggests, create a function like this:
function notUpdating(field) {
return !(field in request.resource.data) || resource.data[field] == request.resource.data[field]
}
In your case, you would probably want to break your write
into create
,update
,delete
and the update
could look something like this:
allow update: if
notUpdating(addedBy)
&& notUpdating(address)
&& notUpdating(category)
// ... put all fields here except 'claim'
&& notUpdating(status)
&& notUpdating(verificationCode) ;
Upvotes: 1
Reputation: 91
rights assignments in firestore Rules as Ron says can only be applied to a whole document. Nevertheless there is a way of allowing to write/update/delete/create a specific file and that is by ensuring that the incoming change object has only the field you want to grant rights. And you do that by:
request.resource.data.keys()
hasOnly(["claim"])
service cloud.firestore {
match /databases/{database}/documents {
match /businesses/{businessId} {
allow read;
allow write: if request.resource.data.keys().hasOnly(["claim"]);
}
}
}
Hope it helps although the question was posted a while a go!!
Upvotes: 9
Reputation: 635
I have written the following function to be used to allow only one field to be editable:
function onlyField(field) {
return request.resource.data.keys().hasOnly([field]);
}
This function can be used as follow:
match /someObject/{document=**} {
allow update: if onlyField('someFieldOfYOurObject');
}
Upvotes: 0
Reputation: 18555
Authorization is applied to the entire document. You can create a "claims" collection of documents identified by business-uid's and set it to write
only so it is impossible for public to read the list but they can update the claim
property. These documents could be boolean like
home/claimsCollection
bizABC123
claim:true
bizXYZ123
claim:false
Upvotes: 0