UnhandledPromiseRejectionWarning: ValidationError: - javascript

I am a student I am trying to create a booking api and I need to authenticate if the user that log in is an admin that is allowed to add courses and if not an admin would return access denied..
module.exports.addCourse = (reqBody) => {
let newCourse = new Course({
name : reqBody.name,
description : reqBody.description,
price : reqBody.price
});
return newCourse.save().then((course,error) => {
if (!req.user.isAdmin) {
return res.status(401).send({ message: "Access denied" });;
} else if (reqBody.isAdmin = true){
return true;
};
});
};
router.post("/",auth.verify,(req,res)=>{
const data ={
course: req.body,
isAdmin: auth.decode(req.headers.authorization).isAdmin
}
courseController.addCourse(data).then(resultFromController=>res.send(resultFromController));
});
module.exports = router;
I wanted to add the course in my database if the user is an admin and does not allow if not an admin, I always get the error:
(node:17308) UnhandledPromiseRejectionWarning: ValidationError: Course validation failed: name: Course is required, description: Description is required, price: Price is required
even though I have given the name description and price and also added the token in the postman.

why are you using callback and promises? your syntax is not right...
// Alter 1
module.exports.addCourse = (reqBody) => {
const newCourse = new Course({
name : reqBody.name,
description : reqBody.description,
price : reqBody.price
});
return newCourse.save()
.then((course) => {
// ...code
}).catch((err) => {
// code error
})
}
router.post("/",auth.verify,(req,res)=>{
const data ={
course: req.body,
isAdmin: auth.decode(req.headers.authorization).isAdmin
}
courseController.addCourse(data).then(resultFromController=>res.send(resultFromController));
});
module.exports = router;
// alter 2
module.exports.addCourse = async (reqBody) => {
const newCourse = new Course({
name : reqBody.name,
description : reqBody.description,
price : reqBody.price
});
return await newCourse.save()
}
router.post("/",auth.verify, async (req,res)=>{
const data ={
course: req.body,
isAdmin: auth.decode(req.headers.authorization).isAdmin
}
try {
const response = await courseController.addCourse(data)
// response
} catch (err) {
// error response
}
});
module.exports = router;
// alter 3
module.exports.addCourse = (reqBody) => {
const newCourse = new Course({
name : reqBody.name,
description : reqBody.description,
price : reqBody.price
});
return new Promise((resolve, reject) => {
newCourse.save()
.then((course) => {
resolve(course)
}).catch((err) => {
reject(err)
})
})
}
router.post("/",auth.verify,(req,res)=>{
const data ={
course: req.body,
isAdmin: auth.decode(req.headers.authorization).isAdmin
}
return new Promise((resolve, reject) => {
courseController.addCourse(data)
.then((resultFromController) => {
resolve(res.send(resultFromController))
}).catch((error) => {
reject(res.send('error'))
})
})
});

Related

How can I check If a value of a Boolean Variable is false?

I don't know If I'm checking for the value of the boolean correctly
what this code does: the user creates a note for himself, his ID is on the note and it needs to belong to a category name that has to be in the category schema ( where my error happens )
exports.postAddNote = (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const error = new Error("validation failed, entered data is incorrect");
throw error;
}
const content = req.body.content;
const tags = req.body.tags;
const categoryName = req.body.categoryName;
let creator;
const note = new Note({
content: content,
categoryName: categoryName, // work
tags: tags,
creator: req.userId,
});
Category.find()
.select("-_id")
.select("-__v")
.select("-notesId")
.then((categories) => {
console.log(categories); //stripping everything but names off categories
const CategoryExists = categories.some(
(category) => category.name === categoryName
);
console.log(CategoryExists); // ~~~~~~~~~~ this logs correctly
if (CategoryExists === -0) { // ~~~~~~~~~~ what i want: if the value is false
return res.json({ Error: "The category you entered does not exist" });
}
note // ~~~~~~~~~~ the code stops here :/ it doesn't save the note
.save()
.then((note) => {
console.log("saved note");
User.findById(req.userId);
})
.then((user) => {
creator = user;
user.notes.push(note);
return user.save();
})
.then((result) => {
res.status(201).json({
info: {
dateCreated: new Date().toISOString(),
status: "Note Created Successfully",
creator: { _id: creator._id, email: creator.email },
},
});
})
.catch((err) => {
if (!err.statusCode) {
err.statusCode = 500;
}
});
})
.catch((err) => {
console.log(err);
next();
});
};
if (CategoryExists === -0)
should be
if (CategoryExists === false)
or just
if (!CategoryExists)
i believe. did you try that? not sure why you are using -0. the return value for some() is either going to be true or false.
try this:
if (!CategoryExists) {
return res.json({ Error: 'The category you entered does not exist' });
}

Nodejs Mongodb - Document Property is 'Undefined ' when printing

I'm learning Node, Express & Mongodb, hence a very much beginner. I'm developing a form where in there is a text field in which user will add data.
First, i need to check if that data exist or not in a master table. If exist, then i will return the record id else i will create a new record and return its id. Below is the code which I had tried but it's giving me id as undefined.
code.js (controller)
const toolsModel = require('../models/modTools');
const { validationResult } = require('express-validator');
module.exports = {
async saveCode(req, res)
{
var promiseToolId = () => {
return new Promise((resolve, reject) => {
let tool_exist = toolsModel.findOne({ title: req.body.inpTool });
if (tool_exist) {
console.log('tool_exist'); // prints this line
console.log(tool_exist._id); // gives undefined
console.log(tool_exist); // prints the object.
resolve(tool_exist._id);
}
else{
console.log('tool not exist. inserting');
var newTool = new toolsModel();
newTool.insert({title: req.body.inpTool, created_at: new Date()}, function(err, newRec) {
if(err){
console.log('err while inserting');
console.log(err);
reject(err);
}
else{
console.log('inserted');
console.log(newRec);
resolve(newRec._id);
}
});
}
});
};
let errors = validationResult(req);
if (!errors.isEmpty()){
console.log('validation error');
console.log(errors);
}
else{
console.log('form is valid'); // prints this line
// check if the tool exists in our database
var toolId = await (promiseToolId()); //anything here is executed after result is resolved
console.log('toolId ', toolId); // prints undefined
}
}
};
modTools.js (model)
const mongoose = require('mongoose'),
timeZone = require('mongoose-timezone'),
Schema = mongoose.Schema;
const toolsSchema = new Schema({
title: {type:String, required:true, trim: true},
created_at: {type: Date, default: Date.now},
});
toolsSchema.plugin(timeZone);
module.exports = mongoose.model('developmentTools', toolsSchema);
Please note that I'm using Auto-increment id for my model above which i had created using below codes.
db.createCollection("developmentTools");
db.developmentTools.insert ( {_id: "toolsId" , toolSeqValue : 0 } );
function getToolsNextID(seqName) {
var seqDoc = db.developmentTools.findAndModify({
query: { _id: seqName },
update: { $inc: { toolSeqValue: 1 } },
new: true
});
return seqDoc.toolSeqValue;
}
I know the way I'm accessing the object property tool_exist.title is correct but dont know why its giving me undefined.
M I wrong in implemenation of the Promise?
Please help.
Much Regards,
Javed Ansari
I'm able to resolve the issue. Listing the complete code if anyone faces the same issue. Thanks a lot to #ifaruki for sharing the informative URL and #slimane-amiar for his time.
async saveCode(req, res)
{
async function createTool(tool_ttle){
var newTool = new toolsModel({
title: tool_ttle,
created_at: new Date()
});
return new Promise((resolve, reject) => {
newTool.save((err, newRec) => {
if(err){
console.log('err while inserting');
reject(err);
}
else{
console.log('inserted');
resolve(newRec);
}
});
});
}
let errors = validationResult(req);
if (!errors.isEmpty()){
console.log('validation error');
console.log(errors);
}
else{
console.log('form is valid');
toolTitle = req.body.inpTool;
toolTitle = toolTitle.trim().toUpperCase();
let toolRecord = '';
// check if the tool exists in our database
try {
toolRecord = await toolsModel.findOne({ title: toolTitle });
if (toolRecord){
console.log('tool_exist');
console.log(toolRecord);
}
else{
console.log('tool not exist. inserting');
toolRecord = await createTool(toolTitle);
if(toolRecord){
console.log('new tool is created below');
console.log(toolRecord);
}
else
{
console.log('error in creating new tool');
console.log(toolRecord);
}
}
}
catch(error){
console.log('in catch');
console.log(error);
return error;
}
console.log('proceeding further');
}
}
You should add await to the query as it returns a promise, as follow
return new Promise( async (resolve, reject) => {
let tool_exist = await toolsModel.findOne({ title: req.body.inpTool });

nodemon app crashed - waiting for file changes before starting error after geting response from server

I'm developing a server in Node JS where there are two routes - Login and Signup.
Whenever I do signup, I am getting response as success and the data is being stored in MongoDB database successfully and then I'm getting [nodemon] app crashed - waiting for file changes before starting... in my console.
Note:- "The problem is in signup only not in login".
postSignup() will be called when a user requests for signup which is validated according to schema and inserted in database.
I'm providing the code related to signup.
signup.js
const { User } = require("../../models");
const createError = require("http-errors");
const postSignup = (req, res, next) => {
//validation
const validation = User.validate(req.body);
if (validation.error) {
const error = new Error(validation.error.message);
error.statusCode = 400;
return next(error);
}
//check Existence
const user = new User(req.body);
user
.checkExistence()
.then((result) => {
if (result.check) {
const error = new Error(result.message);
error.statusCode = 409;
return next(error);
}
user.save((err) => {
if (err) {
console.log(err);
return next(createError(500));
}
res.status(201).json({
message: "User has been Successfully Created",
});
});
})
.catch((err) => {
next(createError(500));
});
};
module.exports = {
postSignup,
};
User.js
const { dbCon } = require("../configuration");
const { userValidator, logSchema } = require("../validator");
const { hashSync, compareSync } = require("bcryptjs");
class User {
constructor(userData) {
this.userData = { ...userData };
}
save(cb) {
dbCon("users", (db) => {
try {
const hashPass = hashSync(this.userData["password"], 12);
this.userData["password"] = hashPass;
db.insertOne(this.userData);
cb();
} catch (err) {
cb(err);
}
});
}
checkExistence() {
return new Promise((resolve, reject) => {
dbCon("users", async (db) => {
try {
const user = await db.findOne({
$or: [
{ username: this.userData["username"] },
{ email: this.userData["email"] },
],
});
if (!user) {
resolve({
check: false,
});
} else if (this.userData["username"] === user.username) {
resolve({
check: true,
message: "username already exists",
});
} else if (this.userData["email"] === user.email) {
resolve({
check: true,
message: "email already exists",
});
}
} catch (err) {
reject(err);
}
});
});
}
static validate(userData) {
//console.log(userData);
return userValidator.validate(userData);
}
module.exports = User;
userValidator.js
const Joi = require("#hapi/joi");
const schema = Joi.object({
username: Joi.string().alphanum().required().min(3).max(15),
email: Joi.string().email().required(),
password: Joi.string()
.pattern(
new RegExp(
"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}$"
)
)
.message(
"Password must contain at least eight characters, at least one number and both lower and uppercase letters and special characters"
)
.required(),
first_name: Joi.string().required(),
last_name: Joi.string().required(),
});
module.exports = {
schema
};
I faced the same issue. I don't know what was the issue but I tried to change node version in mongo db connect and then used the new connect URL.
If it still doesn't work, then try to create new cluster and connect it again with new cluster.

Avoid duplicates when saving new data with mongoose

I am working on an application where I can save destinations to my Mongo DB. I would like to throw a custom error when trying to save a destination that already exsist in the DB. Mongoose prevents that from happening but I want clear and userfriendly error handling.
// post a new destination
router.post('/',
(req, res) => {
const newCity = new cityModel(
{
name: req.body.name,
country: req.body.country
}
)
newCity.save()
.then(city => {
res.send(city)
})
.catch(err => {
res.status(500).send('Server error')
})
});
Before saving a new destination, you can check if there is document already using findOne method, and if it exists you can return a custom error.
router.post("/", async (req, res) => {
const { name, country } = req.body;
try {
const existingDestination = await cityModel.findOne({name,country});
if (existingDestination) {
return res.status(400).send("Destionation already exists");
}
let newCity = new cityModel({ name, country });
newCity = await newCity.save();
res.send(city);
} catch (err) {
console.log(err);
res.status(500).send("Server error");
}
});
Note that I guessed the duplication occurs when the same country and name exist. If it is not what you want, you can change the query in findOne.
Since you've created unique index, When you try to write duplicate then the result would be :
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
}
})
Your code :
Constants File :
module.exports = {
DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
DUPLICATE_DESTINATION_CODE: 4000
}
Code :
//post a new destination
const constants = require('path to constants File');
router.post('/',
(req, res) => {
const newCity = new cityModel(
{
name: req.body.name,
country: req.body.country
}
)
try {
let city = await newCity.save();
res.send(city)
} catch (error) {
if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
/* In case if your front end reads your error code &
it has it's own set of custom business relates messages then form a response object with code/message & send it.
if (error.code == 11000) {
let respObj = {
code: constants.DUPLICATE_DESTINATION_CODE,
message: constants.DUPLICATE_DESTINATION_MSG
}
res.status(400).send(respObj);
} */
}
res.status(500).send('Server error');
})

Node.js, RESTIFY, Mongoose, Promise: Trying to $push an array to update but not working

I used this method because I am storing an array of classified messages, I would like to vividly understand why it doesn't update.
Here's the db.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = mongoose.Types.ObjectId;
const usersessionSchema = new Schema({
fb_id: String,
fb_name: String,
fb_profpic: String,
message_body: [
{
message: String,
message_type: String,
timestamp: String
}
],
admin: Boolean,
branch: String
});
const model = (prefix) => {
prefix = prefix || '';
console.log(prefix);
if (prefix.length > 0) {
return mongoose.model(prefix + "-usersessions", usersessionSchema);
} else {
return new Error('Undefined collection prefix!');
}
}
/** Push message into message body*/
module.exports.pushsession =
async(model, id, data) => {
return new Promise((resolve, reject) => {
console.log(data);
model.findOneAndUpdate({fb_id: id}, {$push: {data}},{safe: true})
.then(res => {
console.log(res);
/
resolve(res);
})
.catch(err => {
reject(err);
console.log(err);
throw err;
});
});
}
Here's the controller.js:
/** Push usersession message */
module.exports.pushsession =
async(req, res, next) => {
try {
//jwt.validateToken(req);
var en = "en";
var dateEn = moment().locale(en);
format = "MM/DD/YYYY h:mm:ss A"; //h:mm:ss.SSS if you want miliseconds
var datetime_now = dateEn.format(format);
console.log(datetime_now);
var request = {
message_body: {
message: req.body.message,
message_type: req.body.message_type,
timestamp: datetime_now
}
};
const model = usersessionDB(req.query['client']);
const id = req.body.fb_id;
const result = await usersessionDB.pushsession(model, id, request);
if (result) {
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
} else {
response.failure(res, next, {
message: 'ID does not exist'
}, 404, response.HTTP_STATUS_CODES.not_found);
}
} catch (err) {
response.failure(res, next, err, 500, response.HTTP_STATUS_CODES.internal_server_error);
}
}
Here's the route.js:
const controller = require('../controller/usersession-controller');
module.exports =
(server) => {
server.post('/api/session', controller.create);
server.get('/api/session', controller.list);
server.get('/api/session/:id', controller.get);
server.put('/api/session/:id', controller.update);
server.del('/api/session/:id', controller.delete);
server.put('/api/pushsession', controller.pushsession);
}
Visually, if you run this using postman, you can see that it display the one I want to search and update
Result of the postman
What I want to happen is to insert another set of array inside that message_body
Data I've inserting
My desired output
This code is working without that promise something, but in my project it is needed so I can't remove that thing.
So, based on :
This code is working without that promise something
i can point a thing or two,
in db.js
module.exports.pushsession =
async(model, id, data) => {
return new Promise((resolve, reject) => {
you don't need async since you're returning a promise so replace this
async(model, id, data) => {
with
(model, id, data) => {
and since you're returning a promise and removed async , you don't need the await on the other side ( controller.js ), so this
const result = await usersessionDB.pushsession(model, id, request);
if (result) {
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
} else {
should be
usersessionDB.pushsession(model, id, request).then(
(result) => { // when resolved
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
},
(err) => { // when rejected
response.failure(res, next, {
message: 'ID does not exist'
}, 404, response.HTTP_STATUS_CODES.not_found);
});
this is a comparison between async/await and promises : Javascript Promises vs Async Await. Difference?
and here's some good examples of using promises : https://medium.com/dev-bits/writing-neat-asynchronous-node-js-code-with-promises-32ed3a4fd098
i think your $push is ok but you already said
This code is working without that promise something
i hope this helps and Good luck :)
I tried cleaning my code
here's the controller.js:
/** Push usersession message */
module.exports.pushsession =
async (req, res, next) => {
try {
//jwt.validateToken(req);
var en = "en";
var dateEn = moment().locale(en);
format = "MM/DD/YYYY h:mm:ss A"; //h:mm:ss.SSS if you want miliseconds
var datetime_now = dateEn.format(format);
console.log(datetime_now);
var data = {
message: req.body.message,
message_type: req.body.message_type,
timestamp: datetime_now
};
const model = usersessionDB(req.query['client']);
const id = req.body.fb_id;
console.log(id);
const result = await usersessionDB.pushsession(model, id, data).then(
(result) => { // when resolved
response.success(res, next, result, 200, response.HTTP_STATUS_CODES.ok);
},
(err) => { // when rejected
response.failure(res, next, {
message: 'ID does not exist'
}, 404, response.HTTP_STATUS_CODES.not_found);
});
} catch (err) {
response.failure(res, next, err, 500, response.HTTP_STATUS_CODES.internal_server_error);
}
}
Here's the db.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ObjectId = mongoose.Types.ObjectId;
const usersessionSchema = new Schema({
fb_id: String,
fb_name: String,
fb_profpic: String,
message_body:[{
message: String,
message_type: String,
timestamp: String
}],
admin: Boolean,
branch: String
});
/** Push message into message body*/
module.exports.pushsession =
async(model, id, data) => {
console.log(data);
return new Promise((resolve, reject) => {
model.findOneAndUpdate({fb_id: id}, { $push: { message_body: data }})
.then(res => {
console.log(res);
resolve(res);
})
.catch(err => {
reject(err);
console.log(err);
throw err;
});
});
}
Out of the blue after I tried to replace $push with $set then again I replace it with $push, it worked.
I don't if there's a difference, or I miss something, feel free to point it out.

Categories