How to access user profile information in firebase through getUser() - javascript

I am using cloud functions as a means to send users push notifications for my app. I am following the template set by google Here. The problem I have is that I dont really understand Javascript well and I have my user profile data stored within a profile node. When I call the getUser() function I am not able to access the user info within the profile node. How can I access the data within the users profile node so that I can display their "username" and "profileImage" in the push notifications.
Data Structure
users/uid/profile/Dictionary(key/val pairings here for data).
Google Data Structure
users/uid/displayName
Cloud Function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendPushNotificationRep = functions.database.ref('/recieved-friend-requests/{userId}/{friendId}').onWrite(event => {
const userID = event.params.userId;
const friendID = event.params.friendId;
if (!event.data.val()) {
return;
}
const getDeviceTokensPromise = admin.database().ref(`/users/${userID}/fcmToken`).once('value');
// Get the follower profile.
const getRepProfilePromise = admin.auth().getUser(friendID);
return Promise.all([getDeviceTokensPromise, getRepProfilePromise]).then(results => {
const tokensSnapshot = results[0];
const friend = results[1];
if (!tokensSnapshot.hasChildren()) {
return console.log('There are no notification tokens to send to.');
}
const payload = {
notification: {
title: 'Rep Request!',
body: `${friend.username} sent you a request`,
badge: '1',
sound: 'default',
icon: 'logo3'
}
};
const tokens = Object.keys(tokensSnapshot.val());
// Send notifications to all tokens.
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove());
}
}
});
return Promise.all(tokensToRemove);
});
});
});

Related

Adaption of firebase stripe sample cloud functions returning unspecified error

I am implementing the firebase stripe cloud functions from this sample: https://github.com/firebase/functions-samples/blob/master/stripe/functions/index.js with some adaptions (mainly running stripe.confirmCardSetup() on the cloud function instead of front-end because I had a lot of trouble trying to import stripe correctly outside of the functions files) in my Vue webapp.
The code as is, however, produces an error with no type specification, which is why it sets the field "error" to 'An error occurred, developers have been alerted', as defined in the function userFacingMessage()
What is causing these errors?
Btw, I am still running stripe in test mode and use the test cards for testing, however, I don't imagine that causes the errors.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// const { Logging } = require('#google-cloud/logging');
// const logging = new Logging({
// projectId: "",
// });
const stripe = require('stripe')(functions.config().stripe.secret, {
apiVersion: '2020-03-02',
});
exports.createStripeCustomerSA = functions
.region('southamerica-east1')
.auth.user().onCreate(async (user) => {
const customer = await stripe.customers.create({ email: user.email });
const intent = await stripe.setupIntents.create({
customer: customer.id,
});
await admin.firestore().collection('users').doc(user.email).set({
customer_id: customer.id,
setup_secret: intent.client_secret
});
return;
});
exports.createStripePaymentSA = functions
.region('southamerica-east1')
.firestore
.document('users/{userId}/payments/{pushId}')
.onCreate(async (snap, context) => {
const { amount, payment_method } = snap.data();
try {
// Look up the Stripe customer id.
const customer = (await snap.ref.parent.parent.get()).data().customer_id;
const setup_secret = (await snap.ref.parent.parent.get()).data().setup_secret;
const { setupIntent, error } = await stripe.confirmCardSetup(
await setup_secret,
{
payment_method
}
);
if (error) {
await snap.ref.set({"confirmCardSetupError": 1});
return;
}
// Create a charge using the pushId as the idempotency key
// to protect against double charges.
const idempotencyKey = context.params.pushId;
const payment = await stripe.paymentIntents.create(
{
amount: amount,
currency: 'BRL',
customer: customer,
payment_method: setupIntent.payment_method,
off_session: false,
confirm: true,
confirmation_method: 'manual',
},
{ idempotencyKey }
);
// If the result is successful, write it back to the database.
await snap.ref.set(payment);
//CREAT THE COLLECTION OF PAID ITEMS
await snap.ref.parent.parent.collection("wantedCourses").map(function (course) {
return course.set("paid", 1);
})
} catch (error) {
// We want to capture errors and render them in a user-friendly way, while
// still logging an exception with StackDriver
await snap.ref.set({ error: userFacingMessage(error) }, { merge: true });
// await reportError(error, { user: context.params.userId });
}
});
exports.confirmStripePaymentSA = functions
.region('southamerica-east1')
.firestore
.document('stripe_customers/{userId}/payments/{pushId}')
.onUpdate(async (change, context) => {
if (change.after.data().status === 'requires_confirmation') {
const payment = await stripe.paymentIntents.confirm(
change.after.data().id
);
change.after.ref.set(payment);
}
});
function userFacingMessage(error) {
return error.type
? error.message
: 'An error occurred, developers have been alerted';
}

firebase cloud function snapshot undefined

Im trying to write a function with firebase cloud function which will send an email as soon as a new message is added to my "contactMessages" realtime database. so i did this but here i got an undefined snapshot :
const functions = require("firebase-functions");
const nodemailer = require("nodemailer");
const gmailEmail =
encodeURIComponent(functions.config().gmail.email);
const gmailPassword =
encodeURIComponent(functions.config().gmail.password);
const mailTransport = nodemailer.createTransport(
`smtps://${gmailEmail}:${gmailPassword}#smtp.gmail.com`
);
exports.sendContactMessage = functions.database
.ref("/contactMessages/{pushKey}")
.onWrite((change, context) => {
// Only send email for new messages.
if (snapshot.previous.val() || !snapshot.val().name) {
return;
}
const val = snapshot.val();
const mailOptions = {
to: "test#example.com",
subject: `Information Request from ${val.name}`,
html: val.html
};
return mailTransport.sendMail(mailOptions).then(() => {
return console.log("Mail sent to: test#example.com");
});
});
Change this:
exports.sendContactMessage = functions.database
.ref("/contactMessages/{pushKey}")
.onWrite((change, context) => {
// Only send email for new messages.
if (snapshot.previous.val() || !snapshot.val().name) {
return;
}
into this:
exports.sendContactMessage = functions.database
.ref("/contactMessages/{pushKey}")
.onWrite((change, context) => {
// Only send email for new messages.
if (change.before.val() || !change.after.val().name) {
return;
}
From the docs:
For onWrite and onUpdate events, the change parameter has before and after fields. Each of these is a DataSnapshot with the same methods available in admin.database.DataSnapshot.

Firebase: Cloud Firestore trigger not working for FCM

I wrote this to detect a docment change,when it changes i want to send notifications to all the users who all are inside the Collection "users"
the problem is How to choose all docments inside a collection??
/*eslint-disable */
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification23 = functions.firestore.document("student/anbu").onWrite(event => {
//now i'm returning to my personal document and fetched my username only because i don't want to send a notification to myself,
const fromUser = admin.firestore().collection("users").doc("iamrajesh#gmail.com").get();
//here i want to fetch all documents in the "users" collection
const toUser = admin.firestore().collection("users").document.get();//if i replace "docmument" with "doc("xxxxxxx#gmail.com")" it works it fetches his FCM but how to fetch all documents??
//All documents has a "username",and a fcm "token"
return Promise.all([fromUser, toUser]).then(result => {
const fromUserName = result[0].data().userName;
const toUserName = result[1].data().userName;
const tokenId = result[1].data().tokenId;
const notificationContent = {
notification: {
title: fromUserName + " is shopping",
body: toUserName,
icon: "default",
sound : "default"
}
};
return admin.messaging().sendToDevice(tokenId, notificationContent).then(result => {
console.log("Notification sent!");
//admin.firestore().collection("notifications").doc(userEmail).collection("userNotifications").doc(notificationId).delete();
});
});
});
The following should do the trick.
See the explanations within the code
/*eslint-disable */
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification23 = functions.firestore.document("student/anbu").onWrite((change, context) => {
// Note the syntax has change to Cloud Function v1.+ version (see https://firebase.google.com/docs/functions/beta-v1-diff?0#cloud-firestore)
const promises = [];
let fromUserName = "";
let fromUserId = "";
return admin.firestore().collection("users").doc("iamrajesh#gmail.com").get()
.then(doc => {
if (doc.exists) {
console.log("Document data:", doc.data());
fromUserName = doc.data().userName;
fromUserId = doc.id;
return admin.firestore().collection("users").get();
} else {
throw new Error("No sender document!");
//the error is goinf to be catched by the catch method at the end of the promise chaining
}
})
.then(querySnapshot => {
querySnapshot.forEach(function(doc) {
if (doc.id != fromUserId) { //Here we avoid sending a notification to yourself
const toUserName = doc.data().userName;
const tokenId = doc.data().tokenId;
const notificationContent = {
notification: {
title: fromUserName + " is shopping",
body: toUserName,
icon: "default",
sound : "default"
}
};
promises.push(admin.messaging().sendToDevice(tokenId, notificationContent));
}
});
return Promise.all(promises);
})
.then(results => {
console.log("All notifications sent!");
return true;
})
.catch(error => {
console.log(error);
return false;
});
});

Cant send push in firebase .sendToDevice()

I'm simply trying to make a web push notifications work but I cant seem to get past the .sendToDevice() method, it runs but I dont receive any push notifications. Can someone please tell/show me what im doing wrong here...
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotifications = functions.database.ref('/notifications/{notificationId}')
.onWrite((change, context) => {
console.info("Running..");
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
// Grab the current value of what was written to the Realtime Database.
const NOTIFICATION_KEY = context.params.notificationId
const NOTIFICATION_DATA = change.after.val();
const payload = {
notification: {
title: `New Message from ${NOTIFICATION_DATA.user}!`,
body: NOTIFICATION_DATA.message,
icon: NOTIFICATION_DATA.userProfileImg,
click_action: `https://google.com`
}
};
return admin.database().ref('/tokens').once('value').then((data) => {
if ( !data.val( ) ) return;
const snapshot = data.val();
const tokens = [];
for(let key in snapshot) {
tokens.push( snapshot[key].token);
}
console.info(tokens);
console.info(snapshot);
return admin.messaging().sendToDevice(tokens, payload);
})
});

Firebase Cloud Functions Does not work when used Promise.all

I have an Android app To organize events
I am trying to send a Notification to subscribers about the changes in time or date of the event.
When I used the following example, the function worked fine
//Cloud Functions Modules
const functions = require('firebase-functions');
//Firebase Admin SDK Modules (it will send the Notifications to the user)
const admin = require('firebase-admin');
//init Admin SDK
admin.initializeApp(functions.config().firebase);
exports.changeventTime = functions.database.ref('/user-
event/{authUid}/{key}/eventTime/')
.onWrite(event => {
var eventKey = event.params.key;
var authUid = event.params.authUid;
var eventSnapshot = event.data;
var newTime = eventSnapshot.val();
var eventTopic = "notifications_"+eventKey;
var payload = {
data: {
pushTyp: 'changTime',
time: newTime,
key: eventKey,
authuid: authUid
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(eventTopic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
But when I tried to use "return Promise.all()" The function did not work!
As in the following example:
//Cloud Functions Modules
const functions = require('firebase-functions');
//Firebase Admin SDK Modules (it will send the Notifications to the user)
const admin = require('firebase-admin');
//init Admin SDK
admin.initializeApp(functions.config().firebase);
exports.changeventTime = functions.database.ref('/uesr-
event/{authUid}/{eventKey}/eventTime/')
.onWrite(event => {
const eventKey = event.params.eventKey;
const authUid = event.params.authUid;
const eventTopic = "notifications_"+eventKey;
const eventSnapshot = event.data;
const newTime = eventSnapshot.val();
const getevent = admin.database().ref(`user-event/${authUid}/${eventKey}/`).once('value');
return Promise.all(getevent).then(results => {
const eventSnapshot = results[0];
const eventNumber = eventSnapshot.val().eventNumber;
const eventDescription = eventSnapshot.val().eventDescription;
const eventTime = eventSnapshot.val().eventTime;
const payload = {
data: {
pushTyp: 'changeTime',
time: eventTime,
key: eventKey,
authuid: authUid,
number: eventNumber,
dscr: eventDescription
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(eventTopic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
});

Categories

Resources