firebase functions deployment error: Insufficient permissions to (re)configure a trigger - firebase

When I deploy storage trigger functions I get the following error msg and the deployment fails:
Deployment error.
Insufficient permissions to (re)configure a trigger (permission denied for bucket Bucket-Name. Please, give owner permissions to the editor role of the bucket and try again.
Firestore trigger functions can be deployed. I already tried to fix the ACLs using the commands suggested here and here.
Any ideas how to fix that?
Edit: I set up a new project, facing the same error.
My /functions/index.js:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<project-name>.firebaseio.com"
});
const storage = admin.storage();
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Im deployed successfully");
});
exports.storageTrigger = functions.storage
.object()
.onChange(event => console.log('I fail to deploy'));

Related

Firebase CLI: execute arbitrary Firebase Authentication requests to Firebase Emulator

Using the Firebase CLI, I'm executing arbitrary JavaScript that's stored in a file. In that script, I'm trying to make calls to admin.auth().something(), but it doesn't work against the Firebase Emulator. This is in contrast to making calls to Firestore, which works perfectly fine with the Emulator.
Firestore (everything works)
GCP
This makes calls to Firestore on GCP and it succeeds:
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'my-project' });
const db = admin.firestore();
(async () => {
const widget = await db.doc('/widgets/123456789').get();
console.log(widget.data().name);
})();
Emulator
This also succeeds:
const admin = require('#firebase/testing');
const db = admin
.initializeAdminApp({ projectId: 'my-project' })
.firestore();
(async () => {
const widget = await db.doc('/widgets/123456789').get();
console.log(widget.data().name);
})();
Firebase Auth (GCP works but Emulator does not)
GCP
This makes calls to Firebase Auth on GCP and it succeeds:
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'my-project' });
(async () => {
const user = await admin
.auth()
.getUser('user123456789');
console.log(user.email);
})();
Emulator
This fails:
const admin = require('#firebase/testing');
const auth = admin
.initializeAdminApp({ projectId: 'my-project' })
.auth();
(async () => {
const user = await auth.getUser('user123456789');
console.log(user.email);
})();
The error message is:
C:\Users\...\node_modules\#firebase\testing\node_modules\#firebase\component\dist\index.cjs.js:134
throw e;
^
[t [Error]: Your API key is invalid, please check you have copied it correctly.] {
code: 'auth/invalid-api-key',
a: null
}
I'm not sure what API key they're referring to, as the request is against the Emulator. How can I execute Firebase Auth requests against the Emulator using Firebase CLI?
To send requests against Firebase Emulator Auth, set the following environment variables and use the standard Firebase Admin SDK (firebase-admin) instead of using #firebase/testing:
process.env.FIREBASE_AUTH_EMULATOR_HOST = 'localhost:9099';
process.env.FIRESTORE_EMULATOR_HOST = 'localhost:8080';
const admin = require('firebase-admin');
admin.initializeApp({ projectId: 'emulator projectId' });
Now this works:
(async () => {
const user = await auth.getUser('user123456789');
console.log(user.email);
})();

Unable to send or retrive data in the Firebase Web

I am facing a problem in sending or retrieving the data from the Firebase web.
Although I can successfully register the user and I can even get the user UID by writing the code shown below-
if(user!=null)
{
var uid = firebase.auth().currentUser.uid;
console.log(`UID ===> ${uid}`)
}
But still I cannot retrieve/send data from/to the Firebase. I am not even getting any error in the console.
My codes for index.js file in the functions folder is below-
const functions = require('firebase-functions');
const express = require('express');
var admin = require('firebase-admin');
var serviceAccount = require('/path/to/my/serviceAccount/key.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://urlOfMyDatabaseURL.firebaseio.com'
});
const app = express();
app.get('/', (request, response)=>{
response.send(index.html);
});
exports.app=functions.https.onRequest(app);
Please help, I am stuck here!

File upload with filestreams and Firebase cloud functions + cloud storage

I've written the following code for my QR file upload using firebase cloud functions
const functions = require('firebase-functions');
const qrcode = require('qrcode')
const admin = require('firebase-admin');
const spawn = require('child-process-promise').spawn;
const serviceAccount = require("./secret.json");
const gcs = require('#google-cloud/storage')();
admin.initializeApp(functions.config({
credential: admin.credential.cert(serviceAccount),
storageBucket: "https://SECRET.firebaseio.com"
}));
exports.qrcode = functions.https.onRequest((req, res) => {
const storage = admin.storage().bucket();
const dummyFile = storage.file('dummy.png')
new Promise ((resolve, reject) => qrcode.toFileStream(
dummyFile.createWriteStream()
.on('finish', resolve)
.on('error', reject),
'DummyQR'))
.then(console.log("success")) //Doing stuff here later
.catch(console.log)
res.send("<script>window.close();</script>")
});
According to the docs I should be able to connect to the bucket by simply calling admin.storage().bucket(); (https://firebase.google.com/docs/storage/admin/start) however I get the following error:
Error: Error occurred while parsing your function triggers.
Error: Bucket name not specified or invalid. Specify a valid bucket name via the storageBucket option when initializing the app, or specify the bucket name explicitly when calling the getBucket() method.
and so I'm stuck and not sure how to proceed. If I try to manually enter the bucket admin.storage().bucket("https://SECRET.firebaseio.com"); I get the error
{ ApiError: Not Found
at Object.parseHttpRespBody (/user_code/node_modules/firebase-admin/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:193:30)
at Object.handleResp (/user_code/node_modules/firebase-admin/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:131:18)
at /user_code/node_modules/firebase-admin/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:496:12
at Request.onResponse [as _callback] (/user_code/node_modules/firebase-admin/node_modules/retry-request/index.js:195:7)
at Request.self.callback (/user_code/node_modules/firebase-admin/node_modules/request/request.js:185:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/firebase-admin/node_modules/request/request.js:1157:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
code: 404,
errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ],
response: undefined,
message: 'Not Found' }
I had this same problem. I just added the storageBucket name when initializing the app, and if you are using the getSignedUrl method you need to include a service account, otherwise that url it's gonna get expired after a week (as it was in my case).
const serviceAccount = require('/your/service/account/key/path');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
storageBucket: "your-storage-bucket-name.appspot.com",
});
don't forget to update your firebase functions with
firebase deploy --only functions
on the command line
UPDATE 6 APRIL 2020
Signed URLs actually expire after 7 days. If you need URLs for more time than that, you should read this answer and this thread
It looks like you're not initializing the admin SDK correctly. Just call initializeApp with no parameters to get all the correct defaults:
admin.initializeApp();
This will use the default service account provided by Cloud Functions for your project. This account has permission to do most of what you need to do in your function without any additional configuration.
In my case it was similar issue to this one (Unable to use cloud storage without specifying storageBucket when initialising app with firebase-admin).
I had following setup:
const admin = require("firebase-admin")
admin.initializeApp()
export * from "./api/api"
export * from "./cron/cronJobs"
export * from "./posts/postsCloudFunctions"
Changed it to:
const admin = require("firebase-admin")
export * from "./api/api"
export * from "./cron/cronJobs"
export * from "./posts/postsCloudFunctions"
admin.initializeApp()
And it seems the issue is initializeApp() was not being called before accessing the storage bucket.
I have same issue while uploading to image to firebase storage:
Error: Bucket name not specified or invalid. Specify a valid bucket name via the storageBucket option when initializing the app, or specify the bucket name explicitly when calling the getBucket() method.
ndlers\users.js:130:8)
at Busboy.emit (events.js:189:13)
at Busboy.emit (E:\react-project\socialape-functions\functions\node_modules\busboy\lib\main.js:37:33)
at E:\react-project\socialape-functions\functions\node_modules\busboy\lib\types\multipart.js:52:13
at process._tickCallback (internal/process/next_tick.js:61:11)
Then i add storageBucket to admin function
var admin = require("firebase-admin");
var serviceAccount = require("your service account key file path);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://your-app-1234.firebaseio.com",
storageBucket: "your-storage-bucket-name given in firebase storage"
});
const db = admin.firestore();
module.exports = { admin, db };
After adding bucket to admin functions it works.
You should change
storageBucket: "your-storage-bucket-name given in firebase storage"
to
storageBucket: "<BUCKET_NAME>.appspot.com".
You can find BUCKET_NAME as the picture below:

Firebase Functions 1.0.0 migration: Trouble with custom initializeApp() with Google Service Account credential

I just updated from the beta (v0.9.1) to v1.0.0, and ran into some problems with initialization. As per the migration guide, functions.config().firebase is now deprecated. Here is my initialization before:
const serviceAccount = require('../service-account.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: functions.config().firebase.databaseURL,
storageBucket: functions.config().firebase.storageBucket,
projectId: functions.config().firebase.projectId,
})
Here is what I changed it to after upgrading:
admin.initializeApp()
At first this seems to work fine, the databaseURL and storageBucket are being recognized. However, there is a problem regarding the newly absent credential field. That field is required in order to access Google Cloud Storage. I access the #google-cloud/storage API in my app like so:
import { Bucket, File } from '#google-cloud/storage'
import * as admin from 'firebase-admin'
bucket: Bucket = admin.storage().bucket()
this.bucket
.upload(filepath, {
destination: uploadPath,
})
.then((fileTuple: [File]) => {
// after uploading, save a reference to the audio file in the DB
fileTuple[0]
.getSignedUrl({ action: 'read', expires: '03-17-2025' })
.then((url: [string]) => {
dbRef.child('audioFiles').push(url[0])
})
.catch(err => console.log('Error:', err))
console.log(`${filepath} uploaded to ${this.bucket.name}.`)
})
This uploads a file to storage, then it inserts the signed URL into my Realtime Database.
After migration, this chunk of code gives the following error:
SigningError: Cannot sign data without `client_email`
Since client_email was a field on service-account.json, I suspect that I need to reinsert credentials, like so:
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
})
When I try this, however, I get errors like Error: Can't determine Firebase Database URL. or Error: Bucket name not specified or invalid.. So if I manually insert credential, it appears to expect databaseURL and storageBucket to be manually inserted as well.
So the question is, how do I do this?
Figured it out myself. I had to rewrite my init call like this:
const serviceAccount = require('../service-account.json')
const firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG)
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: firebaseConfig.databaseURL,
storageBucket: firebaseConfig.storageBucket,
projectId: firebaseConfig.projectId,
})

Firebase: Update Firestore Fails If Document Does Not Exist [duplicate]

This is my very basic Cloud Function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore()
exports.createdNewAccount = functions.auth.user().onCreate(event => {
return db.collection('users').doc(event.data.uid).update({
"creationDate" : Date.now()
})
})
And I get the error
Error: no entity to update: app
What is wrong with my code?
Most likely, the document for event.data.uid does not exist. The documentation for update() states:
The update will fail if applied to a document that does not exist.
Use set() instead.
I faced a similar error when testing my app locally with the Firebase emulator. My firebase config file looked like:
import firebase from "firebase";
import "firebase/firestore";
const firebaseConfig = {
apiKey: <FIREBASE_API_KEY>,
authDomain: <FIREBASE_AUTH_DOMAIN>,
databaseURL: <FIREBASE_DB_URL>,
projectId: <FIREBASE_PROJECT_ID>,
storageBucket: <FIREBASE_STORAGE_BUCKET>,
messagingSenderId: <FIREBASE_MSG_SENDER_ID>,
appId: <FIREBASE_APP_ID>,
measurementId: <FIREBASE_MEASUREMENT_ID>,
};
// Initialize Firebase
const firebaseApp = firebase.initializeApp(firebaseConfig);
// for local instances, use the emulator to connect the frontend to firestore & functions
if (location.hostname === "localhost") {
firebase.firestore().settings({
host: "localhost:8080",
ssl: false,
});
firebase.functions().useFunctionsEmulator("http://localhost:5001");
}
Turns out my local Firestore database (expected to be running at localhost:8080) wasn't being hit. So my cloud functions were trying to write to a non-existent db. The underlying issue was that I also had my backend initializing to a different database:
// functions/index.js
const admin = require("firebase-admin");
var serviceAccount = require("./serviceAccount.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://other-firebase-project-id.firebaseio.com",
});
The solution (originally adapted from a Fireship tutorial) was to remove this [incorrect] re-initialization of the database altogether:
// functions/index.js
...
admin.initializeApp();
...
After all, according to the docs, we can initialize the Firebase Admin SDK without parameters since the FIREBASE_CONFIG environment variable is included automatically in Cloud Functions for Firebase functions that are deployed via the Firebase CLI.
FWIW, also be sure to set the correct Firebase project on the CLI. Doing so with this allows the Firebase CLI to hook Functions/Firestore to the right project:
firebase use <desired-firebase-project-id>
If you have multiple Firebase projects, you can list them out with: firebase projects:list

Resources