For some reason, I don't know, my cloud function isn't working with the error being:
! functions: failed to update function projects/jungschar-website/locations/us-central1/functions/createUser
Failed to update function projects/jungschar-website/locations/us-central1/functions/createUser
Functions deploy had errors with the following functions:
createUser(us-central1)
i functions: cleaning up build files...
Error: There was an error deploying functions
index.ts
import * as functions from "firebase-functions";
import admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
export const createUser = functions.auth.user().onCreate((user) => {
db.doc("users/" + user.uid).set({
uid: user.uid,
email: user.email,
isAdmin: false,
});
});
firebase-debug.log
https://paste.gg/p/anonymous/827e6ed903df4ad097e6551bd859884f
Please help me. I've been googling for so long
import * as functions from "firebase-functions";
import admin = require("firebase-admin");
admin.initializeApp();
// const db = admin.firestore();
export const createUser = functions.auth.user().onCreate((user) => {
admin.firestore().doc("users/" + user.uid).set({
uid: user.uid,
email: user.email,
isAdmin: false,
});
});
This works
Related
Given that I have a Firebase project, but no development environment that supports the Firebase SDK, how can I get a valid Firebase JWT for one of the users in the Firebase project? I am able to create cloud functions in the project, and I tried making a function for this (in TypeScript), but to no avail:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
export const login = functions.https.onRequest((req, res) => {
const email: string = req.query.email || req.body.email;
const password: string = req.query.password || req.body.password;
admin.auth().signInWithEmailAndPassword(email, password);
admin.auth().currentUser.getIdToken(true).then((idToken: any) => {
functions.logger.info("token: " + idToken, {structuredData: true});
res.status(200).send(idToken);
}).catch((error: any) => {
functions.logger
.info("could not get token: " + error, {structuredData: true});
res.status(500).send(error);
});
});
This code wont deploy due to these errors:
Property 'signInWithEmailAndPassword' does not exist on type 'Auth'.
Property 'currentUser' does not exist on type 'Auth'.
Here's the JS script I got from a colleague for this:
// Import the functions you need from the SDKs you need
const { initializeApp } = require("firebase/app");
const { getAuth, signInWithEmailAndPassword } = require("firebase/auth");
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "API-key-here",
authDomain: "my-app.firebaseapp.com",
databaseURL: "https://my-app-default-rtdb.firebaseio.com",
projectId: "my-app",
storageBucket: "my-app.appspot.com",
messagingSenderId: "sender-id-here",
appId: "app-id-here",
measurementId: "measurement-id-here"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth();
signInWithEmailAndPassword(auth, "user#example.com", "user-password-here")=
.then((userCredential) => {
console.log(userCredential.user.accessToken);
})
.catch((error) => {
console.log(error.message);
});
I have this cloud function in my index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
const db = admin.firestore();
const fcm = admin.messaging();
console.log("osakosak");
export const sendToDevice = functions.firestore
.document('orders/{orderId}')
.onCreate(async snapshot => {
console.log("osakosak2");
const order = snapshot.data();
const querySnapshot = await db
.collection('users')
.doc(order.ustaID)
.collection('tokens')
.get();
const tokens = querySnapshot.docs.map(snap => snap.id);
const payload: admin.messaging.MessagingPayload = {
notification: {
title: 'New Order!',
body: `you sold a ${order.day} for ${order.time}`,
click_action: 'FLUTTER_NOTIFICATION_CLICK'
}
};
return fcm.sendToDevice(tokens, payload);
});
However, when the document gets added a notification isn't sent. Nor is anything printed. I have deployed the function.
You need to check your function error logs in your firebase functions. Go to your function named sendToDevice and click show daily logs. Also be sure that collection and document names are correct. I had the same issue and I solved them by checking logs and correcting the collection/document names in function.
I have the following function in my index.ts file:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
const fcm = admin.messaging();
export const sendToDevice = functions.firestore
.document('orders/{orderId}')
.onCreate(async snapshot => {
print("aa")
console.log("osakosak");
const order = snapshot.data();
const querySnapshot = await db
.collection('users')
.doc(order.ustaID)
.collection('tokens')
.get();
const tokens = querySnapshot.docs.map(snap => snap.id);
const payload: admin.messaging.MessagingPayload = {
notification: {
title: 'New Order!',
body: `you sold a ${order.day} for ${order.time}`,
click_action: 'FLUTTER_NOTIFICATION_CLICK'
}
};
return fcm.sendToDevice(tokens, payload);
});
However, when the new document gets added into the order collection, this doesn't get triggered. Even the print and console.log don't work. I tried putting print and console log before export, and it still didn't fire.
Based on your comments ("It depends on cloud_firestore in pubspec.yaml"), it seems that you didn't deploy your Cloud Function correctly.
As a matter of fact, Cloud Functions are totally independent from your Flutter app (your front-end). It is a back-end service. You should deploy it with the Firebase CLI, see the doc. Note that the code shall be in the Firebase Project, not in your Flutter project.
I'm trying to set up a scheduled firebase function that will export all collections in Firestore every 24 hours. I'm using this script for that:
import {fs} from '../services/firestore';
import * as functions from 'firebase-functions';
import * as firestore from '#google-cloud/firestore';
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://my-cool-backup';
export const scheduledFirestoreExport = functions
.region('europe-west1')
.pubsub
.schedule('every 24 hours')
.onRun(async (context) => {
const collections = await fs.listCollections();
const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT;
const databaseName =
client.databasePath(projectId, '(default)');
const responses = await client.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: collections.map(x => x.id)
});
const response = responses[0];
console.log(`Operation Name: ${response['name']}`);
return response;
});
../services/firestore looks like this:
import * as settings from '../settings.json';
import * as serviceAccount from '../firebase-admin.json';
import * as admin from 'firebase-admin';
export const fs = admin.initializeApp({
credential: admin.credential.cert(serviceAccount as any),
...settings.firebase
}).firestore();
When I trigger the function using the Google Cloud Platform, this is the output:
Error: function execution failed. Details:
7 PERMISSION_DENIED: The caller does not have permission
The service account I'm using has the following permissions
I have many functions running without any problems, just this one is failing. I suspect it's because of #google-cloud/firestore, whereas the other ones only use firebase-admin
The error message gives me very little to go with. What am I missing here?
This is most certainly an issue with permission on the service account you are using.
You can follow this link for settings Role (roles/datastore.user) [1], [2] for firestore on service account
[1]https://cloud.google.com/firestore/docs/quickstart-servers#set_up_authentication
[2]https://cloud.google.com/firestore/docs/security/iam#roles
I'm creating a react application. I have code like this
async componentDidMount() {
const questions = await axios.get('getQuestions');
console.log(questions);
}
(I have a baseURL set up for axios and all, so the URL is correct)
I created a firebase function as follows (typescript)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
const db = admin.firestore();
exports.getQuestions = functions.https.onRequest(async (request, response) => {
const questions = [];
const querySnapshot = await db.collection('questions').get();
const documents = querySnapshot.docs;
documents.forEach(doc => {
questions.push(doc.data());
});
response.json({ questions: questions });
});
Now when I build and run firebase deploy --only functions, and then visit the url directly, everything works. I see my questions.
But in the react app, I get the following error
Access to XMLHttpRequest at '.../getQuestions' from origin
'http://localhost:3000' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
After some googling, I tried
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
const db = admin.firestore();
const cors = require('cors')({ origin: true });
exports.getQuestions = functions.https.onRequest(
cors(async (request, response) => {
const questions = [];
const querySnapshot = await db.collection('questions').get();
const documents = querySnapshot.docs;
documents.forEach(doc => {
questions.push(doc.data());
});
response.json({ questions: questions });
})
);
But that just gave me an error when I ran firebase deploy --only functions
✔ functions: Finished running predeploy script. i functions:
ensuring necessary APIs are enabled... ✔ functions: all necessary
APIs are enabled i functions: preparing functions directory for
uploading...
Error: Error occurred while parsing your function triggers.
TypeError: Cannot read property 'origin' of undefined
at ...
And tbh, even if this command worked, I don't know if it is the correct solution
Got it :) I was doing something silly
import * as cors from 'cors';
const corsHandler = cors({ origin: true });
exports.getQuestions = functions.https.onRequest(async (request, response) => {
corsHandler(request, response, async () => {
const questions = [];
const querySnapshot = await db.collection('questions').get();
const documents = querySnapshot.docs;
documents.forEach(doc => {
questions.push(doc.data());
});
response.status(200).json({ questions: questions });
});
});
This answer will help someone who facing cors error.
01 - Create Firebase Function Called BtnTrigger (You can name whatever you like)
// Include Firebase Function
const functions = require('firebase-functions');
// Include Firebase Admin SDK
const admin = require('firebase-admin');
admin.initializeApp();
//cors setup include it before you do this
//run npm install cors if its not in package.json file
const cors = require('cors');
//set origin true
const corsHandler = cors({ origin: true });
//firebase function
export const BtnTrigger = functions.https.onRequest((request, response) => {
corsHandler(request, response, async () => {
//response.send("test");
response.status(200).json({ data: request.body });
});
});
Then Run firebase deploy --only functions this will create your firebase function. if you need you can check it from your Firebase Console.
02 - Create Function Trigger from your Application from your application code
i used same BtnTrigger name to understand it properly you can change variable here but httpsCallable params should same as your Firebase Function Name you created.
var BtnTrigger =firebase.functions().httpsCallable('BtnTrigger');
BtnTrigger({ key: value }).then(function(result) {
// Read result of the Cloud Function.
console.log(result.data)
// this will log what you have sent from Application BtnTrigger
// { key: value}
});
Don't Forget to import 'firebase/functions' from your Application Code