How do I fetch a specific result from mongodb - reactjs

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});
}

Related

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!

How can I properly handle request errors with React front end?

Currently I have my backend set up as such on the '/register' route:
registerRouter.post('/', async (req, res) => {
// Validate submitted registration form
const { error } = registerValidation(req.body)
if(error) {
return res.status(400).send(error.details[0].message)
}
try {
// Check if email exists already
const user = await User.findOne({ email: req.body.email })
if(user) {
return res.status(400).send('Email already exists')
}
// If not, begin registering user by hashing the password
const hashedPassword = await bcrypt.hash(req.body.password, 10)
const newUser = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: hashedPassword
})
const savedUser = await newUser.save()
res.send(savedUser)
} catch(error) {
res.sendStatus(500)
}
})
Using Postman I get the proper responses when I make correct/incorrect requests. But when I make requests on my frontend, if it is an incorrect request, e.g. not long enough password, missing a required field, then I just get a 400 response. How can I use the error response to, for example, display the error on-screen for the user to see?
This is my current onSubmit function for the form:
const register = async event => {
event.preventDefault()
axios
.post('/register', newUser)
.then(res => console.log(res))
.catch(err => console.log(err))
}
try to use:
axios
.post('/register', newUser)
.catch(function (error) {
console.log(error.toJSON()); // or maybe exist .toText()
});
(https://github.com/axios/axios#handling-errors)
also convert it on server side:
return res.status(400).send('Email already exists')
to
return res.status(400).send({ error: 'Email already exists' });

Find subdocument object in another db

I'm trying to check each email of attendees and see if they are a registered user. If not, I will send them an email (not yet coded, will do later).
Here's the event and user schema:
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
const Event = new Schema({
title: {
type: String,
required: true
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'users'
},
attendees:[
{email: {
type: String,
required: true
},
name: {
type: String,
required: true
},
status: {
type: String
}}
]
});
router.post('/', auth, async (req, res) => {
const {title,
attendees
} = req.body
if (!title) {
return res.status(400).json({ msg: 'Please enter a title' });
}
try{
const newEvent = new Event({
title,
user: req.user.id,
attendees: attendees.map(x => ({
email: x.email,
name: x.name,
status: x.status,
})),
});
const attendeeExists = await User.findOne({"attendees.email":email});
if (!attendeeExists) throw Error("User doesn't exist. Send email");
The last two lines are giving me an error: email is not defined.
Not sure what I'm missing.
This works in the user routes:
const user = await User.findOne({ email });
Thanks #ambianBeing, your solution helped me get a working model.
const email = attendees.map((a) => a.email);
const attendeesFound = await User.find({email});
For checking any of the attendee's email found, .find() with $in can be used which'll return the users found with any of the email ids.
/*collect all emails to test*/
const emails = attendees.map((a) => a.email);
const attendeesFound = await User.find({ "email": { $in: emails } });
Another Mongoose syntax wihich does the same thing as above:
/*collect all emails to test*/
const emails = attendees.map((a) => a.email);
const attendeesFound = await User.find({}).where("email").in(emails);

Save user info into database just after registration in Firebase

I am trying to save a newly created user's info into Firestore using the uid as the document id. The problem I encounter comes after the creation of the user, in order to save his information into the Firestore collection after creation.
Here is what I have already tried:
const usersRef = firebase.firestore().collection('Users');
firebase.auth().createUserWithEmailAndPassword(values.email, values.password).then(function(user){
usersRef.doc(`${user.uid}`).set({
firstName: values.firstName,
lastName: values.lastName,
username: values.username,
uid: user.uid
})
}).catch(function(error){
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode == 'auth/weak-password') {
alert('The password is too weak.');
} else {
alert(errorMessage);
}
console.log(error);
// [END_EXCLUDE]
});
The code is expected to save the user's info after creation, but it causes the following error :
The collection document ID cannot be undefined or so
The method you're using using returns Promise<UserCredential>. Your code should be:
const usersRef = firebase
.firestore()
.collection('Users');
firebase
.auth()
.createUserWithEmailAndPassword(values.email, values.password)
.then(function(userCredential) {
usersRef
.doc(`${userCredential.user.uid}`)
.set({
firstName: values.firstName,
lastName: values.lastName,
username: values.username,
uid: userCredential.user.uid
})
...

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