GET Request route MEAN - node.js

I'm creating a MEAN APP and upon registration I want to check if an email already exists. However the GET request doesn't show anything. Also no error.
server.js
...
// Set user routes
const userRoutes = require('./user/user_controller');
app.use('/user', userRoutes);
...'
user_controller.js
router.get('/:email', (req, res) => {
console.log('Requesting user');
User.findOne({'email': req.params.email})
.exec(function(err, user) {
if(err) {
console.log('Error getting the post');
} else {
res.send(user);
}
});
});
The GET route never enters because I also don't see the console.log at the beginning of the route. I expect the route to work when I call localhost/user?email=email
I have a POST route whih works perfectly for localhost/user - just to compare
router.post('/', (req, res) => {
user = req.body;
// Validation
req.checkBody('firstName', "Enter a valid firstname").exists().isAlpha();
req.checkBody('lastName', 'Enter a valid lastname').exists().isAlpha();
req.checkBody('email', 'Enter a valid email').exists().isEmail();
req.checkBody('password', 'Enter a valid password').exists().isLength({min:8});
const errors = req.validationErrors();
if(errors) {
res.json({errors: errors});
} else {
User.create(user)
.then((user) => res.send(user));
}
});

You are calling your route the wrong way,
You can do one of these things.
1) Change your route path to /
As you said you were calling it localhost/user?email=email because this matches the route path / not /:email and you can access it like req.query.email.
2) Change the way you're calling it
If you want to use with /:email route path call it like localhost/user/someemail.

Related

Variable route/url param connected to Mongodb

Thanks for reading my question!
I'm making a chat-app where people can chat with each other who are born at the same date.
So the question is,
How do I change the route with an additional birthdate which is changing with every different user with different birthdates?
I already can signup/login and save the birthdate for every user.
So I need to take the birthdate from the mongoDB to put it in the url so nobody gets directed to the wrong chat.
router.get("/", chatController.getAll);
app.use('/api/v1/chat', passport.authenticate('jwt', { session: false }), apiChatRouter);
const getAll = (req,res)=>{
Message.find({},(err,docs)=>{
if(!err){
res.json({
"status":"succes",
"data":{
"chat":docs
}
});
}
});
}
fetch('http://localhost:3000/api/v1/chat/', {
//nodige headers meegeven met localstorage
'headers':{
'Authorization': 'Bearer ' + localStorage.getItem('token')
}
}).then(result => {
return result.json();
}).then(json =>{
console.log(json);
}).catch(err =>{
console.log("Unauthorized")
});
If you want to check the rest of the code:
https://github.com/abuijzen/Herexamen-Webtech3
You can use express path param please check the below example
To redirect user to other path you can user
res.redirect('/1990-03-29');
to get param from url
app.get('/api/v1/chat/:bd', function (req, res) {
// http://localhost:xx/api/v1/chat/1990-03-29
req.params // eqal { "bd": "1990-03-29" }
})
Please check routing and redirect

How to show logged in user info in all routes NodeJS

So this is my code that shows if user session exists and if it exists then it renders user info with the file so I can display the logged in user info there.
app.get('/', async(req, res) => {
if(req.session.user && req.cookies.user_sid){
let user = await User.findOne({username: req.session.user.username});
res.render('index', {user});
} else {
res.render('index');
}
});
But now I want to display user info and in another routes. So in my opinion it would be stupid to repeat again that if statement. What alternative could be there?
It's best to repeat that statement and make the DB call again. In the time between the first request and any subsequent requests, the user may have been logged out (such as by cookies expiring) or user data might have been changed in the database, so it's best to not cache the data and check every time.
Method 1
Add a user details middleware ,which checks if user details is available in session or not and then updates the session object if not available.This way you will avoid redundant calls to db across routes.
app.use(function (req, res, next) {
if(req.session && req.session.userDetails === undefined){
const userDetails = await User.findOne({username: req.session.user.username});
req.session.userDetails = userDetails || undefined;
//optional
req.user = {};
Object.assign(req.user, req.session.userDetails);
}
next()
})
You can pass the userDetails in all your routes with reference to req.user or req.session.userDetails, something like
app.get('/profile', async(req, res) => {
res.render('profile', {user : req.user});
})
Method 2
You can also save the user details in session when the user successfully logs in and use the session reference in all routes, something like
app.post('/authenticate', async (req, res) => {
const userDetails = await User.findOne({ username: req.body.username, password: req.body.password });
if (userDetails.length > 0) {
//when authentication is successsful
req.session.user = userDetails;
}
});

Can I use res.redirect and res.send simultaneously in Node.js?

I want to print user's info on the landing page after they get logged in. I am using res.redirect to redirect to landing page i.e index1.html after a user get successfully logged in.
Now I want to get user info. Here is my node.js code:
app.post('/login-feedback', function (req, res) {
dbConn.then(function(db) {
delete req.body._id; // for safety reasons
var dd = db.db("customermanagement");
dd.collection('admin').findOne({username: req.body.username, password: req.body.password}, function(err, user){
if(err) {
console.log(err);
}
else if(user){
req.session.user = user;
console.log( req.session.user.username);
res.status(200);
res.redirect('/index1.html');
}
else {
res.redirect('/login1.html');
}
});
});
});
I would love if you will tell me explicitly everything step by step.
If you want to send data to a static file, like an html file, you should use res.render :
res.render('/login1.html', {user: req.session.user.username})

passport-local-mongoose changePassword function

I want to have the functionality that user can change their password.
I've implemented a route ('/resetPasswd') like this:
UserRouter.route('/resetPasswd')
.post(function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
user.changePassword(req.body.oldPassword, req.body.newPassword, function (err, user) {
if (err) next(err);
res.json('password changes successfully !');
})
})(req, res, next);
});
this is what I send as the body:
{
"oldpassword": "secret",
"newPassword": "new"
}
But I get this error as response:
{
"message": "user.changePassword is not a function",
"error": {}
}
and this is a picture of my schema:
user schema:
I don't think I should declare the changePassword function in my schema (since it is provided by the passport-local-mongoose, although I added it but still get the same error) What mistake am I making here?
Someone had the same issue last night actually. Their problem was the package needed to be updated. I would check that you're on the latest version.
Here is what i did in my controller handling the reset password,
exports.editPassword = async (req, res) => {
const user = await User.findOne({
username: req.user.username
});
await user.setPassword(req.body.password);
const updatedUser = await user.save();
req.login(updatedUser);
req.flash('success', 'Password Changed Successfully') res.redirect('back')
}
from the Documentation Passport-local-mongoose ,you first need to get the specific user to update the password , here in my case the current login user , which is available on the req.user which we are exposed to , you can use any of the return property to query your collection, using async await i made a variable to hold the return object, in my case 'user', thereafter i chained the setProperty on it passing in the new password(req.body.password) since it return a promise i await it and assign a variable to it. from here you are good ...Note: since it is a promise it either resolved of reject, handling error can be done by rapping your code in a safe blanket, try..catch . You can read more Here
Since changePassword is a schema method, it must be used on an instance of a model, not the model itself or the imported passportLocalMongoose.
UserModel.findById(req.user._id)
// I assume you already have authentication and the req.user is generated
.then(foundUser => {
foundUser.changePassword(req.body.old, req.body.new)
.then(() => {
console.log('password changed');
})
.catch((error) => {
console.log(error);
})
})
.catch((error) => {
console.log(error);
});
the user object passport sends in callback function is just an object and not a schema instance document object, thus it does not have the changePassword function.

sails session writing bug

I'm using sails 0.10.4 and stumbled with one pretty annoying bug. When user logs in I write his data into the req.session.user then in policies I can retrieve his data such as his role, password etc. But the req.session.user becomes undefined when I go out of the login action. Do you have any ideas how to handle this? Here's the code:
api/controllers/User.js :
module.exports = {
login: function (req, res) {
Users.findOneByEmail(req.param('email'))
.exec(function (err, user) {
if ((err) || (!user)) {
res.send({
error: 'User not found'
});
return;
}
if (!passwordHash.verify(req.param('password'), user.password)) {
res.send({
error: 'Incorrect passwpord'
});
return;
}
req.session.user = user;//I write user into the session
res.send({
user: user
});
});
}
}
api/policies/isLoggedIn.js
module.exports = function (req, res, next) {
if (req.headers.authentication) {
var credentials = JSON.parse(req.headers.authentication);
if(req.session.user.login === credentials.login)//User doesn't exist in session
return next();
}
}
In a testing environment , this issue can happen when testing with Supertest and not defining an agent
var agent = request.agent(app);
agent.post('/api/login',{email:'foo#bar.com',password:'foobar})
.end(function(err,res){...; done();});
It is the correct way to work with sessions, simply using request.post would not work as it would reinit the session variable as soon as the response is sent, even if we are chaining requests inside the same test.
Learnt it the hard way, so I hope it can help some lost developper.

Resources