Using the Web modular API (firebase js sdk 11.0.1 as well as previous version), when I call setDoc after testing existence, I get:
Missing or insufficient permissions
export async function setYouTubePublication(publication: YouTubePublication) : Promise<void> {
console.log("setYouTubePublication", publication);
const db = getFirestore();
const ref = doc(db, "youtube_publications", publication.youtubeID);
const snap = await getDoc(ref);
if (snap.exists()) {
throw new Error(`YouTube publication with ID ${publication.youtubeID} already exists`);
}
return setDoc( ref, publication );
}
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /youtube_publications/{document} {
allow read: if request.auth != null && resource.data.owner == request.auth.token.dcid;
allow create: if request.auth != null;
}
}
}
If I remove the existence test, setDoc works as it should:
export async function setYouTubePublication(publication: YouTubePublication) : Promise<void> {
console.log("setYouTubePublication", publication);
const db = getFirestore();
const ref = doc(db, "youtube_publications", publication.youtubeID);
return setDoc( ref, publication );
}
Anyone have any idea what I'm doing wrong or if there is a workaround? Seems like there is a bug.
The problem is in your read
rule:
allow read: if request.auth != null && resource.data.owner == request.auth.token.dcid;
If the document doesn't exist then the rules engine cannot determine resource.data.owner
, so it raises an error. And any error while evaluating the rules means that the operation is denied.
If you want the operation to work, explicitly check whether the resource exists:
allow read: if request.auth != null &&
(!exists(/databases/$(database)/documents/youtube_publications/$(document))
|| resource.data.owner == request.auth.token.dcid);