I'm trying to use a Firebase Cloud Function to update a document within my Firestore database, when one of my documents has been updated using a trigger. The trigger is called and working fine, but when I'm using the firebase admin instance to get the other document which I want to update, I'm getting the following error.
Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
at Object.exports.createStatusError (/user_code/node_modules/firebase-admin/node_modules/grpc/src/common.js:87:15)
at ClientReadableStream._emitStatusIfDone (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client.js:235:26)
at ClientReadableStream._receiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client.js:213:8)
at Object.onReceiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:1256:15)
at InterceptingListener._callNext (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:564:42)
at InterceptingListener.onReceiveStatus (/user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:614:8)
at /user_code/node_modules/firebase-admin/node_modules/grpc/src/client_interceptors.js:1019:24
function code:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
const settings = { timestampsInSnapshots: true };
admin.firestore().settings(settings);
export const onDocUpdate = functions.firestore
.document("documents/{documentId}")
.onUpdate((snapshot, context) => {
console.log("onDocUpdate called ", context.params.documentId);
const document = snapshot.after.data();
console.log("Document: ", document);
if (document.screw) {
console.log("Document screw exists. ", document.screw);
const docRef = admin
.firestore()
.collection("screws")
.doc(document.screw);
return docRef
.get()
.then(doc => {
if (doc.exists) {
console.log("Screw for document exists.");
} else {
console.error(
"Screw for document not found! ",
document.screw
);
}
})
.catch(error => {
// Here I get the permission error :(
console.error(
"Screw for document doc load error!! ",
error
);
});
} else {
console.error("Document is not bound to a screw! ", document.id);
}
return null;
});
package.json
{
"name": "functions",
"scripts": {
"lint": "tslint --project tsconfig.json",
"build": "tsc",
"serve": "npm run build && firebase serve --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"main": "lib/index.js",
"dependencies": {
"@google-cloud/firestore": "^0.16.0",
"firebase-admin": "^6.0.0",
"firebase-functions": "^2.0.4",
"protobufjs": "^6.8.8"
},
"devDependencies": {
"tslint": "~5.8.0",
"typescript": "~2.8.3"
},
"private": true
}
I assume that it has something to do with the permission of the admin instance, but no idea what the error could be, I've just followed the steps from the docs and the firebase videos on youtube.
My account is still on a Free Plan and I'm getting a notice in the logs the that I should configure the billing account, but if understand the documentation correct I should be able to access services within the Google Cloud Platform and so reading other nodes within the same database should not be a problem.
I've already found two similar issues here on stackoverflow, but did not find a solution there. Maybe someone else also faced this issue in the meantime and was able to solve it?
PERMISSION_DENIED Firestore CloudFunction TypeScript and Firebase error writing to Firestore via a Function: "7 PERMISSION_DENIED: Missing or insufficient permissions"
Update 1: Had another issue with the new timestampsInSnapshots setting. This has been fixed and the code above updated. The main issue permission denied is still present.
Update 2: Regarding the answer by @RonRoyston below. This is a Cloud Function and its using the Admin SDK from firebase-admin package to read the node. Hence it should not be effected by the firestore security rules. There's already a comment on one of the linked questions by @DougStevenson mentioning this. Based on the Admin SDK documentation it should be enough to initialize it by calling admin.initializeApp(), but unfortunately in my case it isn't. I've read no where that there is any need to apply any special IAM settings within the service accounts or security rules when using Cloud Functions, and so I didn't touch any of these settings.
Cheers, Lars
firestore.rules
file. – Ronnie Royston