How to get multiple parameters from API call in Node and Express - node.js

Need some help here as I am very lost in something that should be very simple. Either that or I am losing my mind.
Ok so I am routing my routes using the express.Router()
I will jump right to the problem:
This works:
apiRouter.get('/api/user/:id', secureAPIPages, function(req, res, next){
userModel.findOne({'profileID':req.params.id}, function(err, user) {
if(user){
res.json({
fullname: user.fullname,
about: user.about,
birthday: user.birthday,
email: user.email,
location: user.location
});
} else {
console.log('Result does not exist');
}
});
})
So when I make a call on a browser like:
http://localhost:3000/api/user/123456
It picks up the "id" variable and puts it in the req.params so all good there.
Now, the problem (this is what I want to make work, the above one is just to test out if my API routing worked):
apiRouter.get('/api/user', secureAPIPages, function(req, res, next){
userModel.findOne({'profileID':req.params.id}, function(err, user) {
if(user){
res.json({
fullname: user.fullname,
about: user.about,
birthday: user.birthday,
email: user.email,
location: user.location
});
} else {
console.log('Result does not exist');
}
});
})
Why is it not picking up my "id" and "name" variables when I run this URL on a browser:
http://localhost:3000/api/user?id=123456789&name=Shayan
As always, thanks for the help in advance.
Shayan

You should use query object as follows:
If this is the URL:
http://localhost:3000/api/user?id=123456789&name=Shayan
use
req.query.id, req.query.name

Related

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

User Registration using Mongo and NodeJs not working

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.

Why my middleware is not checking if the email already exists?

I am authenticating people using passportJS. The problem I have recently realised is the fact that users are able to register for more than one account. I have created a middleware to check whether the email is already in use but somehow it is still passing the test.
var User = require('../models/users');
var authMethods = {};
authMethods.isInUse = function(req,res,next){
User.findOne({"email" : req.body.email}, (err,user) => {
if(user){
req.flash('error',"This mail is already in use.");
res.redirect('/register');
}else {
return next();
}
});
}
module.exports = authMethods;
In my authentication page I am calling the middleware inside the route to meet the condition.
router.post('/register',authMethods.isInUse ,multipart(),function(req, res) {
var image = fs.readFileSync(req.files.image.path);
var profilePic = {data : image, contentType : 'image/png'};
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password,
occupation: req.body.occupation,
phone: req.body.phone,
profilePic : profilePic,
firstName : req.body.firstName,
lastName : req.body.lastName
});
user.save(function(err) {
req.logIn(user, function(err) {
req.flash("success", "Welcome to the site " + user.username);
res.redirect('/flats');
});
});
});
I haven't been able to spot the faulty approach that's causing the problem.
If multipart() does what I think it does (parse the request data into req.body), then req.body will probably not be populated in your middleware because it's being called before the multipart middleware.
Try switching the middleware functions around:
router.post('/register', multipart(), authMethods.isInUse, function(req, res) {
...
});

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/

mongodb returns incorrect type of a key

Im using node.js+express+mongodb+mongoose, trying to retrieve user from database by custom ids, page returns back completely empty due to incorrect datatype of id value, here is some part of my code:
var User = new Schema({
name: String ,
email: String ,
id: Number,
role: String
});
var userModel = mongoose.model('User', User);
var person = new userModel();
function loaduser(req, res, next) {
userModel.find({}, req.params.id, function(err, user){
if (user){
req.user = user;
console.log(user);
next();
}
})
console.log(typeof req.params.id);
};
//personal page route
app.get('/user/:id', loaduser, function(req, res){
res.render('show', { users: req.user });
});
and then this returns in console:
string
{ _id: 5012aa222c2d4d5876c5acd0,
email: 'alex#mail.com',
id: '0',
name: 'alex',
role: 'admin' },
even though i declared type of id as Number it gets back as String.
Any suggestions are welcome :)
Your find call isn't quite right. The first parameter should be your query document and since you're looking for one document you should use findOne instead. You also need to convert req.params.id to a number:
userModel.findOne({ id: Number(req.params.id) }, function(err, user){
If you still see a problem with id coming back as a string, it must be a string in the collection.
req.params.id seems to be wrong in
userModel.find({}, req.params.id, function(err, user){
It should be
userModel.find({}, { id: parseInt(req.params.id) }, function(err, user){

Resources