Express return next() not ending the request - node.js

Whenever I send a request, I reach the .then() block and after executing the check(it gets confirmed), the route returns the error as expected. However, the function keeps going and adds the createdAppointment to the database. I've made tried returning just next(), using next(error) only but it keeps giving the same results - it always inserts into the database. Of course, I have the error middleware at the end.
async (err, client) => {
if (err) {
res.status(500).send("Failed Connection!");
return;
}
const forename = req.body.professional.split(" ")[0];
const surname = req.body.professional.split(" ")[1];
const professional = await client
.db("FYP")
.collection("Users")
.findOne({ forename: forename }, { surname: surname });
if (!professional) {
const error = new Error("Professional doesn't match with any in the database")
error.code = 422
return next(error)
}
if(professional.type != "Therapist") {
const error = new Error("The chosen user is not a therapist.")
error.code = 422
return next(error)
}
const user = await client
.db("FYP")
.collection("Users")
.findOne({ _id: res.locals.uid });
const clientUserName = user.forename + " " + user.surname;
const professionalUserName = professional.forename + " " + professional.surname
await client
.db("FYP")
.collection("AppointmentsTherapists")
.find({ client: clientUserName}, { complete: false})
.toArray()
.then(async data => {
if(data) {
console.log(data.length)
for(let i=0; i<data.length; i++) {
console.log(dateInPast(data[i].startTime))
if(dateInPast(data[i].startTime) == false) {
console.log(data[i]._id)
const error = new Error("You already have a booked appointment with a therapist. Please attend the current appointment before booking another.")
error.status = 422
return next(error)
}
}
}
})
if (professionalUserName == clientUserName || user.type == "Therapist" || user.type == "Rehabilitator") {
const error = new Error("A professional cannot book an appointment for themselves.")
error.code = 422
return next(error)
}
const appointment = {
client: clientUserName,
professional: req.body.professional,
information: req.body.information,
startTime: req.body.startTime,
endTime: req.body.endTime,
status: "Pending",
complete: false,
date: new Date()
};
const createdAppointment = await client
.db("FYP")
.collection("AppointmentsTherapists")
.insertOne({ ...appointment });
res.status(200).send(createdAppointment);
return next();
}
);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
message: error.message
})
})

Use async / await or .then() but not both...
let data = await client
.db("FYP")
.collection("AppointmentsTherapists")
.find({ client: clientUserName}, { complete: false})
.toArray()
if(data) {
console.log(data.length)
for(let i=0; i<data.length; i++) {
console.log(dateInPast(data[i].startTime))
if(dateInPast(data[i].startTime) == false) {
console.log(data[i]._id)
const error = new Error("You already have a booked appointment with a therapist. Please attend the current appointment before booking another.")
error.status = 422
return next(error)
}
}
}

Related

Why my user controller can't get userid property which i have provided in my USERS Schema?

Issue 1: Why my user controller can't get userid property which i have provided in my USERS Schema? i have given a property userid in my Schema which will be a number, but when i am checking my mongobd to see that is userid is coming or not than that userid property is not even showing in my mongobd..
Issue 2: Why my Schema is replicating 3 times whenever i sign up in my app? the Schema is replicating 3 times but every 3 times the mongobd user_id gets change i think its a bug (Note: here the user_id which i am talking about is a user_id which is created by my controller response and in the above issue which i am talking about is a userid that i want to give to my user which will be much smaller and it will be a property)
Mongobd look like this
_id
63613eb2685aa82252cb121b
name
"ecawecawecawce"
phoneNumber
"ewcwaecawecwaecawec"
profileImage
"https://www.pngitem.com/pimgs/m/146-1468479_my-profile-icon-blank-prof…"
selectedCountry
Object
name
"India"
dialCode
"+91"
isoCode
"IN"
flag
"https://cdn.kcak11.com/CountryFlags/countries/in.svg"
__v
0
My Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Users = new Schema({
name: String,
phoneNumber: String,
userid: Number, // Ealier it was a string
profileImage: {
type: String,
default: 'https://www.pngitem.com/pimgs/m/146-1468479_my-profile-icon-blank-profile-picture-circle-hd.png'
},
about: String,
selectedCountry: {
type: Object
}
})
module.exports = mongoose.model("users", Users)
user.controller.js:
const user_module = require('./user.modules');
class user_controller extends user_module {
static create_user = async (req, res) =>{
try {
console.log("controller response",req.body)
let response = await this.save_user_details(req)
let message = 'Success';
res.send({
sucess: true,
message: message,
data: response
})
} catch (error) {
let status_code = error.status.code != undefined ? error.status_code: 500;
let type = error.type != undefined ? err.type: 'Bad Request';
let message = err.custom_msg != undefined ? error.custom_msg: "Something went wrong"
res.status(status_code).send({
sucess: false,
error:type,
message: message
})
}
}
static get_users = async (req, res) =>{
try {
console.log("controller response",req.body)
let response = await this.retrieve_user(req)
let message = 'Success';
res.send({
sucess: true,
message: message,
data: response
})
} catch (error) {
let status_code = error.status.code != undefined ? error.status_code: 500;
let type = error.type != undefined ? err.type: 'Bad Request';
let message = err.custom_msg != undefined ? error.custom_msg: "Something went wrong"
res.status(status_code).send({
sucess: false,
error:type,
message: message
})
}
}
static otp_verify = async (req, res) =>{
try {
console.log("controller response",req.body)
let response = await this.verify_user(req)
if(response.status){
res.send({
success: true,
message: response.message,
data: response.user
})
}else{
res.status(400).send({
success: false,
error: false,
message: response.message
})
}
} catch (error) {
let status_code = error.status_code != undefined ? error.status_code: 500;
let type = error.type != undefined ? err.type: 'Bad Request';
let message = error.custom_msg != undefined ? error.custom_msg: "Something went wrong"
res.status(status_code).send({
sucess: false,
error:type,
message:message
})
res.end();
}
}
}
module.exports = user_controller
user.modules.js:
const models = require('../models');
class user_module {
static save_user_details = async (req) => {
try {
console.log("req body", req.body)
const { profileImage } = req.body
let set_data = req.body
if (!!profileImage) {
set_data.profileImage = profileImage
}
return await models.users.create(set_data)
} catch (error) {
throw error
}
}
static retrieve_user = async (req) => {
try {
let {limit, pagination} = req.query
let query = {}
let projection ={__v: 0}
let options = {
lean: true,
sort: {_id: -1},
skip: !Number(pagination) ? 0: Number(pagination) * !Number(limit) ? 10: Number(limit),
limit: !Number(limit) ? 10: Number(limit)
}
let users = await models.users.find(query, projection, options)
let count = await models.users.count(query)
return {users, count}
} catch (error) {
throw error
}
}
static verify_user = async (req) => {
try {
console.log("req body", req.body)
const { otp, user_id } = req.body
if(otp == '123456'){
let user = await models.users.findById(user_id)
return {user: user, status: true, message: 'success'}
}else{
return {user: null, status: false, message: 'Otp Invalid'}
}
} catch (error) {
throw error
}
}
}
module.exports = user_module
You are not getting the Id because you are trying to get it by user_id, however, It's userid in your model.
Either you have to go with userid OR you have to go with User._id to get your _id which MongoDB creates for every new entry

How to create blockUserTime correctly?

I have security.controller, security.service and VerificationEntity.
So, in security.controller I have checkVerificationCode method in which I am trying to block the user if he has exceeded the allowed number of inputs of the wrong code and create the timestamp of the last failed attempt, and then in security.service I'm saving this blockedTime into the blockedTime column in VerificationEntity.
Problem is, when I'm trying to check code again during this block time, blockedTime is updating again. How can I prevent it and make blockedTime static, in order to further compare it with the current timestamp.
security.controller:
public checkVerificationCode = async (req: Request, res: Response) => {
try {
const { mobilePhone, verificationCode, id } = req.body;
const dataToCheck = await this.securityService.checkCode(mobilePhone);
if (verificationCode !== dataToCheck.verificationCode || id !== dataToCheck.id) {
const newTries = dataToCheck.tries + 1;
const triesLeft = +process.env.MAX_CODE_TRIES - +newTries;
if (triesLeft <= 0) {
const blockedTime = await this.securityService.updateBlockTime(mobilePhone, id);
if (timeDiffInMinutes(blockedTime) <= +process.env.USER_BLOCK_EXPIRATION) {
return res.status(StatusCodes.BAD_REQUEST).json({ blockSeconds: `You still blocked` });
}
return res
.status(StatusCodes.BAD_REQUEST)
.json({ blockSeconds: `You was blocked, you can try again after 10 minutes.` });
}
return res.status(StatusCodes.BAD_REQUEST).json({ msg: 'Verification code is invalid' });
}
if (timeDiffInMinutes(dataToCheck.updatedAt) >= +process.env.CODE_EXPIRATION_TIME) {
return res.status(StatusCodes.BAD_REQUEST).json({ msg: 'Verification code expired!' });
}
await this.securityService.resetTries(mobilePhone, id);
return res.status(StatusCodes.OK).json({ msg: 'Success!' });
} catch (error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: error.message });
}
};
security.service:
public async updateBlockTime(mobilePhone: string, id: string) {
const { blockedTime } = await getRepository(VerificationEntity).findOne({ mobilePhone: mobilePhone as string, id });
const timestamp = Date.now();
const blockedTimestamp = new Date(timestamp);
await getRepository(VerificationEntity)
.createQueryBuilder()
.update(VerificationEntity)
.set({ blockedTime: blockedTimestamp })
.where({ mobilePhone: mobilePhone as string, id: id as string })
.execute();
return blockedTime;
}

How to consume a RESTful API in Node.js

I'm new to Node.js and I'm creating a simple pagination page. The REST API works fine, but consuming it has left me in limbo.
Here is the REST API (other parts have been taken out for brevity)
const data = req.query.pageNo;
const pageNo =
(typeof data === 'undefined' || data < 1) ? 1 : parseInt(req.query.pageNo);
let query = {};
const total = 10;
query.skip = (total * pageNo) - total;
query.limit = total;
try {
const totalCount = await Users.countDocuments();
const pageTotal = Math.ceil(totalCount / total);
const users = await Users.find({}, {}, query);
return res.status(200).json(users);
} catch (error) {
console.log('Error ', error);
return res.status(400).send(error)
};
};
When I return the json with just the 'users' object, like so return res.status(200).json(users); the page renders correctly, but when I pass in other objects like what I have in the code, it fails. This is how I'm consuming the API:
const renderHomepage = (req, res, responseBody) => {
let message = null;
if (!(responseBody instanceof Array)) {
message = 'API lookup error';
responseBody = [];
} else {
if (!responseBody.length) {
message = 'No users found nearby';
}
}
res.render('users-list', {
title: 'Home Page',
users: responseBody,
message: message
});
}
const homelist = (req, res) => {
const path = '/api/users';
const requestOptions = {
url: `${apiOptions.server}${path}`,
method: 'GET',
json: true,
};
request(
requestOptions,
(err, {statusCode}, body) => {
if (err) {
console.log('Ther was an error ', err);
} else if (statusCode === 200 && body.length) {
renderHomepage(req, res, body);
} else if (statusCode !== 200 && !body.length) {
console.log('error ',statusCode);
}
}
);
}
I've searched extensively on both here and other resources but none of the solutions quite answers my question. I hope someone could be of help

Code executes before i get the response from the database

I am new to Express and writing the code to get the list from my database. I'm trying to update the quantity of the items in my list. Now there can be multiple items and quantity for those items needs to be updated accordingly. The problem I am facing is when I try to get the list and update item accordingly, before my for loop executes to update the item it doesn't update the item's quantity in the database and saves the order. What am I doing wrong?
I have used async functions, promises and flags to update the items quantity in the database but none helps.
This is my code for to get and update the item's quantity
const Express = require("express");
const app = Express.Router();
const Menu = require("../../models/Menu");
const Order = require("../../models/order");
const User = require("../../models/user");
app.post(
"/create",
async function(req, res) {
var myorder = {};
var orderList = [];
var ordDetail = [];
var UpdateMenus = [];
orderList = JSON.parse(JSON.stringify(req.body["OD"]));
if(orderList.length>0){
const user = await User.findOne({ _id: req.user.id })
.then(user => {
if (!user) {
return res.status(400).json({ error: "User Not Found" });
}
})
.then(() => {
var order = Order({
user: req.user.id
});
myorder = order;
(async function loop() {
for (i = 0; i < orderList.length; i++) {
const ordt = new Object({
menu: orderList[i]["menuId"],
order: myorder.id,
prize: orderList[i]["prize"],
quantity: orderList[i]["quantity"]
});
await Menu.findOne({ _id: orderList[i]["menuId"] })
.exec()
.then(menu => {
if (menu) {
if (menu.quantity >= ordt.quantity) {
menu.quantity = menu.quantity - ordt.quantity;
const editmenu = menu;
(async function updateTheMenu() {
await Menu.findOneAndUpdate(
{ _id: menu.id },
{ $set: editmenu },
{
new: true,
useFindAndModify: false
}
).then(updateMenu => {
console.log(updateMenu);
ordDetail.push(ordt);
});
})();
} else {
return res.status(400).json({
error:
menu.MenuText +
"" +
ordt.quantity +
" Qunatity Is Not Available"
});
}
}
});
}
})();
}).then(()=>{
order
.save()
.then(order => {
if (!order) {
return res.json({ error: "Order is not saved" });
}
res.status(200).json(order);
})
.catch(error => {
return res
.status(400)
.json({ error: "Fields are Not Correct" });
});
});
}
}
);
There are few things wrong with your code:
If you use await then you don't need to use then. You can just assign to a variable. Example:
const menu = await Menu.findOne({ _id: orderList[i]["menuId"] })
You don't need to wrap your loop and every await call in async functions. They are already in an async function.
You can write your response handler like this:
app.post('/create', async function(req, res) {
var myorder = {};
var orderList = [];
var ordDetail = [];
var UpdateMenus = [];
orderList = JSON.parse(JSON.stringify(req.body['OD']));
if (orderList.length > 0) {
const user = await User.findOne({ _id: req.user.id });
if (!user) {
return res.status(400).json({ error: 'User Not Found' });
}
var order = Order({
user: req.user.id
});
myorder = order;
for (i = 0; i < orderList.length; i++) {
const ordt = new Object({
menu: orderList[i]['menuId'],
order: myorder.id,
prize: orderList[i]['prize'],
quantity: orderList[i]['quantity']
});
const menu = await Menu.findOne({ _id: orderList[i]['menuId'] });
if (menu) {
if (menu.quantity >= ordt.quantity) {
menu.quantity = menu.quantity - ordt.quantity;
const editmenu = menu;
const updateMenu = await Menu.findOneAndUpdate(
{ _id: menu.id },
{ $set: editmenu },
{
new: true,
useFindAndModify: false
}
);
console.log(updateMenu);
ordDetail.push(ordt);
} else {
return res
.status(400)
.json({
error:
menu.MenuText +
'' +
ordt.quantity +
' Qunatity Is Not Available'
});
}
}
}
try {
const savedOrder = await order.save();
if (!savedOrder) {
return res.json({ error: 'Order is not saved' });
}
res.status(200).json(savedOrder);
} catch (error) {
return res.status(400).json({ error: 'Fields are Not Correct' });
}
}
});

Business logic works but Mongoose save doesn't

Hi I'm trying to save data from my shopping cart app to MongoDB database. In my cart controller folder, there are getAllProducts, addOneProduct, removeOneProduct and updateOneProducts methods. All of them run perfectly fine except for updateOneProducts.
The console.log shows:
GET all product { id: [1,2,4], qty: [1,1,1] }
UPDATE one product { id: [1,2,4], qty: [1,1,2] }
which indicate that the business logic works. However, the document is not updated on mLab.
User model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: String,
userID: String,
picture: String,
products: {
id: [Number],
qty: [Number],
}
});
const Users = mongoose.model('User', userSchema);
module.exports = Users;
updateOneProduct
const extractProduct = (user) => {
const product = {};
product.id = user.products.id;
product.qty = user.products.qty;
return product;
}
// if user is logged in n changes the qty of a product, update the qty in database
const updateOneProduct = (req, res) => {
// if (!req.user) return res.status(401).json({ error: 'Unauthorized' });
const userId = req.user._id;
const event = req.body.event;
const productId = req.body.id;
return Users.findById(userId)
.then(user => {
const qty = user.products.qty;
const index = user.products.id.indexOf(productId);
if (index === -1) {
throw new Error(`Product doesn't exist!`);
}
const regex = /^[0-9\b]+$/;
if (event === 'plus') {
qty[index] += 1;
} else if (event === 'minus') {
qty[index] -= 1;
} else if (regex.test(event) && event !== '0') {
qty[index] = Number(event);
}
if (qty[index] === 0) {
user.products.id.splice(index, 1);
qty.splice(index, 1);
}
return user.save();
})
.then(user => {
const product = extractProduct(user);
console.log('UPDATE one product', product);
return res.status(200).json(product);
})
.catch(error => res.status(400).json({ error }));
}
So I basically cloned user.products.qty array with const qty = [...user.products.qty], do operations on it and replace user.products.qty with it using user.products.qty = qty. Lastly, I save it with return user.save().
For some reason, I can't mutate subdocument project and save it. I have to replace the whole subdocument user.products then save for it to work. I think it might also have something to do with this being a PUT request.
// if user is logged in n changes the qty of a product, update the qty in database
const updateOneProduct = (req, res) => {
// if (!req.user) return res.status(401).json({ error: 'Unauthorized' });
const userId = req.user._id;
const event = req.body.event;
const productId = req.body.id;
return Users.findById(userId)
.then(user => {
const qty = [...user.products.qty];
const index = user.products.id.indexOf(productId);
if (index === -1) {
throw new Error(`Product doesn't exist!`);
}
const regex = /^[0-9\b]+$/;
if (event === 'plus') {
qty[index] += 1;
} else if (event === 'minus') {
qty[index] -= 1;
} else if (regex.test(event) && event !== '0') {
qty[index] = Number(event);
}
if (qty[index] === 0) {
user.products.id.splice(index, 1);
qty.splice(index, 1);
}
user.products.qty = qty;
return user.save();
})
.then(user => {
console.log('UPDATE - After save promise', user.products);
return res.status(200).json(user.products);
})
.catch(error => res.status(400).json({ error }));
}

Resources