Firebase HTTP Trigger Cloud Function to change users' values in realtime database - javascript

So I have written code which should change a certain value in the database. I would use cron-jobs to trigger it in every 24h, but there is something wrong with my code.
const functions = require('firebase-functions');
exports.resetPicksStatus = functions.https.onRequest((req, res) => {
.ref('/users/{userId}')
.onWrite(event => {
const status = event.data.val()
if (status.resetted) {
return true
}
console.log("Resetting status for " + event.paramas.userId)
status.resetted = true
status.picksDone = resetToNil(status.picksDone)
return event.data.ref.set(status)
})
})
function resetToNil(s) {
var resetValue = s
resetValue = resetValue.replace(/\b1\b/ig, "0")
return resetValue
}

It looks like you're trying to put a Realtime Database trigger inside your HTTP trigger, which won't have the outcome you're looking for. Instead of using a database trigger, use the Firebase Admin SDK to access the database from within the HTTP trigger.
In your code, add
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const ref = admin.database().ref();
And use ref to access the database.
Check out the Admin SDK documentation here.
Here are some samples of Cloud Functions, some of which show the Admin SDK.
Here's a video showing how to use the Admin SDK
Here's a video on timing Cloud Functions

Related

TypeError: change.after.val is not a function firebase

Hi there I am trying to read changes in my firestore database
'use stricts'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
require('dotenv').config();
admin.initializeApp(functions.config().firebase);
exports.sendOrderCompletionEmail = functions.firestore.document('/service-requests/{req_id}')
.onUpdate((change, context) => {
const req = context.params.req_id;
const sts = change.after.val(); //Error on this line
console.log(sts);
});
I am getting this error
TypeError: change.after.val is not a function
I want to read changes in my document and return the field value which is changed
Since you are triggering your Cloud Function by the update of a Firestore document, you need to do
const sts = change.after.data();
See the doc for more details.
As a matter of fact we use the val() method for Cloud Functions triggered by a Realtime Database event.
Firebase offers two NoSQL database solutions: Cloud Firestore and the Realtime Database. See this doc for more details.

node.js: firebase snapshot return null

I'm using firebase functions to run the code for my flutter app. That sends a push notification to my app. I want to get the token. But I'm getting null value at snap.val(). Here how my code looks like:
const functions = require('firebase-functions');
var admin = require("firebase-admin");
admin.initializeApp();
var db = admin.database();
exports.CreateTicket = functions.firestore
.document('tickets/{username}')
.onCreate((snapshot, context) => {
console.log(snapshot.data().clientUid);// this one working fine.
var ref = db.ref("token/BX3jXKVpOkRa80SIKb7jPwfbU0c2/");
ref.once("value", (snap) => {
console.log(snap.val()); // this one getting null,
});
});
Your code is querying Realtime Database, but the screenshot here is showing Firestore. These are completely different database systems. Your database query is simply finding nothing, because there is no data at the location of your query.
You will have to write your code using the Firestore APIs for nodejs to read the document you have shown here.

How to update or set property of firestore document after .onCreate cloud function trigger

I'm currently trying to integrate Stripe with my Firebase's Cloud Firestore db through using Cloud Functions for Firebase. The onCreate trigger is happening correctly but I also want it to update or set a specific field called "customer_id" into the right document in my Users collection. I think something is a little off about how I write my function since I'm not the most experienced with javascript.
I've also tried
return admin.firestore().ref(`Users/${user.uid}/customer_id`).set(customer.id);
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
//const logging = require('#google-cloud/logging')();
const stripe = require('stripe')(functions.config().stripe.token);
const currency = functions.config().stripe.currency || 'USD';
// When a user is created, register them with Stripe
exports.createStripeCustomer = functions.auth.user().onCreate((user) => {
return stripe.customers.create({
email: user.email,
}).then((customer) => {
return admin.firestore().collection("Users").doc(user.uid).update({"customer_id": customer.id})
});
});
Customer gets created with Stripe no problem but the "customter_id" field is not getting updated on the Firestore db.
Print screen of the database:
Print screen of the error log:
As said in the comments, from the print screen of the error log, the code you have deployed does not correspond to the code you are referencing to in your question.
The code in your question looks correct.

Getting id of the current user from Cloud Functions and Firebase

I am using google cloud functions to register push notifications through firebase. In my app, i have a notifications reference that changes for a current user whenever they get a new follower or like, etc. As of right now I am able to send the notification to the phone whenever that whole reference child changes
For example, if any single post is liked, then it will send a notification. What I need to do is observe the current user to only send the notification that single person.
Here is my JavaScript file
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendPushNotification = functions.database.ref('/notification/{id}').onWrite(event => {
const payload = {
notification: {
title: 'New message arrived',
body: 'come check it',
badge: '1',
sound: 'default',
}
};
return admin.database().ref('fcmToken').once('value').then(allToken => {
if (allToken.val()) {
const token = Object.keys(allToken.val());
return admin.messaging().sendToDevice(token, payload).then(response => {
});
}
});
});
I would like to replace this line:
functions.database.ref('/notification/{id}').onWrite(event => {
With this:
functions.database.ref('/notification/{id}').(The current user ID).onWrite(event => {
How do I get the current users id?
You seem very new to JavaScript (calling it JSON is sort-of a give-away for that). Cloud Functions for Firebase is not the best way to learn JavaScript. I recommend first reading the Firebase documentation for Web developers and/or taking the Firebase codelab for Web developer. They cover many basic JavaScript, Web and Firebase interactions. After those you'll be much better equipped to write code for Cloud Functions too.
Now back to your question: there is no concept of a "current user" in Cloud Functions. Your JavaScript code runs on a server, and all users can trigger the code by writing to the database.
You can figure out what user triggered the function, but that too isn't what you want here. The user who triggered the notification is not the one who needs to receive the message. What you want instead is to read the user who is the target of the notification.
One way to do this is to read it from the database path that triggered the function. If you keep the notifications per user in the database like this:
user_notifications
$uid
notification1: ...
notification2: ...
You can trigger the Cloud Function like this:
exports.sendPushNotification = functions.database.ref('/user_notification/{uid}/{id}').onWrite(event => {
And then in the code of that function, get the UID of the user with:
var uid = event.params.uid;
For Swift 3.0 - 4.0
You can do this:
import Firebase
import FirebaseAuth
class YourClass {
let user = Auth.auth().currentUser
let userID = user.uid
// user userID anywhere
}

Firebase HTTP Cloud Functions - Read database once

I have a Firebase HTTPs function. The function needs to read a value from a Firebase database based on the query parameter, and return a result based on this data.
The Firebase JS SDK says to do this using:
return firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) {
var username = snapshot.val().username;
// ...
});
However, the Cloud functions examples have:
var functions = require('firebase-functions');
functions.database.ref('/');
But the DB reference doesn't have the method once, only onWrite (https://firebase.google.com/docs/reference/functions/functions.database.RefBuilder). This is obviously for DB write functions, rather than HTTP functions.
Is there a correct way to read from the database once in a HTTP function? Can I use the normal Firebase SDK, or is there a better way?
Thanks.
I found the solution in combining the answer here on how to get the parameter and an answer from Michael Blight to
How to run query from inside of Cloud function?
The answer there also shows what is required to use firebase-admin.
The following works for me when calling my-project.firebaseapp.com/event/123/.
var functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.showEvent = functions.https.onRequest((req, res) => {
const params = req.url.split("/");
const eventId = params[2];
return admin.database().ref('events/' + eventId).once('value', (snapshot) => {
var event = snapshot.val();
res.send(`
<!doctype html>
<html>
<head>
<title>${event.name}</title>
</head>
<body>
<h1>Title ${event. name} in ${event.city}</h1>
</body>
</html>`
);
});
});
You're confusing two parts:
the firebase-functions module, which contains the logic to trigger based on database calls with functions.database.ref('/path').onWrite().
the firebase-admin module, which allows your function to call into the database.
Since you have a HTTP function, you should trigger as the documentation for HTTP functions shows:
exports.data = functions.https.onRequest((req, res) => {
// ...
});
Then in your function, you access the database as the documentation for the Admin SDK shows:
return admin.database().ref('/users/' + userId).once('value').then(function(snapshot) {
var username = snapshot.val().username;
// ...
});
So in total:
exports.date = functions.https.onRequest((req, res) => {
admin.database().ref('/users/' + userId).once('value').then(function(snapshot) {
var username = snapshot.val().username;
res.status(200).send(username);
});
});
Note that this is a tricky pattern. The call to the database happens asynchronously and may take some time to complete. While waiting for that, the HTTP function may time out and be terminated by the Google Cloud Functions system. See this section of the documentation.
As a general rule I'd recommend using a Firebase Database SDK or its REST API to access the database and not rely on a HTTP function as middleware.

Categories