saving firebase user to firestore and adding new elements - javascript

I have a firebase function that is triggered with onCreate method. In this function, I am copying over user data into firestore. Everything works fine, except when I try to add a new element to the user object (even though no errors are thrown) the new firestore document does not show the added element.
Here is my firestore function:
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.newUser = functions.auth.user().onCreate((user)=>{
// create new variable
let currentUser = user;
//add hasSeenProfileUpdate element to the currentUser. This is what I need to add and ultimately save in the firestore
currentUser.hasSeenProfileUpdate = false;
return db
.collection("user")
.doc(user.uid)
.create(JSON.parse(JSON.stringify(currentUser)))
})
The function runs fine and the currentUser is saved to firestore. However the hasSeenProfileUpdate element does not show up in firestore. The console.log on currentUser also doesn't show the new element.
Any help is greatly appreciated!

(Thanks to #Dharmaraj) Posting refactored code that works Now:
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.newUser = functions.auth.user().onCreate((user)=>{
const currentUser = JSON.parse(JSON.stringify(user));
return db
.collection("user")
.doc(user.uid)
.create({
...currentUser,
hasSeenProfileUpdate: false
})
})

Related

Firebase Funtions push notifications

I'm new to firebase and there is something I can't do. I want to send a notification to the phone with firebase functions. I want to receive notifications on the phone when someone follows me. My Firebase collection is as in the photo. I want to access the Followers array and send its information with notification. The codes I could write are as follows. What do I need to add?
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.sendPushNotification = functions.firestore.document('/users/{uid}').onCreate((snap, context) => {
var values = snap.data();
var token = values.fcmTokens;
var payload = {
notification: {
title: values.title,
body: values.message
}
}
return admin.messaging().sendToDevice(token, payload);
});
First, onCreate() function is triggered when a document is created. I assume followers array will be updated everytime someone follows a user? In that case you should be using onUpdate() that'll trigger the function when the document is updated. You can just check if length of followers array has changed in the update, if yes then send the notification as shown below:
exports.sendPushNotification = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const newValue = change.after.data();
const previousValue = change.before.data();
if (newValue.followers.length > previousValue.followers.length) {
// followers count increased, send notification
const token = newValue.fcmTokens;
const payload = {
notification: {
title: "New Follower",
body: "Someone followed you"
}
}
await admin.messaging().sendToDevice(token, payload);
}
return null;
});
Here, we send notification only if the followers field has changed since this function will trigger whenever any field in this user document is updated.
If you want to specify who followed the user, then you'll have to find the new UID added in followers array and query that user's data.
Firestore documents have a max size limit of 1 MB so if a user can have many followers then I'll recommend creating a followers sub-collection. Then you'll be able to use onCreate() on the sub-document path /users/{userId}/followers/{followerId}

How do I write a cloud function which creates a user in the Firestore database once a new user gets authenticated?

So far I have written the following code:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.addAccount = functions.auth.user().onCreate((event) => {
const user = event.data; // The firebase user
const id = user.uid;
return admin
.database()
.ref("/users/" + id)
.set("ok");
});
The idea here is to execute a cloud function once a new user gets created. As this happens, I want to create a new node in the Firestore database. Under the 'users' collection I want to add a document with the uid, which contains a bit of information, in this case a String that says 'ok'.
When deploying this function it produces an error. How exactly should I go about creating it?
The admin.database() returns the Realtime Database service. To use Firestore, use firebase.firestore(). Try refactoring the code as shown below:
exports.addAccount = functions.auth.user().onCreate((event) => {
const user = event.data; // The firebase user
const id = user.uid;
return admin
.firestore()
.collection("users")
.doc(id)
.set({ uid: id, ...user });
});

Setting collection name in Firebase function

Just starting to use Firebase functions and have the sample working, but confused because the update event doesn't occur if I change the 'messages' collection to a different name, eg 'listings'. I change the word 'messages' in two places, on the 'add' and the 'makeUppercase' line. I get the response OK, it writes the data to the collection, but doesn't fire the event. Must be simple, but can't google it.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('messages').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
I'm using the local firebase emulator to do this test, by the way.
This is the new version, ony changing 'messages' to 'vvvv' in two places.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('vvvvv').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/vvvvv/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
OK. Doug, your suggestion sank in after an hour or so! I've restarted everything and think that I understand. If I change the name in those two places, without restarting, the collection.add function takes place and I can see the record in the new collection, but the onCreate event didn't fire. I had to restart the whole service to restart buth parts. I was getting confused because one part was working and not the other. Thanks for your patience.

Firebase functions update document / sendgrid

I have this function of Firebase Firestore, every time a new document is created in the collection pagos I am sending a transactional email through Sendgrid with the data of this new document created. It works well.
My question is how do I do the same function, that is, to send said email but only when the document is updated with a certain field (for example dataPago) Can it be done?
Here my function when creating a document:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const SENDGRID_API_KEY = functions.config().sendgrid.key
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
exports.pagoRealizado = functions.firestore
.document('pagos/{pagoId}')
.onCreate((snap, context) => {
const pagoId = context.params.pagoId;
const db = admin.firestore()
return db.collection('pagos').doc(pagoId)
.get()
.then(doc => {
const pago = doc.data();
const msg = {
from: 'xxx#gmail.com',
to: 'xxx#xxx.com',
templateId: 'd-3473a9cc588245b7b2a6633f05dafdd8',
substitutionWrappers: ['{{', '}}'],
dynamic_template_data: {
nombre: pago.dataCliente.nombre,
}
};
return sgMail.send(msg)
})
.then(() => console.log('email enviado!'))
.catch(err => console.log(err))
});
Instead of using an onCreate trigger, you can use an onUpdate trigger. This will fire whenever a matched document is changed in some way, but not created or deleted. You can read more about each kind of Firestore trigger in the documentation.
You can't set up a trigger on specific field in a document. The trigger will fire when any field in the document changes in any way. You will have to check the before and after states of the document snapshots delivered to the function in order to figure out if it's a change you want to act on. Again, the documentation talks about this in more detail.

How to retrieve data from Firebase using DialogFlow Inline Editor

I am pretty new to DialogFlow. I am wondering how can I retrieve data from Firebase through the Inline Editor of DialogFlow. Hope you can help me!
Thats how you can communicate with firebase from dialogflow
const functions = require('firebase-functions');
const firebaseAdmin = require('firebase-admin');
const DialogflowApp = require('actions-on-google').DialogflowApp;
Initialize Firebase Admin SDK.
firebaseAdmin.initializeApp(functions.config().firebase);
Interaction with firebase Collection users in fulfillment function
let userId = app.getUser().userId;
admin.firestore().collection('users').where('userId', '==', userId).limit(1).get()
.then(snapshot => {
let user = snapshot.docs[0]
if (!user) {
// If user is not in DB, its their first time, Welcome them!
app.ask('Welcome to my app for the first time!');
// Add the user to DB
firebaseAdmin.firestore().collection('users').add({
userId: userId
}).then(ref => {
console.log('Added document with ID: ', ref.id);
});
} else {
// User in DB
app.ask('Welcome back!')
}
});
}
// Map function hanlder to Dialogflow's welcome intent action 'input.welcome'
const actionMap = new Map('input.welcome', start)
app.handleRequest(actionMap);

Categories

Resources