I'm currently working with Firebase and React Native I have come to a slight problem.
Reading the documentation for the: createUserWithEmailAndPassword:
On successful creation of the user account, this user will also be signed in to your application.
I was trying to work with the promise as follows:
firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(function(authData){
this.writeUserData(authData.uid);
}).catch(function(error){
console.warn(error)
});
And my writeUserData() method:
writeUserData(the_uid) {
console.warn("Writting data ")
var today = new Date();
firebase.database().ref('users/' + authData.uid + '/').set({
name: this.state.name,
birthday: this.state.date,
email: this.state.email,
registered: today
});
}
In the function however the console.warn is never fired hence the event isn't fired since the user is automatically logged in.
Problem: The .then isn't executed since user is logged in straight away.
Goal: Be able to add the user information (name, birthday, etc) after user creation before sign in.
Okay understood you, the problem seems to be how you define a function in your .then statement. You should be using an Arrow function, like so -
firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((authData) => {
this.writeUserData(authData.uid);
}).catch(function(error){
console.warn(error)
});
what i have understand is that you are trying to push (name ,birthday , etc ) to firebase , well with my little experience using firebase , you have to call {firebase.database().ref().child('your path')} to create a path first , then use the push() , exemple :
{ var ref = firebaseRef.database().ref().child('Clients');
var ref = ref.push(this.state.username); }
well i m newbie , but this worked for me , hope it help you
Related
I have created a function that sets the user ID in the firestore database based on the email adress in the authentication tab of firebase. However, I need it to be a cloud function that triggers upon the first login. I have found documentation that mentioned this functionality, but I can't figure out how I have it trigger only on the first login, not when the user logs in for the second time and also not upon user creation. I have also provided the code below, perhaps it gives a better idea of what I need. Some lines are commented out, so I could test the rest of the code. I have found multiple threads about this topic, but I cant figure out how to exactly manage this.
https://firebase.google.com/docs/functions/auth-events#trigger_a_function_on_user_creation
//Detect first login from user
//if(firebase.auth.UserCredential.isNewUser()){
if(true){
//User is logged in for the first time
//const userID = firebase.auth().currentUser.UID;
//const userEmail = firebase.auth().currentUser.email;
const userID = '1234567890';
const userEmail = 'example#example.com';
var docFound = false;
//Get email, either personal or work
console.log('Taking a snapshot...');
//Test for work email
const snapshot = db.collectionGroup('people').where('email.work', '==', userEmail).get()
.then(function(querySnapshot){
querySnapshot.forEach(function(doc){
//work email found
console.log('work email found');
console.log(doc.data());
docFound = true;
const organisationID = doc.ref.parent.parent.id;
writeUID(doc.id, userID, organisationID);
});
});
if(!docFound){
//Test for personal email
const snapshot = db.collectionGroup('people').where('email.personal', '==', userEmail).get()
.then(function(querySnapshot){
querySnapshot.forEach(function(doc){
//personal email found
console.log('personal email found');
console.log(doc.data());
const organisationID = doc.ref.parent.parent.id;
writeUID(doc.id, userID, organisationID);
});
});
}
}
async function writeUID(doc, uid, organisationID){
const res = db.collection(`organisations/${organisationID}/people`).doc(doc).set({
userId: uid
}, { merge: true });
}
/*
TODO: Detect first login
TODO: Get correct user values
Rest of the function works
*/
Thanks in advance for your help.
I can't figure out how I have it trigger only on the first login, not when the user logs in for the second time and also not upon user creation
What you're trying to do is not possible with Cloud Functions auth triggers.
Auth triggers only work when a user account is created or deleted. They don't trigger when a user signs in. Only your app knows when a user signs in or out - neither Firebase Auth nor Cloud Functions understands your specific definition of what a "first sign in" actually means. What you will have to do is detect your "first sign in" in your app code, then possibly call a function (HTTP or callable) to do some work on behalf of the user.
My use case is that I want to ask newly signed up users to enrich basic info like their names.
So I was hoping to do it like:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
if (some indicator tells me it is newly signed up user)
{redirect to a form to fill in more info}
} else {
// No user is signed in.
}
});
I checked the doc, and could not find anything related to this...
Thanks for the help in advance.
Since version 4.6.0: https://firebase.google.com/support/release-notes/js#4.6.0
You can get if a user is new or existing in 2 ways:
If you are getting back a UserCredential result, check result.additionalUserInfo.isNewUser
Check firebase.auth().currentUser.metadata.creationTime === firebase.auth().currentUser.metadata.lastSignInTime
Previously you had to do that on your own and keep track of the user using Firebase Realtime Database. When a user signs in, you check if a user with the specified uid exists in the database or not. If the user was not found, it is a new user, you can then add the user to the database. If the user is already in the database then this is a returning existing user. Here is an example in iOS.
Handing Firebase + Facebook login process
Example for using result.additionalUserInfo.isNewUser:
firebase.auth().signInWithPopup(provider).then((result) => {
console.log(result.additionalUserInfo.isNewUser);
});
One thing you can do is do things in the callback function of the signup function, the signup function do return a promise. You can do something like this:
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function(user) {
//I believe the user variable here is the same as firebase.auth().currentUser
//take the user to some form you want them to fill
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
However, I don't really recommend doing it this way because the client side code can be unreliable. Think about what if a user suddenly disconnect before they can fill the form. Their data will be incomplete in your database. So if you do it this way, do set a flag in your user's profile when they submit the form so that you know who filled detailed information and who didn't.
Another better way to do this is using firebase cloud functions. You can have code like this in your cloud functions. Cloud functions are written in node.js so you don't need to spend time on another language.
exports.someoneSignedUp = functions.auth.user().onCreate(event => {
// you can send them a cloud function to lead them to the detail information form
//or you can send them an welcome email which will also lead them to where you want them to fill detailed information
});
This way is much better because you can safely assume that your cloud functions server will never be down or compromised. For more information about cloud functions you can refer to their doc: https://firebase.google.com/docs/functions/auth-events
You can check the sign-in methods the user has (if any). If there are none, it is a new user.
// Fetch sign in methods (if any)
Auth.auth().fetchSignInMethods(forEmail: userEmail!) { [self] signInMethodsArray, error in
// Check for error and alert user accordingly
if let error = error {
// handle errors
}
// Email accepted.
// Check if new or returning user.
else {
if (signInMethodsArray == nil) {
// New User
}
else {
// Returning User
}
}
}
This is Swift (iOS) code, but the concept is the same across languages.
My use case is that I want to ask newly signed up users to enrich basic info like their names.
So I was hoping to do it like:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
if (some indicator tells me it is newly signed up user)
{redirect to a form to fill in more info}
} else {
// No user is signed in.
}
});
I checked the doc, and could not find anything related to this...
Thanks for the help in advance.
Since version 4.6.0: https://firebase.google.com/support/release-notes/js#4.6.0
You can get if a user is new or existing in 2 ways:
If you are getting back a UserCredential result, check result.additionalUserInfo.isNewUser
Check firebase.auth().currentUser.metadata.creationTime === firebase.auth().currentUser.metadata.lastSignInTime
Previously you had to do that on your own and keep track of the user using Firebase Realtime Database. When a user signs in, you check if a user with the specified uid exists in the database or not. If the user was not found, it is a new user, you can then add the user to the database. If the user is already in the database then this is a returning existing user. Here is an example in iOS.
Handing Firebase + Facebook login process
Example for using result.additionalUserInfo.isNewUser:
firebase.auth().signInWithPopup(provider).then((result) => {
console.log(result.additionalUserInfo.isNewUser);
});
One thing you can do is do things in the callback function of the signup function, the signup function do return a promise. You can do something like this:
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function(user) {
//I believe the user variable here is the same as firebase.auth().currentUser
//take the user to some form you want them to fill
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
However, I don't really recommend doing it this way because the client side code can be unreliable. Think about what if a user suddenly disconnect before they can fill the form. Their data will be incomplete in your database. So if you do it this way, do set a flag in your user's profile when they submit the form so that you know who filled detailed information and who didn't.
Another better way to do this is using firebase cloud functions. You can have code like this in your cloud functions. Cloud functions are written in node.js so you don't need to spend time on another language.
exports.someoneSignedUp = functions.auth.user().onCreate(event => {
// you can send them a cloud function to lead them to the detail information form
//or you can send them an welcome email which will also lead them to where you want them to fill detailed information
});
This way is much better because you can safely assume that your cloud functions server will never be down or compromised. For more information about cloud functions you can refer to their doc: https://firebase.google.com/docs/functions/auth-events
You can check the sign-in methods the user has (if any). If there are none, it is a new user.
// Fetch sign in methods (if any)
Auth.auth().fetchSignInMethods(forEmail: userEmail!) { [self] signInMethodsArray, error in
// Check for error and alert user accordingly
if let error = error {
// handle errors
}
// Email accepted.
// Check if new or returning user.
else {
if (signInMethodsArray == nil) {
// New User
}
else {
// Returning User
}
}
}
This is Swift (iOS) code, but the concept is the same across languages.
In my javascript code I ask user to subscribe for website notifications using OnceSignal service, so I do:
OneSignal.registerForPushNotifications();
Then I'm trying to catch PlayerId of subscribed user with the following:
OneSignal.push(function() {
OneSignal.on('notificationPermissionChange', function(permissionChange) {
var currentPermission = permissionChange.to;
if (currentPermission == "granted") {
OneSignal.getUserId(function(userId) {
console.log(userId);
});
}
});
Then I get that userId and store it in my mysql database so I can send notifications later. But for some reason that userId is different from PlayerId stored on OneSignal Server while the format is the same. Are UserId and PlayerId different things? If it is so, how can I get PlayerId after user subscribes for Pushes?
Most likely you're seeing an old user ID. The notificationPermissionChange event occurs too early to obtain the user's ID. The event is for analytics only, and if you want to find the user's ID after subscription, use the subscriptionChange event.
SDK Docs Link: https://documentation.onesignal.com/docs/web-push-sdk
The below used to work nicely, however of late, haven't been able to get the player id at all when binding to the "subscriptionChange" event.
Infact, in the event listener, nothing after "OneSignal.push" executes.
Tried removing it and went straight to " OneSignal.getUserId", however seems the promise returns nothing.
OneSignal.on('subscriptionChange', function (isSubscribed) {
console.log('is subscribed', isSubscribed);
OneSignal.push(function() {
console.log('attempt to get id'); // doesn't get this far
OneSignal.getUserId(function(userId) {
console.log('user id', userId); // doesn't get this far
});
});
});
Strange thing is, can get the player id fine if you paste this into the console, only during the callback is nothing returned.
OneSignal.getUserId(function(userId) {
console.log('user id', userId);
});
Seems really weird why the code has just stopped working as we where using this exact code for over a year.
Any suggestions?
Hello this is how I got it done with js
Greetings, I hope it works for you.
window.plugins.OneSignal
.addSubscriptionObserver(function(state){
var datos = JSON.stringify(state);
var valor = JSON.parse(datos);
var playerId = valor.to.userId
console.log( playerId + ' *_IF_**PLAYER ID***' )
});
Disclaimer, I am trying to self-teach myself development. I am building a hybrid mobile app using Ionic 1 and now Firebase 3 for my database and authentication.
For my scenario, in short, I'm trying to display a list of 'friends' for the user that is currently logged in. Here is the current data structure I have (the relevant part anyway):
Data Structure
I have a line of code that does return me what I want:
var friends = $firebaseArray(ref.child('users').child('-KXcxMXkKs46Xv4-JUgW').child('friends'));
Of course, that can't work because there is a nice little hard coded value in there.
So, I looked into how to retrieve the current UID so I could replace the hard coded value. But after running the following bit of code through, the first node under user is not the UID (it is some other auto generated value that I don't really know how it got there). The UID is actually within the id field.
var ref = firebase.database().ref();
authObj = $firebaseAuth();
var firebaseUser = authObj.$getAuth();
console.log(firebaseUser.uid);
So, ultimately what I would love is to be able to change the data structure so that the UID is the first node under Users, but I can't seem to find documentation to do that. I looked at this other stack thread, but it is for an outdated version and I can't seem to connect the dots. Other thread
Though, if I can't change the structure, I still need to figure out how to access that friends node for the current user, one way or another.
Thank you in advance. This is my first stackoverflow post, so be gentle.
Update:
Per Frank's comment, this is the code that I execute to create users - $add is what is creating the push id (-KXcxM...).
createProfile: function(uid, user) {
var profile = {
id: uid,
email: user.email,
registered_in: Date()
// a number of other things
};
var messagesRef = $firebaseArray(firebase.database().ref().child("users"));
messagesRef.$add(profile);
},
register: function(user) {
return auth.$createUserWithEmailAndPassword(user.email, user.password)
.then(function(firebaseUser) {
console.log("User created with uid: " + firebaseUser.uid);
Auth.createProfile(firebaseUser.uid, user);
Utils.alertshow("Success!","Your user has been registered.");
})
.catch(function(error) {
Utils.alertshow("Error.","Some helpful error message.");
console.log("Error: " + error);
});
}
Instead of creating a $firebaseArray and calling $add on it, you can just store the user using the regular Firebase JavaScript SDK:
createProfile: function(uid, user) {
var profile = {
id: uid,
email: user.email
};
firebase.database().ref().child("users").child(uid).set(profile);
}
Since AngularFire is built on top of the Firebase JavaScript SDK, the two interact nicely with each other. So if you have any existing $firebaseArray on users it will pick up the new profile too.