Send data to firebase cloud function - firebase

I'm using firebase cloud function to add users to my database after they register.
I want to add (when user is created) a nickname for example.
In the register form, there is a box for nickname, but how can I send it the firebase function so it would be added to the user in the database?
This is firebase function:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const ref = admin.database().ref()
exports.createUserAccount = functions.auth.user().onCreate(event=>{
const uid = event.data.uid
const email = event.data.email
const photoUrl = event.data.photoUrl || 'https://vignette1.wikia.nocookie.net/paulblartmallcop/images/9/9c/Person-placeholder-male.jpg/revision/latest?cb=20120708210100'
const newUserRef = ref.child(`/users/${uid}`)
return newUserRef.set({
photoUrl: photoUrl,
email: email,
})
});
The register form is in another file (register.js), how can I send data from there to the function?
I do not call createUserAccount anywhere, it is triggered when this function happens:
handlePress = (navigation)=>{
if(this.state.password == this.state.verify){
firebaseRef.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).then((newUser)=>{
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Home'})
]
})
navigation.dispatch(resetAction)
}).catch(function(error){
console.log(error);
});
}else{
//password not match, show error.
}
}
Thanks in advance!

You don't have to use a firebase cloud function to add a nickname to the user (If the user is already created).
Just call from your js :
ref.child("users").child(uid).child("nickname").set(nickname);
Other solution
You can create the user only when the nickname is filled. You can save it in the user.displayName and access to it from your onCreate trigger.
exports.createUserAccount = functions.auth.user().onCreate(event=>{
const user = event.data; // The Firebase user.
const uid = user.uid;
const email = user.email;
const nickname = user.displayName;
const photoUrl = user.photoUrl || 'https://vignette1.wikia.nocookie.net/paulblartmallcop/images/9/9c/Person-placeholder-male.jpg/revision/latest?cb=20120708210100';
const newUserRef = ref.child('/users/${uid}');
return newUserRef.set({
nickname: nickname,
photoUrl: photoUrl,
email: email
});
});

Related

Flutter Firebase Notify Admin On New Request

I am learning flutter /firebase and trying to explore a functionality where I can get an email on a new document created in a specific collection. Is it possible in flutter or firebase?
Yes, you can use Cloud Firestore Triggers. These Triggers are easy to set up with Cloud Functions
The code below is a function that gets triggered when a new document is created inside an example collection of Users. Once triggered, we can extract the user name and email (that comes from the request to create a new user), and use Nodemailer to send a custom email.
{your_email} and {your_password} represent the email account that is sending this email.
const functions = require('firebase-functions');
import * as nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
priority: 'high',
auth: {
user: '{your_email}',
pass: '{your_password}',
},
});
export const onCreateUserTrigger = functions.firestore
.document('Users/{userId}')
.onWrite((snap, context) => {
const userEmail = snap.data().email;
// this is the email we send to but you can make this any email:
// userEmail = 'admin#gmail.com';
const userName = snap.data().name;
const userId = context.params.userId;
// send a mail
const htmlText = `<p>Hello ${userName}, </p>
<p> This is a notification about... </p>
`;
const mailOptions = {
from: "{your_name} <{your_email}>",
to: userEmail,
subject: "Notification",
html: htmlText,
};
await transporter.sendMail(mailOptions);
});
If you want a function that gets triggered for any write (create and edit) to the Users collection you can change the firestore function to onWrite:
export const onWriteUserTrigger = functions.firestore
.document('Users/{userId}')
.onWrite((snap, context) => {
// send email
});

Displaying user data from Firebase Firestore in React Native within a Text tag

Background
Hey! I'm trying to build a header for the home page of my app. I have succesfully implemented email/password auth with Firebase and also persistent credentials. However, I am unable to fetch data from the firestore collection which stores my users.
Basically, what I need is to have my header display "Hello {userName}", but I have absolutely no clue on how to do that.
My Home Screen is a function component, not a class component, so as far as I know I can't go the "componentDidMount()" way.
Question
Which is the best way to fetch the current user's data and display a specific field of information, such as their first name?
How would I go about rendering that within a <Text> tag? Is it something like <Text> Hello {this.user.firstName}</Text> or am I absolutely wrong?
What I've tried
I know this has something to do with this line of code: const usersRef = firebase.firestore().collection('users') but I've no idea what to follow it up with. Also have tried with this method:
var user = firebase.auth().currentUser;
var firstName, email, photoUrl, uid, emailVerified;
if (user != null) {
firstName = user.firstName;
email = user.email;
photoUrl = user.photoURL;
emailVerified = user.emailVerified;
uid = user.uid;
}
But that doesn't seem to work. On the last example I'm calling firstName like this: <Text>Hello {firstName}</Text>
You are confusing auth with firestore. Firebase auth only provides credentials and the ability to login and does not enter any data into a database (firestore). What you want to do is when a user is registering you want to set a corresponding document in firestore with the users uid (identification) and all of the users custom data (First name, etc).
Here is an example:
const onRegister = async () => {
try {
const credential = await auth.createUserWithEmailAndPassword(
'email#email.com',
'password',
);
const {uid} = credential;
// your data here (dont forget to store the uid on the document)
const user = {
firstName: 'whatever',
lastName: 'whatever',
user_id: uid,
};
await firestore().collection('users').doc(uid).set(user);
} catch {
//do whatever
}
};
and then when you wanna get their data you can access their document and display it:
const [user, setUser] = useState();
const {uid} = auth().currentUser;
const getUser = async () => {
try {
const documentSnapshot = await firestore()
.collection('users')
.doc(uid)
.get();
const userData = documentSnapshot.data();
setUser(userData);
} catch {
//do whatever
}
};
// Get user on mount
useEffect(() => {
getUser();
}, []);
// return info if user is set
return (
<Text>{user && user?.firstName}</Text>
);

Unable to Access Firestore Document Within a Firestore Cloud Function

Issue: Type Error
I setup a Firestore Cloud Function to call from my Android app which is being called as expected, however I am unable to access a Firestore document from within the method and receiving a TypeError in the logs.
Attempted Solutions
functions.firestore().document('qa/content/feeds/main/content/'+contentTitle)
functions.firestore().ref('qa/content/feeds/main/content/'+contentTitle)
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();
const MAIN_FEED_TYPE = "MAIN";
const SAVED_FEED_TYPE = "SAVED";
const ARCHIVED_FEED_TYPE = "ARCHIVED";
const SAVE_USER_ACTION = "SAVE";
const ARCHIVE_USER_ACTION = "ARCHIVE";
const SAVED_PATH = "saved"
const ARCHIVED_PATH = "archived"
exports.updateQualityScore = functions.https.onCall((data, context) => {
const environment = data.environment
const feedType = data.feedType
const action = data.action
const contentTitle = data.contentTitle
const uid = context.auth.uid;
var feedTypePath
if (feedType === SAVED_FEED_TYPE) {
feedTypePath = SAVED_PATH
} else if (feedType === ARCHIVED_FEED_TYPE) {
feedTypePath = ARCHIVED_PATH
}
admin.firestore().ref('qa/content/feeds/main/content/'+contentTitle)
.get().then(function(doc) {
console.log('Trigger fired on content: '
+ contentTitle + " | user: " + uid
+ " | action: " + action + ' | feedType: ' + feedType);
if (doc.exists) {
console.log("Document data:", doc.data());
} else {
console.log("No such document!");
}
return {
status: 'Get content success.'
}
}).catch(function(error) {
console.log("Error getting document:", error);
return {
status: 'Get content error.'
}
});
});
Firestore doesn't have a ref() method. Realtime Database does. You're probably confusing the two.
With Firestore, you deal with collections and documents, and there are different methods to get a hold of collection and document references. Maybe you meant to use the doc() method instead, like this?
admin.firestore().doc('qa/content/feeds/main/content/'+contentTitle)
Sorry wrong answer.
You need to pass credential when initializing app.
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
var db = admin.firestore();
or
admin.initializeApp({
credential: admin.credential.cert({
projectId: '<PROJECT_ID>',
clientEmail: 'foo#<PROJECT_ID>.iam.gserviceaccount.com',
privateKey: '-----BEGIN PRIVATE KEY-----\n<KEY>\n-----END PRIVATE KEY-----\n'
}),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});
initialize the sdk
Quick Start

Setting a firestore document when a new user is created with firebase auth using node.js

I'm using firebase cloud functions, firebase auth and firestore.
I've done this before with firebase database but just not sure with firestore how to set a document in the users collection to the uid of a newly created firebase auth user.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore()
exports.createUser = functions.auth.user().onCreate(event => {
const uid = event.data.uid;
console.log(uid);
db.collection('users').doc(uid);
});
The above completes ok in the logs but the uid isn't getting set in the database. Do I need to call set at some stage?
const collection = db.collection("users")
const userID = "12345" // ID after created the user.
collection.doc(userID).set({
name : "userFoo", // some another information for user you could save it here.
uid : userID // you could save the ID as field in document.
}).then(() => {
console.log("done")
})
Note, that the onCreate return has changed, it does return the user now, so event.data.uid isn't valid anymore.
The full function should look something like this, it will create a document with the user's uid in the "users" root-collection.
exports.createUser = functions.auth.user().onCreate((user) => {
const { uid } = user;
const userCollection = db.collection('users');
userCollection.doc(uid).set({
someData: 123,
someMoreData: [1, 2, 3],
});
});

Invalid login on create user event when working with Cloud Functions for Firebase and node mailer

I am using Cloud Functions for Firebase and Nodemailer and putting together code to fire welcome email. Following is the code I have:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
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`);
const APP_NAME = 'Test';
exports.sendWelcomeEmail = functions.auth.user().onCreate(event => {
const user = event.data; // The Firebase user.
const email = user.email; // The email of the user.
const displayName = user.displayName; // The display name of the user.
return sendWelcomeEmail(email, displayName);
});
function sendWelcomeEmail(email, displayName) {
const mailOptions = {
from: '"Test" <noreply#test.com>',
to: email
};
// The user subscribed to the newsletter.
mailOptions.subject = `Welcome to hell!`;
mailOptions.text = `Hey I hope you will enjoy our service.`;
return mailTransport.sendMail(mailOptions).then(() => {
console.log('New welcome email sent to:', email);
});
}
I do have Allow Less secure Apps turned on
I do see my gmail address and password in the config. I have verified this by typing firebase functions:config:get in the command line
I am getting the following error
I solved it just using the correct email address in from: the one you put in the config.
from: '"Test" <youremail#gmail.com>',

Resources