Firebase web realtime database stiring user id as undefined - javascript

I have a create user and login authentication setup with firebase realtime database. I have a user field in my database where I will store user data. However, I would like to create a child element under the user field that is the user id then the user information can be displayed under that child.
So far I have tried to create such a field with this:
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.13.0/firebase-app.js";
import { getDatabase, set, ref, update } from "https://www.gstatic.com/firebasejs/9.13.0/firebase-database.js";
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, signOut} from "https://www.gstatic.com/firebasejs/9.13.0/firebase-auth.js";
//Signup section
signup.addEventListener('click',(e) => {
var username = document.getElementById('signup-user').value;
var email = document.getElementById('signup-email').value;
var schoolID = document.getElementById('signup-id').value;
var password = document.getElementById('signup-pwd').value;
createUserWithEmailAndPassword(auth, email, password, schoolID)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
update(ref(database, "user/" +user.id),{
username: username,
schoolID: schoolID,
email: email
})
alert('User Created!');
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
alert('Error please try again');
// ..
});
});
But it only gives me an undefined field in my realtime database:
Not only that but it overwrites the previous entry every time a make an new user.

userCredential.user is a User type object, which is a subclass of UserInfo. As you can see from the linked API documentation, User doesn't have an property called id. It will always be undefined.
What you want instead is uid.
update(ref(database, "user/" + user.uid), {...})

Related

Firebase Authentication with FullName

I am trying to register user with createUserWithEmailAndPassword function, which logically receives only email and password. But I want also to write fullname field of user. Can you tell me what is the way of doing this? Thanks
But I want also to write fullname field of user.
I make the assumption that you want to update the displayName property of the user Object.
Do as follows, by using the updateProfile() method:
firebase.auth().createUserWithEmailAndPassword(email, password)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
return user.updateProfile({displayName: "Your name"});
})
.then(() => {
console.log("Profile updated successfully!");
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
// ..
});

How to add a user to Firestore database after signing up through Firebase Authentication?

Upon sign up, I want to add a user to a "users" collection using the corresponding userID. Under this userID would be the user's data, such as name, email, posts, etc...
Here is my code:
I get no errors, and the user is created and is visible in firebase auth. However the user is not added to the firestore database.
firebase.initializeApp(config);
const auth = firebase.auth();
const db = firebase.firestore();
auth.createUserWithEmailAndPassword(email, pass).then(cred => {
const userId = cred.user.uid;
const userData = {
firstName: firstName,
lastName: lastName,
email: email
};
db.collection("users").doc(userId).set(userData).then(() => {
console.log("User successfully added to the DB!");
})
.catch((e) => {
console.log("Error adding user to the DB: ", e);
});
}).then(() => {
console.log('User created! - ' + email);
}).catch(e => {
console.log(e.message);
txtErrMsg.classList.remove('hide');
txtErrMsg.innerHTML = e.message;
});
It just seems like I am not able call the DB inside of the auth.createUserWithEmailAndPassword(email, pass) function. If I put the db.collection("users").doc(userId).set(userData) call with some dummy data outside of the auth.createUserWithEmailAndPassword(email, pass) function, then the data appears in the firestore DB.
FYI: I have console logged the parameters (userId and userData), and they appear as expected.

Creating Firebase User and simultaneously adding data into database

I want to have my create users to be added into my database by their user uid when i sign them up from my firebase.
currently my code is working , just i dont understand why when my data is save into my firebase, the name (which is suppose to be the created user uid) shows "undefined". but the data that is grabbed and saved is correct.
My firebase database which shows undefined: https://imgur.com/ATRsmKe
My JS code which i am trying to save and create user:
/*Show Login User*/
// Firebase Variables
var auth = firebase.auth();
$(document).ready(function () {
//Pass parameter from form to Firebase
$('.addpic').on('submit', event => {
event.preventDefault();
const name = $('#name').val();
const hp = $('#hp').val();
const email = $('#email').val();
const password = $('#password').val();
const role = $('#role').val();
//Firebase user authentication
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(user => {
//set data into User database
firebase.database().ref('Admin/Person In Charge' + "/" + user.uid).set({
Name: name,
ContactNo: hp,
Email: email,
Password: password,
Role: role
}).then(success => {
console.log(user);
window.alert("Registered");
window.location = "user.html";
});
})
.catch(function (error) {
var errorCode = error.code;
var errorMessage = error.message;
window.alert("Error : " + errorMessage);
});
});
});
I want my data to be saved under the UID of the created user. I tried all possible solutions, but none work for me.
You should take a look at the return type of createUserWithEmailAndPassword. If I'm reading the docs correctly, it returns an instance of firebase.auth.UserCredential, not an actual user. I think you need to actually drill down one more level into that credential object and get the user.uid.
Example
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(userCredential => {
//set data into User database
firebase.database().ref('Admin/Person In Charge' + "/" + userCredential.user.uid).set({
Name: name,
ContactNo: hp,
Email: email,
Role: role
}).then(success => {
console.log(user);
window.alert("Registered");
window.location = "user.html";
});
})
You could figure this out in the future by inspecting the value of your user in your then via a console.log().

Firebase Document for each user?

I am wondering how to make a document for each user as they create their account (with Firebase Web). I have Firebase Authentication enabled and working, and I'd like each user then to have a document in Cloud Firestore in a collection named users. How would I get the UID and then automatically create a document for each user? (I am doing this so that calendar events can be saved into an array field in the document, but I need a document for the user to start with). I am aware and know how to make security rules for access, I just don't know how to make the document in the first place.
Thanks!
While it is definitely possible to create a user profile document through Cloud Functions, as Renaud and guillefd suggest, also consider creating the document directly from your application code. The approach is fairly similar, e.g. if you're using email+password sign-in:
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(function(user) {
// get user data from the auth trigger
const userUid = user.uid; // The UID of the user.
const email = user.email; // The email of the user.
const displayName = user.displayName; // The display name of the user.
// set account doc
const account = {
useruid: userUid,
calendarEvents: []
}
firebase.firestore().collection('accounts').doc(userUid).set(account);
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
Aside from running directly from the web app, this code also creates the document with the user's UID as the key, which makes subsequent lookups a bit simpler.
You´ll have to set a firebase function triggered by the onCreate() Auth trigger.
1. create the function trigger
2. get the user created data
3. set the account data.
4. add the account data to the collection.
functions/index.js
// Firebase function
exports.createAccountDocument = functions.auth.user().onCreate((user) => {
// get user data from the auth trigger
const userUid = user.uid; // The UID of the user.
//const email = user.email; // The email of the user.
//const displayName = user.displayName; // The display name of the user.
// set account doc
const account = {
useruid: userUid,
calendarEvents: []
}
// write new doc to collection
return admin.firestore().collection('accounts').add(account);
});
If you are using Firebase UI to simplify your life a lil, you can add a User document to a "/users" collection in Firestore only when that user first signs up by using authResult.additionalUserInfo.isNewUser from the signInSuccessWithAuthResult in your UI config.
I'm doing something like this in my project:
let uiConfig = {
...
callbacks: {
signInSuccessWithAuthResult: (authResult) => {
// this is a new user, add them to the firestore users collection!
if (authResult.additionalUserInfo.isNewUser) {
db.collection("users")
.doc(authResult.user.uid)
.set({
displayName: authResult.user.displayName,
photoURL: authResult.user.photoURL,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
})
.then(() => {
console.log("User document successfully written!");
})
.catch((error) => {
console.error("Error writing user document: ", error);
});
}
return false;
},
},
...
}
...
ui.start("#firebaseui-auth-container", uiConfig);
The signInSuccessWithAuthResult gives you an authResult and a redirectUrl.
from the Firebase UI Web Github README:
// ...
signInSuccessWithAuthResult: function(authResult, redirectUrl) {
// If a user signed in with email link, ?showPromo=1234 can be obtained from
// window.location.href.
// ...
return false;
}

Firebase user.updateProfile({...}) not working in React App

So, I have this ReactJS app, there is a user database,
The function for creating the user is this
import { ref, firebaseAuth } from './../Components/config'
export function auth (email, pw) {
return firebaseAuth().createUserWithEmailAndPassword(email, pw)
.then(saveUser)
}
export function saveUser (user) {
return ref.child(`users/${user.uid}/info`)
.set({
email: user.email,
uid: user.uid,
number: "" //custom
})
.then(() => user)
}
as you see the user is made of 3 properties, email, uid, and a custom number property which initially is "",
I have a
changeNumberToNew = (n) =>{
var user = firebase.auth().currentUser;
if (user != null) {
user.updateProfile({
number: n
}).then(() => {
console.log("Number changer");
}).catch((error) => {
console.log(error);
});
} else {
console.log("No user")
}
};
and a button to call the function
<button onClick={this.changeNumberToNew(4)}>Click to change number</button>
When i click the button the promise is resolver leading to the execution of
console.log("Number changer")
but when I go and look at the firebase database object .. nothing changes, even if a reload and wait still nothing changes
I think the problem here is that you are confusing the user object in your database with the user in your authentication module. They are not the same.
You save a 'copy' of your user to the database when you say the following in the first chunk.
ref.child(`users/${user.uid}/info`)
.set({
email: user.email,
uid: user.uid,
number: ""
})
Then in the second chunk of code you try and update the current user in your authentication module. Not good. You should be updating your database, not your authentication module.
var user = firebase.**auth()**.currentUser
if (user != null) {
user.updateProfile({...})
}
I don't think you can create a custom field on the current User in the authentication module. The updateProfile() is used to update the fields you get by default from the provider, such as email, display name, photoURL etc. You can't create new ones.
You should update the copy of the user in your database and then reference that when you need the value of 'number'.
You change function should probably be more like...
changeNumberToNew = (n) => {
var user = firebase.auth().currentUser;
if (user) {
ref.child(`users/${user.uid}/info`).update({number: n})
.then(() => console.log("Number changer"))
.catch(error => console.log(error))
} else {
console.log("No user")
}
}
Firebase Auth updateProfile only supports displayName and photoURL. It does not support client custom attributes. For admin custom attributes, you would need to use the admin SDK: https://firebase.google.com/docs/auth/admin/custom-claims#set_and_validate_custom_user_claims_via_the_admin_sdk
You are probably better off in this case saving these arbitrary custom fields in the database only (provided they do not require admin privileges).

Categories