errors generated by express validator with node express [closed] - node.js

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I am using nodejs, express, & express-validator. I am trying to use express validator on my sign_up page . Express-validator generates the errors in an array of objects.
the error:
Result {
formatter: [Function: formatter],
errors: [
{
value: undefined,
msg: 'Please Enter a Valid Username',
param: 'username',
location: 'body'
},
{
value: undefined,
msg: 'Please enter a valid email',
param: 'email',
location: 'body'
},
{
value: undefined,
msg: 'Please enter a valid password',
param: 'password',
location: 'body'
}
]
}
I use postman to test the register operation
and send the following in the request:
{
"username":"ruba",
"email":"test#gmail.com",
"password":"1234544545#"
}
my user.js code:
// Filename : user.js
const express = require("express");
const { check, validationResult} = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const router = express.Router();
const User = require("../model/User");
/**
* #method - POST
* #param - /signup
* #description - User SignUp
*/
router.post(
"/signup",
[
check("username", "Please Enter a Valid Username")
.not()
.isEmpty(),
check("email", "Please enter a valid email").isEmail(),
check("password", "Please enter a valid password").isLength({
min: 6
})
],
async (req, res) => {
const errors = validationResult(req);
console.log(errors);
if (!errors.isEmpty()) {
console.log("error sign");
return res.status(400).json({
errors: errors.array()
});
console.log("error sign2");
}
console.log("error sign3");
const {
username,
email,
password
} = req.body;
try {
let user = await User.findOne({
email
});
if (user) {
return res.status(400).json({
msg: "User Already Exists"
});
}
user = new User({
username,
email,
password
});
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
"randomString", {
expiresIn: 10000
},
(err, token) => {
if (err) throw err;
res.status(200).json({
token
});
}
);
} catch (err) {
console.log(err.message);
res.status(500).send("Error in Saving");
}
}
);
module.exports = router;
my index code:
const express = require("express");
const bodyParser = require("body-parser");
const user = require("./routes/user"); //new addition
const InitiateMongoServer = require("./config/db");
// Initiate Mongo Server
InitiateMongoServer();
const app = express();
// PORT
const PORT = process.env.PORT || 4000;
// Middleware
//app.use(bodyParser.json());
app.use(express.json());
app.get("/", (req, res) => {
res.json({ message: "API Working" });
});
app.use("/user", user);
app.listen(PORT, (req, res) => {
console.log(`Server Started at PORT ${PORT}`);
});
so please help me. what is the problem??
Edit: It's solved. the problem was in the postman settings (the contents type must be JSON)

Did you enabled
app.use(express.json());
Because I cant see any kind of problem with you code (about the express-validator).
I suggest you after this fix, you to change check to body since you wants only to check the content of body.
I'm using an middleware to helps to me keep my code short and legible, and I'll share with you
function validation(validations: Array<ValidationChain>) {
return async (req: Request, _res: Response, next: NextFunction) => {
await Promise.all(validations.map((v) => v.run(req)));
const errors = validationResult(req);
if (errors.isEmpty()) {
return next();
}
const msg = errors
.array()
.map((er) => `${er.param}`)
.join(', ');
const issue = new Issue(400, `missing or invalid params: ${msg}`);
next(issue);
};
}
The usage:
router.post(
'/login',
validation([body('email').isEmail(), body('password').isLength({ min: 5, max: 30 })]),
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
...
});
``'

Related

Cannnot send request to the users/signup route and failing to make connection to the database

Below is the sign up controller...
const signup = async (req, res) => {
const { name, username, profilePhoto, email, password } = req.body;
console.log(req.body);
try {
const existingUser = await User.findOne({ email });
if (existingUser)
return res.status(404).json({ message: "User already exist." });
const hashedPassword = await bcrypt.hash(password, 12);
const result = await User.create({
name,
username,
email,
profilePhoto,
password: hashedPassword,
});
const token = jwt.sign(
{
name: result.name,
email: result.email,
username: result.username,
id: result._id,
},
"test",
{
expiresIn: "1h",
}
);
res.status(200).json({ result: result, token });
} catch (error) {
res.status(500).json({ message: "Something went wrong" });
}
};
This is the code for action for SignUp
export const signup = (formData, history) => async (dispatch) => {
try {
// sign up the user
const { data } = await api.signUp(formData);
dispatch({ type: "AUTH", data });
toast.success("Signed Up successfully");
history.push("/feedbacks");
} catch (error) {
dispatch({ type: "ERROR", data: error?.response?.data });
toast.error(error?.response?.data?.message);
}
While signing in I am getting proper response on the console in the backend. But unable to SignUp.
Error:
But the output of console has the response:
Other functionalities are also working in sync with Front-End
routes
Index.js
const express = require("express");
const connectDB = require("./config/db");
const cors = require("cors");
const app = express();
const feedbacksRoutes = require("./routes/feedbacks");
const userRoutes = require("./routes/users");
app.use(express.json({ extended: false }));
app.use(cors());
// connect to mongoDB
connectDB();
app.use("/feedbacks", feedbacksRoutes);
app.use("/user", userRoutes);

Promise { <pending> } React bcrypt hashing the Password [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 months ago.
I am creating a Login/Registration Form Using Nodejs. I am hashing the password entered by the user using bcrypt.js but when I assign the password to a variable so that I push that to the database I get this error "Promise { pending }".
I am learning nodejs and react so I do not know too much about this can someone help me.
Thanks!
The Code That I am running is:
################################
const express = require('express');
const app = express();
const mysql = require('mysql2');
const bcrypt = require('bcryptjs');
const cors = require('cors');
// Need this to make api request from backend
app.use(cors());
/**using this express will format the data automatically in json format */
app.use(express.json()); /**Use This Otherwise you get the req.body undefined */
const port = 3001;
const securePassword = async (password) => {
const passwordHash = await bcrypt.hash(password, 4);
return passwordHash;
};
const db = mysql.createConnection({
user: 'root',
host: 'localhost',
password: 'newpassword',
database: 'INSTAGRAM',
});
// Getting Data From Signup Form of React
app.post('/signup', (req, res) => {
const emailaddress = req.body.emailaddress;
const fullname = req.body.fullname;
const username = req.body.username;
const password = req.body.password;
const hashPass = securePassword(password);
console.log(hashPass);
// Checking If Use Already Exist
db.query(
'SELECT * FROM USER WHERE username = ? OR email = ? ',
[username, emailaddress],
(err, result) => {
if (err) {
res.send({ err: err });
} else {
if (result.length > 0) {
res.send({ message: 'Username/Email Already Exist' });
} else {
db.query(
'INSERT INTO USER (username, fullname, email, password) VALUES (?, ?, ?, ?)',
[username, fullname, emailaddress, hashPass],
(err, result) => {
if (err) {
res.send(err);
} else {
res.send(result);
}
}
);
}
}
}
);
});
// Starting the server on port 3001
app.listen(port, () => {
console.log(`SERVER STARTED ${port}`);
});
First of all for better and more professional coding try to break your code into multiple functions in multiple .js files .
then you should pass a function to validate the inputs otherwise any data can be passed to db without being validated .
and then you can use this codes for user Registration :
app.js file :
const express = require('express');
const app = express();
const userRouter = require('./routes/user.routes');
app.use(express.json());
app.use('/user', userRouter);
user.routes file :
const express = require('express');
const userRouter = express.Router();
const {httpHandleSignUp} = require('../controllers/user/user.controller');
userRouter.post('/signup', httpHandleSignUp);
module.exports = userRouter
and then for handling Registration you can create a controller file and first of all check the inputs :
httpHandleSignUp controller code :
async function handleSignUp(req, res) {
const values = req.body
const errors = await validateInputs(values, res);
if(errors.length == 0) {
await addUserToDB(values, res);
} else {
res.json(errors)
}
}
you can use any validation you want like code below :
async function validateInputs(values, res) {
let errors = [];
if(!values.name || !values.email || !values.password) {
errors.push('missing required inputs');
}
if(!/\S+#\S+\.\S+/.test(values.email)) { // regex : string#string.string
errors.push('invalid email address ');
}
if(values.password.length < 8) {
errors.push('entered password is too short !');
}
if(await checkDbForEmail(values.email)) {
errors.push('a user with this email already registered !');
}
// TODO : add more validation
return errors;
}
and also you need to a function to check db for already registered users which used in above function :
async function checkDbForEmail(email) {
return await user.findOne({
email: email
});
}
now if there is NO errors the user will be added to DB by this function :
async function addUserToDB(values, res) {
bcrypt.hash(values.password, saltRounds)
.then(hashedPass => {
user.create({
name: values.name,
email: values.email,
password: hashedPass
}, (err, user) => {
res.json({
ok : 'user added to db successfully',
data: {
name: user.name,
email: user.email
}
});
});
})
.catch( (err) => console.log(err));
}
tip: this code works with mongo you may need to changes DB functions.

Cannot set headers after they are sent to the client Nodejs and Angular

I am developing login and register services with Nodejs Express.
Every request in postman I get same error:
Funny thing is that I get response in postman (register, login i even receive my JWT token but every time after request I can't do anything without restarting the service in my terminal)
My index.ts
import express from "express";
const https = require("https");
import cors from "cors";
import mongoose from "mongoose";
const app = express();
//import routes
const usersRoute = require("./routes/users");
//Middleware
app.use(cors());
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
//route midddlewares
app.use("/api/users", usersRoute);
//connect to db
mongoose
.connect("mongodb://localhost:27017/loginregister")
.then(() => {
console.log("connected to database");
})
.catch(() => {
console.log("connection failed!");
});
const PORT = 3000;
app.listen(PORT, () => console.log(`Server up and running on port ${PORT}`));
And my users.ts
import express from "express";
const router = express.Router();
const User = require("../models/User");
const {
registerValidation,
loginValidation,
} = require("../middleware/validation");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const secretKey = "f43g34gergeerg";
const verifyToken = require("../middleware/verifyToken");
//REGISTER user
router.post("/register", async (req, res) => {
//VALIDATE DATA from Joi, before register
const { error } = registerValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
//check if user is alredy in database
const emailExist = await User.findOne({ email: req.body.email });
if (emailExist) return res.status(400).send("Email already exists");
//encrypt password z bcryptjs modulom
const salt = await bcrypt.genSalt(10);
const hashPassword = await bcrypt.hash(req.body.password, salt);
//create new user
const user = new User({
email: req.body.email,
password: hashPassword,
});
try {
//save new user
const savedUser = await user.save();
//res.json(savedUser);
res.json({ user: user._id });
} catch (err) {
res.json({ message: err });
}
});
//LOGIN
router.post("/login", async (req, res) => {
const { error } = loginValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
//check if email exists
const user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("Email doesn't exist");
//password is correct
const validPass = await bcrypt.compare(req.body.password, user.password);
if (!validPass) return res.status(400).send("Invalid password");
//create and send a json web token
const token = jwt.sign({ _id: user._id }, secretKey, { expiresIn: "1h" });
res.header("auth-token", token).send(token);
res.send("Logged in!");
});
module.exports = router;
File: verifyToken.ts
const jwt = require("jsonwebtoken");
const secretKey = "f43g34gergeerg";
module.exports = (req: any, res: any, next: any) => {
const token = req.header("auth-token");
if (!token) return res.status(401).send("Access denied");
try {
const verified = jwt.verify(token, secretKey);
req.user = verified;
next();
} catch (err) {
res.status(400).send("Invalid token");
}
};
My frontend (Angular) code:
login.component.ts
export class LoginComponent implements OnInit {
email: string = '';
password: string = '';
constructor(public authService: AuthService, private router: Router) {}
ngOnInit(): void {}
onLogin(form: NgForm) {
if (form.invalid) {
return;
}
this.authService.login(form.value.email, form.value.password);
console.log(form.value);
}
}
auth.service.ts file
export class AuthService {
constructor(private http: HttpClient) {}
login(email: string, password: string) {
const user: User = { email: email, password: password };
this.http
.post('http://localhost:3000/api/users/login', user)
.subscribe((response: any) => {
console.log(response);
});
}
}
And error in web is:
SOLVED:
First error in the terminal (Cannot set headers after they are sent to the client) was solved with the accepted answer from Shivam Sood) and for solving the second error in the error tab in my browser was solved by defining responseType: 'text' in my http.post() request in my auth.service.ts file
Error is coming from this line in your login route
res.header("auth-token", token).send(token);
res.send("Logged in!");
You are sending response twice res.send()
You will have to remove res.send("Logged in!"); in order to fix the issue.
UPDATE
I suspect the issue with angular is that, by default angular HTTP expects JSON data, but the data you are sending from backend is text. That is why parsing is failing.
You can update res.send to
res.header("auth-token", token).json({token});

Error: Route.post() requires a callback function but got a [object Undefined] throw new Error(msg);

when I try to run the server, I get Route.get() requires callback functions but got a [object Undefined] error. If I comment out the router.post('/signup',validateRequest,isRequestValidated,signup)
everything works okay.
does anyone know what the problem might be and how to fix it?
router file:
const express = require('express');
const { signup, signin } = require('../controller/auth')
const {validateRequest,isRequestValidated} =require('../validators/auth')
const router = express.Router();
router.get('/signin', signin)
router.post('/signup',validateRequest,isRequestValidated,signup)
//Auth Guard
// router.post('/profile', requireSignin, (req, res) => {
// res.status(200).json({ user: 'profile' })
// })
module.exports = router;
validator file:
const { check, validationResult } = require('express-validator')
exports.validateSignUpRequest = [
check('firstName')
.notEmpty()
.withMessage('First Name is Required..!'),
check('lastName')
.notEmpty()
.withMessage('Last Name is Required..!'),
check('email')
.isEmail()
.withMessage('Plz Enter a Valid Email Address..'),
check('password')
.isLength({ min: 6 })
.withMessage('Password must be more than 6 characters')
];
exports.isRequestValidated = (req, res, next) => {
const errors = validationResult(req)
if (errors.array().length > 0) {
return res.status(400).json({ errors: errors.array()[0].msg })
}
next()
};
controller file :
const User = require('../models/user');
const jwt = require('jsonwebtoken');
const env = require('dotenv')
env.config()
// const {validationResult} = require('express-validator')
//SIGNUP:
exports.signup = (req, res) => {
User.findOne({ email: req.body.email })
.then((user) => {
if (user) {
res.status(400).json('User already exists')
}
else {
const _user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: req.body.password,
username: Math.random().toString()
})
_user.save()
res.status(200).json(_user)
}
})
.catch((err) => {
res.status(500).json("Something Went Wrong")
})
}
change:
const {validateRequest,isRequestValidated} =require('../validators/auth')
to:
const {validateSignUpRequest,isRequestValidated} =require('../validators/auth')
and change:
router.post('/signup',validateRequest,isRequestValidated,signup)
to:
router.post('/signup',validateSignUpRequest,isRequestValidated,signup)

I am getting this error TypeError: Cannot read properties of undefined (reading 'header') , I am trying to middleware to get users data

I have created a middleware folder inside it I have created fetchuser.js
This is my fetchuser.js code, I have created getuser endpoint so that I can authenticate the user.
I have created a new post request in my thunderclient, but because of this error I am not able to do anything
...
const jwt = require('jsonwebtoken');
const JWT_SECRET = "Saurabhisgood$ouy";
const fetchuser = (req, res, next) => {
// Get the user from jwt token and id to req object
const token = req.header('auth-token');
if (!token) {
res.status(401).send({ error: "Please authenticate using a valid token" })
}
try {
const data = jwt.verify(token, JWT_SECRET)
req.user = data.user;
next();
} catch (error) {
res.status(401).send({ error: "Please authenticate using a valid token" })
}
}
module.exports = fetchuser();
...
This is auth.js file
...
const express = require('express');
const User = require('../models/User');
const router = express.Router();
const { body, validationResult } = require('express-validator');
const bcrypt = require('bcryptjs');
const JWT_SECRET = "Saurabhisgood$ouy";
const jwt = require('jsonwebtoken');
const fetchuser = require('../middleware/fetchuser');
// Create a user using : POST "/api/auth/createuser". Doesn't require auth. Dosen't require login
router.post('/createuser', [
body('name', 'Name should be atleast 3 characters').isLength({ min: 3 }),
body('email', 'Email should be unique').isEmail(),
body('password', 'Password must be atleast 5 characters').isLength({ min: 5 }),
], async (req, res) => {
// If there are errors then you will get bad request
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Check whether the user with the same email exists
try {
let user = await User.findOne({ email: req.body.email });
if (user) {
return res.status(400).json({ error: "The user with this email already exists" })
}
const salt = await bcrypt.genSalt(10);
const secPass = await bcrypt.hash(req.body.password, salt);
// Create a new user
user = await User.create({
name: req.body.name,
email: req.body.email,
password: secPass
});
const data = {
user: {
id: user.id
}
}
const authToken = jwt.sign(data, JWT_SECRET);
// console.log(jwtData);
// res.json(user);
res.json({authToken});
} catch (error) {
console.error(error.message);
res.status(500).send("Internal server error")
}
})
// Authenticate a user using : POST "/api/auth/login". Doesn't require auth. Dosen't require login
router.post('/login', [
body('email', 'Email should be unique').isEmail(),
body('password', 'Password cannot be blank').exists(),
], async (req, res) => {
// If there are errors then you will get bad request
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
};
const { email, password } = req.body;
// Check whether the user with the same email exists
try {
let user = await User.findOne({email});
if (!user) {
return res.status(400).json({ error: "Please enter the valid credentials" })
}
const passwordComapare= await bcrypt.compare(password, user.password);
if (!passwordComapare) {
return res.status(400).json({ error: "Please enter the valid credentials" })
}
const data = {
user: {
id: user.id
}
}
const authToken = jwt.sign(data, JWT_SECRET);
// console.log(jwtData);
// res.json(user);
res.json({authToken});
} catch (error) {
console.error(error.message);
res.status(500).send("Internal server error")
}
})
// Get details of logged in user using : POST "/api/auth/getuser". Require login
router.post('/getuser', fetchuser , async (req, res) => {
try {
userId= req.user.id;
const user= await User.findById(userId).select("-password");
res.send(user);
} catch (error) {
console.error(error.message);
res.status(500).send("Internal server error")
}
})
module.exports = router
...
You invoking the middleware automatically, change:
module.exports = fetchuser();
to:
module.exports = fetchuser;

Resources