User Registration using Mongo and NodeJs not working - node.js

i have made a usewr registration login in react and node . My signup route is working and user is saved in mongo , but signin route is not working ?
SignIn Component:-
signIn(){
axios.post('/tasks/signin', {
email: this.state.email,
password: this.state.password,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
Routes are:-
Router.post('/signin', (req, res) => {
var User = new db1();
User.findOne({ email: req.body.email , password: req.body.password
}, function(err, user) {
console.log(user);
if(err) return next(err);
if(!user) return res.send('Not logged in!');
return res.send('Logged In!');
});
});
Error:
User.findOne is not a functionand i am getting 500 status.
Please help where am i wrong .

The findOne method is on the model, not the object. So it should be:
db1.findOne({ email: req.body.email , password: req.body.password
See previous question.

It seems to me that you require the model and assign it to a variable call db1 and create an instance called User. After that, you call the findOne method of the instance instead of the model itself.
If you are using Mongoose, this should be the problem. If not, please give some more details.
Also, it is usually a good practice to call your classes with PascalCase and your instances with camelCase. This way you won't get confused.

Related

Fetch data from MongoDB when the user register

I am learning MEAN stack environment and I have a question.
I have a registration page, which registers the user in MongoDB:
// register.component.ts
register(){
this.http.post('http://localhost:3001/register', this.input)
.subscribe(
( next: any) => {
// TO-DO Success event
},
( error: any) => {
// TO-DO Error event
});
}
// app.js
app.post('/register', function(req, res){
db.collection('users').insertOne({
prenom : req.body.prenom,
nom: req.body.nom,
email : req.body.email,
password : req.body.password
})
})
It works pretty well, the problem is that for the connection, I use the _id:
// login.component.ts
login(id: string){
this.http.get('http://localhost:3001/login/' + id).toPromise().then((data: any) => {
this.users = data
})
sessionStorage.setItem('id', id)
}
// app.js
app.get('/login/:id', function(req, res){
db.collection('users').findOne({ email: ObjectId(`${req.params.id}`)}, function(err, user){
if (err) throw err;
if (!user) {
console.log('User not found')
}
else if (user)
{
console.log('Found user: ' + user.prenom)
}
})
})
How to make sure that when the user registers, it returns his _id directly, and like that I can put him in session:
sessionStorage.setItem('id', id)
The db.collection.insertOne() function returns the inserted document, see here. This means you can do a callback or async/await (whichever you prefer) for your insertOne() function and then return the _id by using the Express function res.json(). In your frontend, you'll then get whatever content you put into res.json() as a response. Happy coding! :)

How do I pass data to different routes using Express?

I'm creating a web application that requires a user to register/login, and once they've done that, they're taken to their "account page" where their account information is available for them to see.
I'm using MongoDB, Mongoose, and Passport.
I have my post route:
app.post("/", function(req, res){
User.findOne({username: req.body.username}, function(err, foundUser){
if(foundUser){
//found user in database
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, function(err){
if(err){
console.log(err);
} else {
passport.authenticate("local", function(err, user){
if(err){
console.log(err);
} else {
if(user){
res.redirect("/user");
} else {
res.render("home", {failedAttempt: true});
}
}
})(req, res);
}
});
} else {
//user does not exist
console.log("the user does not exist here");
res.render("home", {failedAttempt: true})
}
});
});
I would like to be able to pass the database info for that particular user to the "/user" route, but I don't know how. How can I make it so that once the user is redirected to root/user, I can then pull up the info on their database?
You may want to look into Express Middleware. This allows you to do some processing first to pull out the user info and then pass the resulting data to your route.
Read all about it:
https://expressjs.com/en/guide/using-middleware.html

Node JS Request Response not working

This is my register route. If the registration is successful I want to redirect to the secret route. But the response is not working. When it is successful the page keeps loading and loading and doesn't redirect me to the secret route.
app.post('/register', function(req, res) {
User.create({
username: req.body.username,
password: req.body.password,
email: req.body.email
}, function(err, result, res) { **HERE**
if(err) throw err;
res.redirect('/secret');
console.log(result);
});
});
I tried this and the /secret route works but when I do this it doesn't check for registration errors and immediately redirects to the secret route.
app.post('/register', function(req, res) {
User.create({
username: req.body.username,
password: req.body.password,
email: req.body.email
}, function(err, result) { **HERE**
if(err) throw err;
console.log(result);
});
res.redirect('/secret');
});
I tried to add return err. So if there is an error the function will exit.
But here the /secret route still is still shown when I intentionally made an error in the registration. So the return is not exiting the function.
app.post('/register', function(req, res) {
User.create({
username: req.body.username,
password: req.body.password,
email: req.body.email
}, function(err, result) {
if(err) return err; **TRIED RETURN TO EXIT**
});
res.redirect('/secret');
});
That it keeps loading and loading indicates that the create user function returns an error in the callback. Or an error occured in the callback.
In case of an error no reponse might be send which will result in a dangling request.
In your code the reason is that you have to remove the res from the create user callback otherwise you will hide the original res of the middelware callback, which will result in an error. But you also have to handle the case when create user itself results in an error.
Your callback could look that way:
function(err, result) {
if(err) {
res.status(500).send('an error occured')
} else {
res.redirect('/secret');
console.log(result)
}
}
How exaclty the callback should look like depends on what you want to do in case of the error. You also might want to choose a different error code then 500 that would match better.
I believe you're confusing the callback-based nature of asynchronous programming in normal NodeJS with regular sequential programming.
The call to User.create will return immediately, and lines following it execute prior to anything within the callback you provide. So your res.redirect() call will trigger the immediate response of a redirect to the client. When the callback finally runs, the request has finished.
Instead, you will want to perform the redirection inside of the callback function, after checking for potential errors.
Your code should end up looking like this:
app.post('/register', function(req, res) {
User.create({
username: req.body.username,
password: req.body.password,
email: req.body.email
}, function(err, result) {
if(err) throw err;
// Since we got here, things went well presumably
res.redirect('/secret');
});
});

Node.js - Check if user exists

I'm using NodeJS and passport to let users create an account before they can see results of a quiz they've just taken. My challenge is I need to confirm the username is available before the page refreshes because the user will lose their results if this happens.
Again: I need to verify the username is not taken prior to refreshing.
I think I'm close but it is not working. How would I change my code to handle this challenge?
Currently if the user name is taken it returns an error on trying to create an account and the user ends up on the /failpage as shown below.
app.post('/quiz', usernameToLowerCase, emailToLowerCase, function(req, res) {
User.findOne({
username: req.body.username
}, function(err, user) {
if (err) {
alert(err)
if (user) {
alert('this username is already taken. Please choose another.')
console.log('there was a user');
return false;
}
}
});
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password,
})
user.save(function(err) {
console.log('this is the problem' + ' ' + err)
if (err) {
return res.redirect('/failpage')
}
req.logIn(user, function(err) {
if (err) {
console.log(err);
}
console.log('all looks good')
res.redirect('/results');
});
});
});
Solved it with this if anyone else is trying to do the same thing:
in app.js
app.get('/usercheck', function(req, res) {
User.findOne({username: req.query.username}, function(err, user){
if(err) {
console.log(err);
}
var message;
if(user) {
console.log(user)
message = "user exists";
console.log(message)
} else {
message= "user doesn't exist";
console.log(message)
}
res.json({message: message});
});
});
In js
$('#usercheck').on('change', function() {
$.get('/usercheck?username='+$('#usernameValue').val().toLowerCase(), function(response) {
$('#usernameResponseHidden').text(response.message)
if ($('#usernameResponseHidden').html() === "user exists"){
$('#usernameResponse').text('That username is taken. Please pick another')
}
To solve your problem I think you need to routes. At least a app.get('/quiz') which returns a boolean on if the user exists or not. The section User.findOne can be sent in that route instead. You just need to make a request using ajax when he looses focus of the username field of your form, and display a notification if the name is available or not.

Forcing Sequelize to update req.user in Express route

I have a very simple site that is using Passport JS to create local login strategy to hit a local postgres database using the Sequelize ORM.
The user model looks something like this:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('user', {
id: {
primaryKey: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
email: DataTypes.STRING,
password: DataTypes.STRING,
}, {
classMethods: {
generateHash: function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
},
},
instanceMethods: {
validPassword: function(password) {
return bcrypt.compareSync(password, this.password);
}
},
getterMethods: {
someValue: function() {
return this.someValue;
}
},
setterMethods: {
someValue: function(value) {
this.someValue = value;
}
}
});
}
Everything seems to work just fine. I can sign up using this strategy, log in, and see data.
I also am using Express and have various routes set. The req.user appears to be set correctly, as I can interact with all the fields of this object.
Consider the sample route which works correctly:
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile.ejs', {
user : req.user
});
});
My serialization / deserialization methods:
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id).then(function(user) {
done(null, user);
}).catch(function(e) {
done(e, false);
});
});
So, as per the Passport JS documentation, the user session seems to be correctly set and hooked into Express.
The trouble is that I cannot update any of the fields in the user object.
If I have the following route:
app.get('/change-email', function(req, res) {
req.user.email = req.body.email;
res.status(200).end();
});
Nothing happens in the database.
This is very similar to this question except it appears with Sequalize, the user object never persists, even after logging out and back in again.
I have also tried: req.session.passport.user.email = req.body.email
Although I didn't think this would fix the problem, I also tried to call login with the new user object, but this generated 500 errors. Which such a limited number of functions that can be called, according to the Passport JS documentation, I'm starting to question if this functionality is even possible.
I'm not sure what to try from here. How can I update my user object using Sequelize?
Any help would be greatly appreciated! Thanks!
// Edit: Rewriting first paragraph to be clearer
When you change any column values in an Instance object you also need to explicitly save the changes to the database to persist them. Since you are already storing the user Instance in req.user via passport.deserializeUser you only need to make a small change to your routing code to do this.
Instead of your current route for /change-email, I suggest:
app.get('/change-email', function(req, res) {
req.user.email = req.body.email;
req.user.save()
.then(function() {
res.status(200).end();
});
});
For more information on how to persist changes to an instance, see this part of the Sequelize documentation.
I know it's a late answer but no wonder someone will pass around this in the near future,
anyway, to get the authenticated user information in req.user with sequelize version 6.* and Express
here is the trick:
//a middleware to verify if a user is authenticated or not
exports.verifyToken = async (req, res, next) => {
let token = req.headers.bearer;
if (!token) {
return res.status(403).send({
message: "No token provided!"
});
}
jwt.verify(token, secretKey, async (err, decoded) => {
if (err) {
return res.status(401).send({
message: "Unauthorized!"
});
}
//$$$$$$$$$ here is everything you want to do $$$$$$$$$$$$$$$
req.user = await Users.findByPk(decoded.id, { raw: true });
next();
});
};
and here is an example where we can use that middleware
.get('/wishlist', auth.verifyToken, (req, res, next) => {
console.log(req.user);
})
the output will be something like this:
{
id: '9313e6e5-7b04-4520-8dbc-d04fad3a0cb1',
fullName: 'Anis Dhaoui',
avatar: 'images/imagelink.jpg',
username: 'anis',
}
and of course, you can modify the output of your findByPk or findOne query using include or exclude see Sequelize docs
https://sequelize.org/docs/v6/core-concepts/model-querying-basics/

Resources