Why does my firebase cloud function run multiple times? - javascript

I have written a cloud function for firebase admin. It is to reset a user's password. It passes in the user UID and the new pass, but when I run the function, it not only resets that user's password, it makes that the password for every user. Every single user in the database.
Here is the code that calls the function:
resetForm.addEventListener('submit', (e) => {
e.preventDefault();
let newPass = resetForm['reset-password'].value;
const resetPasswordFunction = firebase.functions().httpsCallable('resetPassword');
resetPasswordFunction({docId: docId, newPass: newPass}).then(() => {
const modal = document.querySelector('#modal-reset');
M.Modal.getInstance(modal).close();
resetForm.reset();
});
});
and here is the function:
var functions = require('firebase-functions');
var admin = require("firebase-admin");
var serviceAccount = require("./troop-30-elections-web-app-firebase-adminsdk-obsmr-61cc4bb59e.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://troop-30-elections-web-app.firebaseio.com"
});
exports.resetPassword = functions.https.onCall((data) => {
return admin.auth().updateUser(data.docId, {
password: data.newPass
})
.then(() => {
return {"text": "User Password Successfully Updated"}; // this is what gets sent back to the app
});
});

Related

Firebase writing data with variable via REST

in my app I am getting the uid of the current user by:
also I get the username from :
console.log gives me the right name.
But when I try to write to my db via:
https://movieapp-8a157.firebaseio.com/users/${username}/${authUser}/posts.json?auth=${token}
It doesnt work. If I remove the ${username} it will write in the correct path. Any ideas? I edited my post for more clearness.
export const postJob = data => {
return async (dispatch, getState) => {
const randomColors = ["#f3a683"];
const colorNumber = Math.floor(Math.random() * 20) + 1;
const bgColor = randomColors[colorNumber];
const val = getState();
const userId = val.auth.userId;
const rules = {
description: "required|min:2"
};
const messages = {
required: field => `${field} is required`,
"description.min": "job description is too short"
};
try {
await validateAll(data, rules, messages);
const token = await firebase
.auth()
.currentUser.getIdToken(true)
.then(function(idToken) {
return idToken;
});
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
// ...
} else {
// User is signed out.
// ...
}
});
var user = firebase.auth().currentUser;
const authUser = user.uid;
const username = await firebase
.database()
.ref("users/" + authUser + "/name")
.once("value", function(snapshot) {
console.log("################", snapshot.val());
});
//console.log("#####################", authUser);
const response = await fetch(
`https://movieapp-8a157.firebaseio.com/users/${username}/${authUser}/posts.json?auth=${token}`,
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
titel: data.titel,
fname: data.fname,
description: data.description,
cover: data.cover,
friend: data.friend,
ownerId: userId,
bgColor: bgColor
})
}
);
const resData = await response.json();
Your code that's getting the UID isn't working the way you exepct. The auth state listener is asynchronous and is triggering after the line of code that accessesfirebase.auth().currentUser. That line of code is actually giving you the current user before the sign-in completes. That means it's going to be undefined.
You're then using that undefined value to build a reference to a location in the database. This is causing the actual reference to be something other than what you expect. You should add debug logging to see this yourself.
You should be using the callback to determine when exactly the user is signed in, and only read and write that user's location. This means that you should probably move the lines of code that write the database into the callback, when you know that user is correct, and use user.uid to build the database reference for reading and writing.

DisplayName not being set when using Firebase

I am trying to get Firebase to assign users a name based off of what they put into a field. However it appears that the name isnt being updated doesnt do anything.
btnSignUp.addEventListener('click', e => {
//Get Email and Password
const acEmail = email.value;
const acPass = password.value;
const acName = name.value;
const auth = firebase.auth();
//Sign Up
const promise = auth.createUserWithEmailAndPassword(acEmail, acPass);
promise.catch(e => console.log(e.message));
then(function(user) {
user.updateProfile({
displayName: acName
})
}).catch(function(error) {
console.log(error);
});
});
Any help is Appreciated!

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.

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

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);
});
});
});

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