Unsupported Firebase Functions services? - firebase

I'm attempting to deploy a minimal Firebase Function based on an authentication trigger. I've worked successfully before with https and database triggers but I'm getting an error while deploying an authentication trigger (docs, reference).
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
exports.onCreateUser = functions
.region('europe-west1')
.auth.user()
.onCreate((user: admin.auth.UserRecord, context: functions.EventContext) => {
console.log(`Triggered On Create User: ${user.email}, ${user.uid}.`);
});
I receive the following error:
Ignoring trigger "onCreateUser" because the service "firebaseauth.googleapis.com" is not yet supported.
I've tried changing my engine node version from 10 to 8 or changing the region to europe-west2 or us-central1 but any variations on my configuration would throw this error.
The documentation I've referenced does not mention a limited support for these triggers. Is there any page with an overview of unsupported services and their limitations?

I seem to have mixed up my intent to run serve and deploy here. As I have been told by a very responsive support team the serve script spins up the emulator and is currently limited to the following scopes:
Functions
Firestore
Realtime Database
Hosting
For the development phase, however, you can make use of the interactive shell:
$ firebase functions:shell
✔  functions: Emulator started at http://localhost:5001
i  functions: Loaded functions: onCreateUser
firebase > onCreateUser({"uid":"99999","email":"test#testing.com"})
'Successfully invoked function.'
>  Triggered On Create User: test#testing.com, 99999.
>  Function returned undefined, expected Promise or value

Related

firebase scheduled cloud function not being called [duplicate]

I am working on cloud functions especially schedule functions. I need to trigger a function periodically each 5 minutes, but in only test step. I need to run it on pubsub emulator without deploying it.
How to do it?
I tried to use firebase shell, but it triggered only once
exports.scheduledFunctionPlainEnglish =functions.pubsub.schedule('every 2 minutes')
.onRun((context) => {
functions.logger.log("this runs every 2 minutes")
return null;
})
Scheduled functions are loaded to the Cloud Functions emulator runtime and are bound to the PubSub emulator topic.
But as #samstern said (https://github.com/firebase/firebase-tools/issues/2034):
you'd have to manually trigger them using a Pub/Sub message.
You can do it like this:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import { PubSub } from '#google-cloud/pubsub';
if (!admin.apps.length) {
admin.initializeApp();
}
const pubsub = new PubSub({
apiEndpoint: 'localhost:8085' // Change it to your PubSub emulator address and port
});
setInterval(() => {
const SCHEDULED_FUNCTION_TOPIC = 'firebase-schedule-yourFunctionName';
console.log(`Trigger sheduled function via PubSub topic: ${SCHEDULED_FUNCTION_TOPIC}`);
const msg = await pubsub.topic(SCHEDULED_FUNCTION_TOPIC).publishJSON({
foo: 'bar',
}, { attr1: 'value1' });
}, 5 * 60 * 1000); // every 5 minutes
Additional info about this concept (thanks to #kthaas):
https://github.com/firebase/firebase-tools/pull/2011/files#diff-6b2a373d8dc24c4074ee623d433662831cadc7c178373fb957c06bc12c44ba7b
https://github.com/firebase/firebase-tools/pull/2011/files#diff-73f0f0ab73ffbf988f109e0a4c8b3b8a793f30ef33929928a892d605f0f0cc1f
As you said, you can use firebase shell to run your function once.
And in firebase shell, you can use NodeJS commands.
Use setInterval
Inside firebase functions:shell, use setInterval to run your function every 2 minutes.
user#laptop:~$ firebase functions:shell
✔ functions: functions emulator started at http://localhost:5000
i functions: Loaded functions: myScheduledFunction
firebase > setInterval(() => myScheduledFunction(), 120000)
> this runs every 2 minutes
Single line script
Since version 8.4.3 of firebase-tools, and especially this PR, the pipe solution does not work anymore.
In Bash, you can even pipe the setInterval command to firebase shell
user#laptop:~$ echo "setInterval(() => myScheduledFunction(), 120000)" | firebase functions:shell
For those of you seeing this in 2023, it's still not supported.
My solution was to abstract the code that does the "work" out of functions.pubsub.schedule and into their own functions. Then create a separate file (i added it at the top of the functions folder) with a setInterval inside it that fires the aforementioned abstracted function.
For example, somewhere in your code:
exports.myScheduledFunctionCode = () => {
console.log('why, hello there interval');
}
And in the timers.js (for example) file at the top of the /functions directory:
setInterval(() => {
myScheduledFunctionCode();
}, 60000);
Then, you can fire up your Firebase Emulator suite. In another Terminal session, just run a vanilla $ node functions/timers.js. Now your scheduled function code is running, and your whole emulator suite too.
Hope this helps someone!
This is currently not supported for scheduled functions. The documentation states:
Using the shell, you mock data and perform function calls to simulate interaction with products that the Emulator Suite does not currently support: Storage, PubSub, Analytics, Remote Config, Storage, Auth, and Crashlytics.
Scheduled functions are an unsupported extension of pubsub triggers.
Feel free to file a feature request with Firebase support.

Deploying Cloud Firestore Trigger function from GCP Console

I have a function that is fired on a onUpdate trigger from my cloud firestore database.
The function not being called at all when I change my database.
I did not deploy the function using firestore CLI, instead I deployed it using the GCP Console.
Here is the function:
exports.NotificationListener = functions
.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const userId = context.params.userId.toString();
const eventId = context.eventId;
console.log('EventId:' + eventId);
console.log('Change in:' + userId);
return 200;
});
Here is the deployment information from the GCP console (showing the trigger):
Finally, here is the Cloud Firestore schema:
I want to monitor any changes to any "USER" in the collection: "/user", hence I am using "user/{userId}".
Why is this function not being called when I change the database ?
EDIT 1
A little information about my environment:
I have my entire project core in a TypeScript file. I have over 40 HTTPS triggered functions that are currently online.
I add a new function in my TS file, then I do a npm run build to compile and get the JS file.
Finally, I go to Google Cloud Console and create a function and choose "Zip Upload" and upload the compiled JS file (obviously, along with the required JSON files for getting Database URL, Authentication etc.)
This approach works perfectly fine, at least for HTTP triggered firestore functions.
Now I repeated the same steps as above for the onUpdate trigger and just instead of choosing HTTP trigger, I chose Cloud Firestore trigger. The trigger information can be found above in the screenshot.
onUpdate is not being fired on DB changes.
EDIT 2
My event trigger function NotificationListener is showing up in the firebase console functions list along with my other 40 HTTPS functions. But it is not being called.
#doug-stevenson, your answer seems to have disappeared, I am not sure why.
Anyway, I found the reason why it wasn't working.
My firebase database was in project "Placeholder 1" and my GCP functions were in project "Placeholder 2".
Now, I was able to update the "Placeholder 1" DB from GCP functions (in "Placeholder 2") using firabse-functions API because I set the DatabaseURL to "Placeholder 1".
But, just setting the DatabaseURL to the desired database doesn't work if you want to LISTEN to the database for changes. You actually need to have the function in the same project otherwise it is not able to subscribe and listen for events.
I think it's a little inconsistent that you can read/write to a DB from different projects, but to listen for events, function needs to be in same project.
Or maybe I am missing something fundamental that caused this confusion for me.

(firebase functions) Error: Forbidden Your client does not have permission to get URL /

I have problem when invoking deployed function in firebase. I have an editor role in the firebase project and when I deployed functions, didn't have any problem with invoking them. When I deployed a new function yesterday, I got the error message that says
Error: Forbidden
Your client does not have permission to get URL / < Function Name > from this server.
Nothing has been changed to my role. It is strange that since yesterday, whatever function I deployed, threw those errors.
In gcp console/cloud functions, where you can see permissions of the function that was selected, I've noticed that "cloud functions invoker" was not assigned to that function. I thought this should be added to any function by default as long as I have an editor access but strangely it does not add them anymore. other functions that were deployed since yesterday have the same issue
any suggestions or advices will be appreciated. Thank you
Please Review Allowing unauthenticated function invocation
As of January 15, 2020, HTTP functions require authentication by default. You can specify whether a function allows unauthenticated invocation at or after deployment.
So here's the answer from the firebase team
The issue you are experiencing is likely caused by the fact that after January 15, 2020, Google Cloud Functions automatically creates HTTP functions to be >private by default.
Please, update the CLI, by running the following command:
npm install -g firebase-tools
This will ensure that future HTTP functions that are created will be publicly accessible.
Lastly, for the existing functions that has the permission issues, you will need >to manually set a function to public using Cloud Console or gcloud CLI.
If you have any questions or you are still facing this issue, please, don’t >hesitate to write back.
edited*
There could be several reasons to cause this issue.
check your function endpoint url make sure there's no typo or space
In the gcp console, make sure you have permission to invoke function https://console.cloud.google.com/functions/list?project=<YOUR_PROJECT_ID>
If the above two are checked, delete your function and redeploy your them again
Unfortunately, you can't do this in Firebase, you have to go into the Google Cloud project which 'hosts' your firebase project. You can follow this guide by Google, and have a look at the screenshots below:
You should see Allow unauthenticated now
To allow unauthenticated invocation of a function, you add the special allUsers member id to the function and grant it the Cloud Functions Invoker role:
You can limit domain access in your function, for example:
exports.myTest= async(req, res) => {
res.set('Access-Control-Allow-Origin', 'foo.com');
...etc
I defined my Firebase cloud functions in typescript/JS and deploy using Firebase CLI. I got this error after customizing the deployment settings, and I fixed it by specifying invoker="public" - I did not need to dig into IAM settings or use the console or CLI to fix.
export const serve = functions
.region("us-west2")
.runWith({
invoker: "public", // this is the magic line
})
.https.onRequest(
async (request: functions.Request, response: functions.Response) => {
// ...
})
updating firebase-tools wasn't enough in my case because i already deployed that function and updating it didn't fix the issue, i had to delete it and deploy again

Writes to Cloud Firestore (emulator) is not showing in Cloud Functions emulator

I am using Firebase Hosting/Firestore/Functions for a Vue app. Hosting + Firestore are working fine.
Now I wanna add more functionality and wanted to add Functions. To test locally, I initiated a Firestore and can run all 3 emulators.
Now, when I start the emulators and goto the hosting emulator, I can insert a record, which also shows up in production database, but the function is not triggered. It's onCreate.
I deployed the function and it works fine. I can see the console.log().
Why are local/production writes not triggering the cloud function?
Here is the function:
export const sendWelcomeEmail = functions.firestore.document('/activeJobsTestDB/{jobId}').onCreate((data,context) => {
const inputRecord = data.data();
console.log('here' + inputRecord);
// const mailOptions = {
// from: '"Spammy Corp." <noreply#firebase.com>',
// to: inputRecord.email,
// };
});
i Starting emulators: ["functions","firestore","hosting"]
⚠ Your requested "node" version "8" doesn't match your global version "12"
✔ functions: Emulator started at http://localhost:5001
i firestore: Serving ALL traffic (including WebChannel) on http://localhost:8080
⚠ firestore: Support for WebChannel on a separate port (8081) is DEPRECATED and will go away soon. Please use port above instead.
i firestore: Emulator logging to firestore-debug.log
✔ firestore: Emulator started at http://localhost:8080
i firestore: For testing set FIRESTORE_EMULATOR_HOST=localhost:8080
i hosting: Serving hosting files from: dist
✔ hosting: Local server: http://localhost:5000
✔ hosting: Emulator started at http://localhost:5000
i functions: Watching "/Volumes/Work/playground/sforce-job/sforce-jobs/functions" for Cloud Functions...
> here
✔ functions[sendWelcomeEmail]: firestore function initialized.
✔ All emulators started, it is now safe to connect.
I goto localhost:5000 and can use my app as I want, but the function is not triggered. Any help will be highly appreciated.
Answering myself here in case someone faces this: I realised there is no way to connect Cloud Firestore with local Cloud Function. Easy way to do it is to have a json which looks like DocumentSnapshot and then pass it to the function via shell. Use:
firebase function:shell
var data = require('./testData.json');
sendwelcomeEmail(data)
Other way will be to create a local database in firestore emulator, point the cloud function to look at firestore emulator.
Then run hosting emulator and all 3 should play well nicely.

Unable to change location for firebase pubsub trigger

I have an App Engine app in asia-northeast1, but i could not specify the region for pubsub trigger.
This works:
functions.region("asia-northeast1").https.onRequest(async (req, res)
This does not work:
functions.region("asia-northeast1").pubsub.schedule('* 6-23 * * *')
With the following erroor message: Error: HTTP Error: 400, Location must equal asia-northeast1 because the App Engine app that is associated with this project is located in asia-northeast1
Does anyone have any experience getting pubsub trigger to work in a different region than the default us-central1? Thank you in advance
This is a known bug in the Firebase CLI version 7.1.0. Downgrade to a prior version for now (7.0.2). This will be fixed.
When you encounter unexpected problems with the Firebase CLI, you should contact Firebase support directly, and also consider filing a bug report in GitHub.
Same issue here: I've resolved setting Google Cloud Platform (GCP) resource location in Firebase Project settings, which was undefined, to eur3 (europe-west) (my AppEngine resources are in europe-west1)

Resources