Cant pass uid from created user firebase - reactjs

I cant pass the uid from the newly created user that is created from a firebase cloud function. The user is created successfully but the document in collection of the firestore is not. When i remove the argument from .doc() like this the user is created but with the random generated uid not the one created from the create user ofc. What i would like is to pass the uid from the created user to as the doc name. The uid is available from the response of the createUsr function.
I think i'm not doing something right with the way i'm using the async function.
const handleSubmit = async (values) => {
const createUsr = functions.httpsCallable('createUsr')
try {
await createUsr({ email: values.email }).then((data) => {
const id = data.uid
const newDocRef = db.collection('students').doc(id)
newDocRef.set({
userID: id,
firstName: values.firstName,
lastName: values.lastName,
access_type: "student"
})
})
success()
} catch {
error()
}
}
Data response from the console
Object
data:
disabled: false
displayName: null
email: "test#gmail.com"
emailVerified: false
metadata: {creationTime: "Tue, 06 Apr 2021 19:06:19 GMT", lastSignInTime: null, lastRefreshTime: null}
passwordHash: null
passwordSalt: null
phoneNumber: null
photoURL: null
providerData: []
tenantId: null
tokensValidAfterTime: "Tue, 06 Apr 2021 19:06:19 GMT"
uid: "GHpc2ykVj3RPnMqPDDiDiViVvmc2"
__proto__: Object
__proto__: Object

Try with this:
const handleSubmit = async (values) => {
const createUsr = functions.httpsCallable('createUsr')
try {
createUsr({ email: values.email }).then(({ data }) => {
const { uid } = data;
const newDocRef = db.collection('students').doc(uid);
await newDocRef.set({
userID: uid,
access_type: "student",
...values
});
});
success();
} catch {
error()
}
}

Related

How do I fetch a specific result from mongodb

I'm still new to reactjs and mongodb.I am trying to fetch a single record of user and display it on the page. But so far I got no output. I want the page to immediately display the result on load
This is my profile.js:
componentDidMount() {
const user = localStorage.getItem('user')
const userObject = {
username: localStorage.getItem('user'),
};
axios.post('http://localhost:4000/users/getUser', userObject)
.then((res) => {
console.log("hi"+res.data)
const userinfo = res.data
this.setState({
name: userinfo.name,
username: res.username,
email: res.email,
password: res.password,
company: res.company,
position: res.position
})
})
.catch(function (error) {
console.log(error);
})
}
and this is my backend(user.js):
let mongoose = require('mongoose'),
express = require('express'),
router = express.Router(),
user = require('../models/user-schema');
router.post('/getUser', async (req, res) => {
console.log(req.body.username)
const User = await user.find({ name: req.body.username })
if (!User) {
return { status: 'error', error: 'Invalid Login' }
}else {
return res.json({
status: 'ok',
name: User.name,
username: User.username,
email: User.email,
company:User.company,
position: User.position,
level: User.userLevel
})
}
})
user.find({ name: req.body.username }) is going to return an array. So in the code below, all those fields such User.name , User.username, User.email etc are going to be undefined since User = [{name:xxx,username:xxx }]
res.json({
status: 'ok',
name: User.name, // undefined
username: User.username, // undefined
email: User.email, // undefined
company:User.company, // undefined
position: User.position,// undefined
level: User.userLevel // undefined
})
You should use user.findOne({ name: req.body.username }) which will return a single object and then you can access the properties.
Additionally (Personal preference) , one might have multiple users with the same username. To make sure you're retrieving the correct docuemnt, rather use findById().
Instead of this find({}) you can use findOne({}) cause find({}) going to return an array but your are expecting an object that the the problem
Use findOne() instead of find() method, find() method returns an array of objects and findOne() method return a single particular object.
const User = await user.findOne({ name: req.body.username })
and you can pass specific filed which you want to get like
let User = await user.findOne({ name: req.body.username },{username:1, email:1, company:1, position:1, level:1});
if(!User){
return res.status(404).json({ status: 'error', error: 'Invalid Login' });
} else {
return res.status(404).json({status:"ok", ...User});
}

Getting some problems in database saving

I'm getting problem in my database, I'm using mongoDB with mongoose npm package.
if (!authData) return res.redirect("/login")
const user = await process.oauth.getUser(authData.access_token);
// console.log(user)
let data = await Schema.findOne({
userID: user.id
})
if (!data) {
let e = await Schema.create({
userID: user.id,
})
await e.save()
let dataID = e._id.toString();
e.access_token = authData.access_token;
e.refresh_token = authData.refresh_token;
e.expires_in = authData.expires_in;
let secretAccessKeyy = jwt.sign({
userID: user.id,
uuid: dataID
}, jwtSecret)
/*
e.secretAccessKey = secretAccessKeyy
console.log(secretAccessKeyy)
*/
e.user = {
id: user.id,
username: user.username,
discriminator: user.discriminator,
avatar: user.avatar
};
await e.save()
await Schema.findOneAndUpdate({
userID: user.id
}, {
secretAccessKey: secretAccessKeyy
})
} else {
const id = data._id.toString();
data.access_token = authData.access_token;
data.refresh_token = authData.refresh_token;
data.expires_in = authData.expires_in;
let secretAccessKey = jwt.sign({
userID: user.id,
uuid: id
}, jwtSecret)
data.secretAccessKey = secretAccessKey
console.log(secretAccessKey)
data.user = {
id: user.id,
username: user.username,
discriminator: user.discriminator,
avatar: user.avatar
};
await data.save()
}
I have this code (its only data part not full code), it should check If there is data then overwrite data with new values other wise create a document, save It then again overwrite that document with new Objects then save.
Problems I'm Getting:
When I'm logging data its returning null but the data actually exists in database
the secretAccessKey is not saving in database
Would appreciate some help.
Thanks!

adding users to firestore with the same uid that it was created with

I am trying to add new users to firestore with the same uid, when they are creatd with createUserWithEmailAndPassword. however I can add users to my user collection, but the id its given is not the same id as the uid. this is how I do it:
const auth = getAuth(db);
const app = getFirestore();
const handleSubmit = useCallback(
async (event) => {
event.preventDefault();
const { email, password, fname, lname } = event.target.elements;
// console.log("clicked", email.value, password.value);
const auth = getAuth(db);
const app = getFirestore();
createUserWithEmailAndPassword(auth, email.value, password.value)
.then(async (userCredential) => {
// Signed in
const user = userCredential.user;
try {
const docRef = await addDoc(collection(app, "users"), {
firstName: fname.value,
lastName: lname.value,
email: email.value,
age: 0,
bday: "",
});
console.log("Document written with ID: ", docRef.id);
} catch (e) {
console.error("Error adding document: ", e);
}
//=================
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
});
},
[history]
);
the ref id it a different id than my uid.
what do I have to do to make it save the user with the same id.
also I have tried this
app.collection("users")
doc(user.uid)
.set({...})
but this generates an error!
If you check the Web version 9 (modular) code sample in the documentation on setting a document, you'll see that setting the document goes like this:
import { doc, setDoc } from "firebase/firestore";
// Add a new document in collection "cities"
await setDoc(doc(db, "cities", "LA"), {
name: "Los Angeles",
state: "CA",
country: "USA"
});
So in your scenario, that'd be:
const docRef = doc(app, "users", user.uid)
await setDoc(docRef, {
firstName: fname.value,
lastName: lname.value,
email: email.value,
age: 0,
bday: "",
});

How to add async functionality to a Firebase 'put' and 'set' query operation

I have been using the following function to store a file in Firebase Storage, return the URL, which I then store along with some other fields, in Firestore.
Where do I add an 'await' or how do I add a promise so that the 'history.push("/") is not called until all operations have completed? At the moment I think it's pushing me on to the next page before it's finished.
async function handleSubmit(e) {
e.preventDefault()
const collectionRef = useFireStore.collection('users').doc(`${currentUser.uid}`);
const storageRef = useStorage.ref("avatars")
const fileRef = storageRef.child(`${uuidv4()}`)
fileRef.put(file).then(() => {
fileRef.getDownloadURL().then(function (url) {
collectionRef.set({
createdAt: timestamp(),
email: currentUser.email,
userid: currentUser.uid,
username: username,
firstname: firstname,
lastname: lastname,
avatar: url
})
});
})
history.push("/")
}
What would be some best-practices here, please?
Kind regards, Matt
You can do something like this,
async function handleSubmit(e) {
e.preventDefault()
const collectionRef = useFireStore.collection('users').doc(`${currentUser.uid}`);
const storageRef = useStorage.ref("avatars")
const fileRef = storageRef.child(`${uuidv4()}`)
await fileRef.put(file);
const url = await fileRef.getDownloadURL();
await collectionRef.set({
createdAt: timestamp(),
email: currentUser.email,
userid: currentUser.uid,
username: username,
firstname: firstname,
lastname: lastname,
avatar: url
});
history.push("/")
}
Refer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

React+Firebase. Write to Database after Authentication

I'm currently setting up Firebase for my React Native app. Authentication & basic writing/reading work fine.
Though, I struggle to write data to the database right after the initial authentication because my "signUp" and "writeUserData" functions execute at the same time (and at this moment there is no userId yet).
Here is my code:
...
module.exports = React.createClass({
getInitialState(){
return({
email: '',
password: '',
confirmPassword: '',
result: '',
})
},
signUp() {
if (this.state.password === this.state.confirmPassword) {
let {email, password} = this.state;
firebaseApp.auth().createUserWithEmailAndPassword(email, password)
.catch(error => this.setState({result: error.message
}));
this.writeUserData(email);
} else {
this.setState({result: 'Passwords do not match.'})
}
},
writeUserData(email) {
let userId = firebaseApp.auth().currentUser.uid;
firebase.database().ref('users/' + userId + '/').set({
info: {
firstName: 'Jonas',
email: email,
},
currentState: {
currentDay: 0,
currentSeries: 0,
}
});
},
render() {
...
I can't find any good documentation about this. Can someone give me a pointer?
Thanks!
The createUserWithEmailAndPassword() method returns Promise, you have to use it's .then for updating the user details, like this:
firebaseApp.auth()
.createUserWithEmailAndPassword(email, password)
.then( user => {
user.updateProfile({
displayName: 'Jonas'
});
user.updateEmail(email);
})
.catch(error => this.setState({result: error.message}));
Note also the appropriate way to update user' email
I found the solution within Stack Overflow. Much easier than expected: How do you include a username when storing email and password using Firebase (BaaS) in an Android app?
EDIT: I'm using now the onAuthStateChangedmethod instead.
componentDidMount() {
firebaseApp.auth().onAuthStateChanged(user => {
if(user) {
this.writeUserData(user.uid, user.email, this.state.firstName);
}
})
},
writeUserData(userId, email, firstName) {
firebase.database().ref('users/' + userId + '/').set({
info: {
firstName: firstName,
email: email,
},
currentState: {
currentDay: 0,
currentSeries: 0,
}
});
},

Resources