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
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
});
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>
);
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
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],
});
});
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>',