I've been trying callable functions to avoid handling cors manually but so far nothing is working
i've read similar issue Firebase Callable Function + CORS
the difference is the that dude has 'no access control allow origin' issue. Mine is response to preflight ... issue
I'd like to request for a guidance people. It's frustrating argh..
I'm on Blaze plan
So far i've been trying only to run the functions Locally. i have not deployed the function at all.
this is my function code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.createOrder = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
resolve(data)
.then(result => {
return result;
})
.catch(err => {
console.error(err.code);
throw new functions.https.HttpsError('unknown', err.message);
});
});
});
this is my client code
export const createOrder = order => {
functions
.httpsCallable('createOrder')({ data: order })
.then(result => {
console.log('result create order is', result);
return result;
});
};
functions package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"#sendgrid/mail": "^6.4.0",
"axios": "^0.19.0",
"cors": "^2.8.5",
"firebase": "^6.3.1",
"firebase-admin": "^8.2.0",
"firebase-functions": "^3.1.0",
"firebase-functions-test": "^0.1.6"
},
"engines": {
"node": "8"
},
"private": true
}
firebase config.json
"firebase": {
"apiKey": "AIzaSy*****",
"authDomain": "jokii-test.firebaseapp.com",
"databaseURL": "https://jokii-test.firebaseio.com",
"projectId": "jokii-test",
"storageBucket": "jokii-test.appspot.com",
"messagingSenderId": "104544.....",
"appId": "1:10454485....."
}
Firebase SDK = "firebase": "^6.3.1",
The client SDK doesn't know how to access a function that hasn't been deployed. Notice in the error output that the URL it's trying to access is the one for your fully deployed function. It's currently not possible to have it override the URL to access one you're running locally on localhost.
If you want to invoke your callable function locally, you'll need to implement a client that follows the protocol specification for callable functions. And, as you can see, that's going to be a fair amount of work, because the client SDK is managing a lot of the HTTP protocol work for you.
Related
I have a google cloud function that will send me an email when a document is added to the Cloud firestore.
Runtime envirment is: Nodejs 14
The function does work but in the logs I get a warning "Warning, FIREBASE_CONFIG and GCLOUD_PROJECT environment variables are missing. Initializing firebase-admin will fail" I don't really understand this warning.
Do you know of any solution? I don't want to see this warning. What do I have to do(solution).
I saw some people used nodejs 8 and it worked but I don't want to use nodejs 8.
I am very new to the cloud stuff. I am talking weeks. Please don't make you answer complicated.
here is the code:
"use strict";
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const nodemailer = require("nodemailer");
const FireStoreParser = require ("firestore-parser");
const { google } = require("googleapis");
admin.initializeApp();
exports.sendMail = functions.handler.firestore.document.onCreate(async(change,context) => {
const OAuth2 = google.auth.OAuth2;
const clientID = "you-dont-need-this";
const clientSecret = "you-dont-need-this";
const refreshToken = "you-dont-need-this"
const oauth2Client = new OAuth2(
clientID, //client Id
clientSecret, // Client Secret
"https://developers.google.com/oauthplayground" // Redirect URL
);
oauth2Client.setCredentials({
refresh_token: refreshToken
});
const accessToken = await oauth2Client.getAccessToken()
const smtpTransport = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: "you-dont-need-this",
clientId: clientID,
clientSecret: clientSecret,
refreshToken: refreshToken,
accessToken: accessToken
}
});
const _fieldsProtoInJSON = FireStoreParser(change._fieldsProto);
const textToMail = JSON.stringify(_fieldsProtoInJSON);
var attachment = [
{ // binary buffer as an attachment
filename: 'dataContainer.json',
content: textToMail
}
];
const mailOptions = {
from: `<you-dont-need-this>`,
to: 'you-dont-need-this,
subject: `New message container ${_fieldsProtoInJSON.ContainerNumber} from ${_fieldsProtoInJSON.Tag}`,
text: `See attachment for data.`,
attachments: attachment
};
smtpTransport.sendMail(mailOptions, (error, info) => {
if (error) {
console.log(error.message);
smtpTransport.close();
}
return "mail sent";
});
});
this is the package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "14"
},
"dependencies": {
"firebase-admin": "^8.12.1",
"firebase-functions": "^3.6.2",
"firestore-parser": "0.9.0",
"#google-cloud/storage": "^5.1.1",
"googleapis": "^51.0.0",
"nodemailer": "^6.4.8"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1"
},
"private": true
}
I fixed the issue by deploying the function using firebase cli. That way the variables are populated automatically.
check this link for an example: Firebase CLI reference
I want to use Stripe with Firebase Functions.
Attempting to deploy the following source code to functions will result in an error.
const functions = require('firebase-functions');
const express = require("express");
const app = express();
// This is your real test secret API key.
const stripe = require("stripe")("STRIPE KEY HERE");
app.use(express.static("."));
app.use(express.json());
const calculateOrderAmount = items => {
// Replace this constant with a calculation of the order's amount
// Calculate the order total on the server to prevent
// people from directly manipulating the amount on the client
return 1400;
};
app.post("/create-payment-intent", async (req, res) => {
const { items } = req.body;
// Create a PaymentIntent with the order amount and currency
const paymentIntent = await stripe.paymentIntents.create({
amount: calculateOrderAmount(items),
currency: "usd"
});
res.send({
clientSecret: paymentIntent.client_secret
});
});
module.exports.express = functions.https.onRequest(app);
This is what I want to achieve.
https://stripe.com/docs/payments/integration-builder
I want to deploy to Firebase Functions using react for the front and Node for the back end.
</functions/package.json>
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "12"
},
"main": "index.js",
"dependencies": {
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.11.0"
},
"devDependencies": {
"eslint": "^7.6.0",
"eslint-config-google": "^0.14.0",
"firebase-functions-test": "^0.2.0"
},
"private": true
}
When I tried the command "firebase deploy --only" functions: express ", I got the following error:
Error: function terminated. Recommended action: inspect logs for termination reason. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging Function cannot be initialized
This was accompanied by this Log object:
{
"#type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {
"code": 3,
"message": "Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation."
},
"authenticationInfo": {
"principalEmail": "MYADDRESS#gmail.com"
},
"serviceName": "cloudfunctions.googleapis.com",
"methodName": "google.cloud.functions.v1.CloudFunctionsService.UpdateFunction",
"resourceName": "projects/MYPROJECT/locations/us-central1/functions/express"
}
i deploying functions
i functions: ensuring required API cloudfunctions.googleapis.com is enabled ...
i functions: ensuring required API cloudbuild.googleapis.com is enabled ...
✔ functions: required API cloudbuild.googleapis.com is enabled
✔ functions: required API cloudfunctions.googleapis.com is enabled
i functions: preparing functions directory for uploading ...
i functions: packaged functions (44.09 KB) for uploading
✔ functions: functions folder uploaded successfully
i functions: creating Node.js 12 function express (us-central1) ...
Functions deploy had errors with the following functions:
express (us-central1)
To try redeploying those functions, run:
firebase deploy --only "functions: express"
To continue deploying other features (such as database), run:
firebase deploy --except functions
Error: Functions did not deploy properly.
Does anyone know the solution?
You need to export the Express.js app as an HTTPS function with
exports.app = functions.https.onRequest(app);
instead of doing
module.exports.express = functions.https.onRequest(app);
See the doc.
Then you need to deploy with, for example, firebase deploy --only functions.
Note that it seems that there is an extra double quote (") in the command you entered:
I typed the command "firebase deploy --only" functions: express "
This question already has answers here:
Error Deploying Firestore Function with a space in the name of a collection
(2 answers)
Closed 2 years ago.
I have been trying to deploy my firebase function called onFollowUser however, it has been constantly failing to launch. I have the Blaze plan currently and this is the error message:
⚠ functions[onFollowUser(us-central1)]: Deployment error.
Failed to configure trigger providers/cloud.firestore/eventTypes/document.create#firestore.googleapis.com (__gcf__.us-central1.onFollowUser)
Functions deploy had errors with the following functions:
onFollowUser
To try redeploying those functions, run:
firebase deploy --only functions:onFollowUser
To continue deploying other features (such as database), run:
firebase deploy --except functions
Error: Functions did not deploy properly.
Here is my complete index.js:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.onFollowUser =
functions
.firestore
.document('/Followers/{userID}/User Follower/{followerID}')
.onCreate(async (snapshot, context) => {
console.log(snapshot.data());
});
I have spotted the error... My database is located in Europe-central, however, for some reason, it is deploying to US-central... How can I change this? The ID of my project which it says it is deploying to is correct.
Here is my package.json:
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"dependencies": {
"firebase-admin": "^8.10.0",
"firebase-functions": "^3.6.1"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.2.0"
},
"private": true
}
Edit: Even though I get this failing message, I can see the function on my console :
This is a know issue, see: Error Deploying Firestore Function with a space in the name of a collection
Rename the a collections so that they do not includes spaces, rather use camel case, dashes or underscores.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
admin.firestore().settings({ timestampsInSnapshots: true });
exports.onFollowUser =
functions
.firestore
.document('/Followers/{userID}/User-Follower/{followerID}')
.onCreate(async (snapshot, context) => {
console.log(snapshot.data());
return;
});
I am getting this error when trying to use #google-cloud/logging with Firebase Functions. If I remove the logging stuff everything works fine. I also tried using #google-cloud/logging-winston however, causing the same error along with an additional error.
Here is my code:
const functions = require('firebase-functions')
const mongoose = require('mongoose')
const Tag = require('../../models/tag')
const { Logging } = require('#google-cloud/logging')
const logging = new Logging({projectId: 'circle-fc687'})
const log = logging.log('tags')
const METADATA = {
resource: {
type: 'cloud_function',
labels: {
function_name: 'tags-getTags',
region: 'us-central1'
}
}
}
const uri = 'mongoURL'
module.exports = functions.https.onRequest(async (req, res) => {
try {
console.log('getTags : start')
const logOne = log.entry(METADATA, { event: 'getTags:mongodb:started', value: 'started', message: 'tags-getTags:started' })
log.write(logOne) // I've also tried with an await here thinking maybe it was trying to do something after the function terminates but that didn't fix anything
console.log('getTags : after first logging statement') // doesn't work
await mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true })
const result = await Tag.find({})
res.send(result)
} catch (err) {
res.send(err)
}
})
Here is the error:
Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
at GoogleAuth.getApplicationDefaultAsync (/srv/node_modules/google-auth-library/build/src/auth/googleauth.js:161:19)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
Edit 1: adding package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"dependencies": {
"#google-cloud/logging": "^6.0.0",
"#google-cloud/logging-winston": "^3.0.2",
"axios": "^0.19.0",
"cors": "^2.8.5",
"firebase-admin": "^8.9.0",
"firebase-functions": "^3.3.0",
"mongoose": "^5.8.3",
"mongoose-unique-validator": "^2.0.3",
"winston": "^3.2.1"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.1.7"
},
"private": true
}
I'm just trying to fetch "uid" of my authenticated users using firebase functions. But every time I run the function in "firebase functions:shell". I get these errors. can anyone help me fix this problem?
"context.auth.uid" TypeError: Cannot read property 'uid' of undefined
exports.sendNewUser = functions.database.ref('/Users/')
.onCreate(async (snapshot, context) => {
const userId = await context.auth.uid;
const tokenPath = await admin.database().ref('Notify').once('value')
var message = []
tokenPath.forEach((childSnapshot) => {
var allTokens = childSnapshot.val().expo
if (allTokens) {
message.push({
"to": allTokens,
"header": " Users",
"body": "New user has been added, check them out!!!"
})
}
})
await fetch('https://exp.host/--/api/v2/push/send', {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(message)
})
console.log("The user ID is : " + userId)
})
Package.json:
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"dependencies": {
"dateformat": "^3.0.3",
"firebase-admin": "6.3.0",
"firebase-functions": "^2.1.0",
"node-fetch": "^2.3.0"
},
"devDependencies": {
"eslint": "^4.12.0",
"eslint-plugin-promise": "^3.6.0"
},
"private": true
}
The context.auth.uid will be undefined with the onCreate trigger, as this is triggered by the cloud funtions runtime and not the user that created the document.
See https://stackoverflow.com/a/64345666/4868790
The documentation for running Realtime Database triggers is clear:
By default, the shell runs Realtime Database functions with
administrative privileges. Use the auth option to instead run
functions as a particular end user, or as an unauthenticated user:
# to mock unauthenticated user
myDatabaseFunction('data', {authMode: 'USER'})
# to mock end user
myDatabaseFunction('data', {auth: {uid: 'abcd'}})
You need to pass the last object that simulates the auth payload in the context. Without that, auth will contain nothing.
It will work fine when you publish it.
You don't need to use await when accessing the uid. It's not an asynchronous function.