Setting a unique user nickname in node express app - node.js

I have a user profile collection in which I have the following fields:
member_id
userhandle
height
weight
I register a user with passport and generate a unique member_id for each user which is later used for getting the profile page populated and also for referrals. Following is the get profile route where user can change their details:
// Get User Profile Settings route
router.get('/profilesettings/:member_id', (req, res) => {
Profile.findOne({ member_id: req.params.member_id })
.then(profile => {
res.render('users/profilesettings', { profile: profile });
})
.catch(error => {
console.log('could not find profile');
});
});
Once this page is loaded the user can change their details and use the submit button to update their data. Following is the code for the put request:
router.put('/profilesettings/:member_id', (req, res) => {
Profile.findOne({ member_id: req.params.member_id })
.then(profile => {
profile.userhandle = req.body.userhandle;
profile.weight = req.body.weight;
profile.height = req.body.height;
profile.mobile = req.body.mobile;
profile.save()
.then(updatedProfile => {
req.flash('success_msg', 'Profile updated successfully');
res.redirect('/user/userdashboard');
})
.catch(error => {
console.log(error);
});
})
.catch(error => {
console.log('could not find record');
});
});
What I want to do is ensure that the userhandle is always unique, so if the user enters a userhandle which is already taken by someone else in the profile collections there should be an error and the form should not submit. I am totaly stumped on how to put in a logic which does the following:
1- Checks if there is a difference in the userhandle submitted and the one already stored in the collection
2- Checks if the userhandle which came in the request already exists or not
3- if not then sets the userhandle to the new value and save
4- if it does it creates and error and redirects.
Would appreciate any advise. I know it's a small thing for you pros but I am learning Node and express :-)

After you have confirmed if the member exists or not, you can do a 'count' query to check if the 'userHandle' exists or not. If the userHandle already exists you can return a 4xx status code. Otherwise, save it in the db. It would look something like this...
router.put('/profilesettings/:member_id', (req, res) => {
Profile.findOne({ member_id: req.params.member_id })
.then(profile => {
Profile.count({userhandle: req.body.userhandle})
.then(count => {
if(count != 0){
//return the error code
}
else{
//proceed with your normal flow
profile.userhandle = req.body.userhandle;
profile.weight = req.body.weight;
profile.height = req.body.height;
profile.mobile = req.body.mobile;
profile.save()
.then(updatedProfile => {
req.flash('success_msg', 'Profile updated successfully');
res.redirect('/user/userdashboard');
})
.catch(error => {
console.log(error);
});
}
}).catch(err => {
console.log(err);
});
})
.catch(error => {
console.log('could not find record');
});
});

Related

Node JS : How to retrive data from frontend after a res.json(data) in backend?

my backend send a res.staus(200).json({somedata)} to my front, but i can't retrieve the data in the frontend.
My backend :
exports.login = (req, res, next) => {
//===== Check if user exists in DB ======
const { user_email, user_password: clearPassword } = req.body;
let sql = `SELECT user_password, user_id FROM users WHERE user_email=?`;
db.query(sql, [user_email], async (err, results) => {
console.log(results);
console.log(req.body);
if (err) {
return res.status(404).json({ err });
}
// ===== Verify password with hash in DB ======
const { user_password: hashedPassword, user_id } = results[0];
try {
const match = await bcrypt.compare(clearPassword, hashedPassword);
if (match) {
console.log("match ... user_id : ", user_id);
// If match, generate JWT token
res.status(200).json({
test: 'iyu',
user_id: user_id,
token: jwt.sign({ userId: user_id }, "TOOOKEN", {
expiresIn: "24h",
}),
});
} else {
console.log("not match");
}
} catch (err) {
return res.status(400).json({ err: "une erreur" });
}
});
};
The frontend :
const login = async (e) => {
e.preventDefault();
await POST(ENDPOINTS.USER_LOGIN, userLogin);
// await GET(ENDPOINTS.USER_LOGIN)
fetch("http://localhost:4200/api/auth/login")
.then((response) => response.json())
.then((data) => {
console.log(data);
});
};
This login fonction send data to my backend, then the backend checks if an user exist in database with the first POST request. If yes, the backend send in json format some data that i wan't to put in the local storage of the user, so after the POST request, i do another request with GET method to retrieve the json data sent from the back, but i have an 404 error.
How can i get my data sent by the back ?
Seems the problem is with the SQL statement, underneath the if statement you have can you print the error like so:
if(err) {
console.log(err);
}
and tell me the result please

Delete item from mongoDB from client side

I've created a React app where you can post vinyls you have in your collection. Now I've implemented a button that is able to remove the selected item from the DOM but I also want the specific item to beremoved from the database. I'm using node with mongoose and that's (for now) my delete route:
vinylsRouter.delete('/:id', (req, res) => {
const id = req.params.id
Vinyl.findByIdAndDelete(id)
.then((deletedVinyl) => {
console.log(deletedVinyl)
})
.catch((error) => {
res.status(500).send(error);
})
});
I also tried to store the id of the specific vinyl _id into a variable and then delete it. So I also created a get route to try to get the _id of the vinyl.
vinylsRouter.get('/:id', authenticateJWT, (req, res) => {
const id = req.params.id;
Vinyl.findById(id, { __v: 0, updatedAt: 0, createdAt: 0 })
.then((user) => {
res.send(user)
})
.catch((error) => {
res.status(500).send(error)
})
});
But now I don't know how to code in the client side to make that when an user clicks in the delete button, it sends something to get the id of the vinyl and then delete it.
First put some response when the delete works:
vinylsRouter.delete('/:id', (req, res) => {
const id = req.params.id
Vinyl.findByIdAndDelete(id)
.then((deletedVinyl) => {
res.status(200).send(deletedVinyl);
})
.catch((error) => {
res.status(500).send(error);
})
});
If are you trying to do a API You can use express/nodejs, and do res.status(200).json({message: "my message"}).
Second you can use a library like axios:
axios.delete(`http://localhost:xyz/vynils/`, { id })
.then(res => {
console.log(res);
console.log(res.data);
})
https://www.digitalocean.com/community/tutorials/react-axios-react
And send for the server when the users click in the delete button.
You can use postman to test your delete endpoint before you use this on client-side (frontend), remember select delete in the dropbox and put a auth token (JWT) in the Authorization tab, or you can remove, only for test the auth middleware:
Say me if is this what you want to do.
app.delete('/product/:id', async (req, res) => {
const id = req.params.id;
const query = { _id: ObjectId(id) };
const result = await productCollection.deleteOne(query);
res.send(result);
})

Deleting the model data through lodash and save() not persisting model in mongodb

I am trying to remove one object from the User collection like this
router.post('/accept-trades', function (req, res, next) {
const {senderName, receiverName, senderId} = req.body;
const user = req.user;
console.log(senderName, receiverName);
if (senderName) {
User.findOne({ name: senderName })
.then(sender => {
_.remove(user.receivedTradeRequest, {username: senderName});
_.remove(sender.sentTradeRequest, {username: receiverName});
console.log('user.receivedTradeRequest', user.receivedTradeRequest);
console.log('\n\nuser.sentTradeRequest', user.sentTradeRequest);
async.parallel([
function (cb) {
user.save()
.then(isSave => {
cb(null, true);
})
.catch(err => {
cb(err, null);
});
},
function (cb) {
sender.save()
.then(isSave => {
cb(null, true);
})
.catch(err => {
cb(err, null);
});
}
], (err, results) => {
if (err) {
return res.status(500).json({
message: 'Error: Trade is invalid as Card is already traded!',
});
}
res.send('done');
//res.redirect('/trade');
});
})
.catch(err => {
throw err;
});
} else {
return res.status(500).json({
message: 'Only accessible to logged in users!',
});
}
});
Here, user is accessed by req.user (i'm using passport).
When i log the user after removal, user.receivedTradeRequest and sender.sentTradeRequest printing empty array which is the correct behaviour.
But when i see the mongodb the array still present for the username.
Could you please suggest what is wrong with the code ?
PS: I know about the mongodb $pull for removal. I am doing some other computation on the user data so had to do with above approach.
I was able to solve it by re-assigning the array after removing the element. Used _.filter instead of _.remove solves the problem.
One thing i don;t understand is the lodash _.remove update the original array after deletion but that clearly is not the case here.

Mongoose findById correct way to check users rights

I need to check users rights to protect route.
I finding user by Id from token, and check in DB "admin" field.
It finds and check well, but i don't get what to do next. I'm using this middleware in "/admin" route:
User.findById(decodedToken.userId,)
.then(user =>{
isAdmin = user.admin;
if(!isAdmin){
const error = new Error('Unauthorized')
error.statusCode = 401
throw error
}else{
req.userId = decodedToken.userId
next();
}
}).catch(err=>{
console.log(err);
return err
})
but I don't get any response on frontend, only pending GET request
You need to send a response to your frontend:
router.route("/").get((req, res, next) => {
res.setHeader("Content-Type", "application/json");
User.findById(decodedToken.userId, )
.then(user => {
//your logic
res.end('Have Permission');
}).catch(err => {
console.log(err);
return err
})
})
If you want to send an object you can do res.json(yourobject)

get logged user with NodeJS and Angular

I have some users in my app, now I want to get one user at a time when they login.
this is my node.js
router.get('/currentUser', (req, res) => {
User.findOne().then(user => {
console.log(user);
if (user) {
return res.status(200).json(user);
} else {
return res.status(404).json({
message: 'User not found'
});
}
});
});
and on my angular app I have
getCurrentUser(user: any) {
console.log(user);
return this.http.get(this.urlEnvironment + this.OneUserUrl).subscribe(data =>{
console.log(data)
});
}
the problem is it gets first user only from the database instead of the current user.
I have tried find() but it gets all those users.

Resources