express .post function try catch error is failing and shows internal server error MERN Stack - express

enter image description here
app.post("/api/signin", async (req, res) => {
try {
const { error } = validate1(req.body);
if (error)
return res.status(400).send({ message: error.details[0].message });
const user1 = await user.findOne({ email: req.body.email });
if (!user1)
return res.status(401).send({ message: "Invalid Email or Password" });
const validPassword = await bcrypt.compare(
req.body.password,
user.password
);
if (!validPassword)
return res.status(401).send({ message: "Invalid Email or Password" });
const token = user.generateAuthToken();
res.status(200).send({ data: token, message: "logged in successfully" });
} catch (error) {
res.status(500).send({ message: "Internal Server Error" });
}
});
I was trying to verify user and sign him in but I'm getting error that Internal server issue

Related

Getting error in MERN stack Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I am new to MERN. I was using this code below . I followed a youtube tutorial and it was working fine for me for 4 to 5 days but now suddenly it has stopped working. I didn't change anything. I am not able to login, logout or even fetch data. My postman is giving positive results using these api but it won't work on my code. I want to remind you guys again, it was working fine for 4 to 5 days.
const User = require("../model/user");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const signup = async (req, res, next) => {
const { fname, lname, email, password, role, phone } = req.body;
let existingUser;
try {
existingUser = await User.findOne({ email: email });
} catch (err) {
console.log(err);
}
if (existingUser) {
return res.status(400).json({ message: "user already exists" });
}
const hashedPassword = bcrypt.hashSync(password);
const user = new User({
fname,
lname,
email,
password: hashedPassword,
phone,
role,
});
try {
await user.save();
} catch (err) {
console.log(err);
}
return res.status(201).json({ message: user });
};
const login = async (req, res, next) => {
const { email, password } = req.body;
let existingUser;
try {
existingUser = await User.findOne({ email: email });
} catch (err) {
console.log(err);
}
if (!existingUser) {
return res
.status(400)
.json({ message: "user doesn't exist. Please signup" });
}
const isPasswordCorrect = bcrypt.compareSync(password, existingUser.password);
if (!isPasswordCorrect) {
return res.status(401).json({ message: "invalid email or password" });
}
const token = jwt.sign({ id: existingUser._id }, "change1122", {
expiresIn: "1h",
});
res.cookie(String(existingUser._id), token, {
path: "/",
expires: new Date(Date.now() + 1000 * 3600),
httpOnly: true,
sameSite: "lax",
});
return res
.status(200)
.json({ message: "user logged in sucessfully", user: existingUser, token });
};
const verifyToken = (req, res, next) => {
const cookies = req.headers.cookie;
const token = cookies.split("=")[1];
if (!token) {
res.status(404).json({ message: "no token found" });
}
jwt.verify(String(token), "change1122", (err, user) => {
if (err) {
return res.status(404).json({ message: "invalid token" });
}
req.id = user.id;
});
next();
};
const getUser = async (req, res, next) => {
const id = req.id;
let user;
try {
user = await User.findById(id, "-password");
} catch (err) {
console.log(err);
}
if (!user) {
res.status(404).json({ message: "user not found with the id" });
}
return res.status(200).json({ user });
};
const logout = async (req, res, next) => {
const cookies = req.headers.cookie;
console.log(cookies);
const token = cookies.split("=")[1];
if (!token) {
res.status(404).json({ message: "no token found" });
}
const user = req.id;
res.clearCookie(`${user}`);
req.cookies[`${user}`] = "";
return res.status(200).json({ message: "successfully logged out" });
};
exports.signup = signup;
exports.login = login;
exports.verifyToken = verifyToken;
exports.getUser = getUser;
exports.logout = logout;
Here is the error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:372:5) at ServerResponse.setHeader (node:_http_outgoing:576:11)
at ServerResponse.header (E:\Reacct\pos\server\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (E:\Reacct\pos\server\node_modules\express\lib\response.js:174:12)
at ServerResponse.json (E:\Reacct\pos\server\node_modules\express\lib\response.js:278:15)
at getUser (E:\Reacct\pos\server\controller\user-controller.js:86:25)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
I think i have an issue with cookies or token, I am new so i don't understand it properly.

user.toJSON is not a function

I'm trying to use authentication using passport and jwt, and when I use user.toJSON() to create tokens it give me following error
const User = require('../../../models/user');
const jwt = require('jsonwebtoken');
module.exports.createSession = async function(req, res){
try{
let user = User.findOne({email: req.body.email});
if(!user || user.password != req.body.password){
return req.json(422,{
message: 'Invalid Username or Password'
})
}
return res.json(200, {
message: 'Sign in Successful, here is your token keep it safe',
data:{
token: jwt.sign(user.toJSON(), 'codeial', {expiresIn :'100000'})
}
})
}catch(err){
console.log('***********', err);
return res.json(500,{
message: 'Internal Server Error'
})
}
}
Anyone Can help me in resolving this error?
try just to remove the .toJSON
data:{
token: jwt.sign(user, 'codeial', {expiresIn :'100000'})
}
or
JSON.stringify(user);

Make the code run using backend development

const router = require("express").Router();
const { User, validate } = require("../models/user");
const bcrypt = require("bcryptjs");
router.post("/register", async (req, res) => {
try {
const { error } = validate(req.body);
if (error)
return res.status(400).send({ message: error.details[0].message });
const user = await User.findOne({ email: req.body.email });
if (user)
return res
.status(409)
.send({ message: "User with given email already exists!" });
const salt = await bcrypt.genSalt(Number(process.env.SALT));
const hashPassword = await bcrypt.hash(req.body.password, salt);
await new User({ ...req.body, password: hashPassword }).save();
res.status(201).send({ message: "User Created Successfully!" });
} catch (error) {
res.status(500).send({ message: "Internal Server Error" });
}
});
module.exports = router;
but when i tested it in POSTMAN it says
"
{
"message": "Internal Server Error"
}
"
WHAT COULD BE THE PROBLEM? T_T

IONIC 4 login gets response, but can't read the custom error message

I created a login for IONIC 4 in Express, the login works, but when a password is invalid, I want to show the custom message. I'm not able to show it.
Here is the response I get back in the browser console:
error: Object { message: "Password not valid!", status: "401" }
headers: Object { normalizedNames: Map(0), lazyUpdate: null, lazyInit: lazyInit()}
message: "Http failure response for http://localhost:3000/login: 401 Unauthorized"
name: "HttpErrorResponse"
ok: false
status: 401
statusText: "Unauthorized"
url: "http://localhost:3000/login"
My login code in express:
const findUserByEmail = (email, cb) => {
return mc.query('SELECT * FROM user_login WHERE email = ?',[email], (err, row) => {
cb(err, row); console.log(err);
});
}
router.post('/login', (req, res) => {
const email = req.body.email;
const form_password = req.body.password;
//console.log(form_password );
findUserByEmail(email, (err, user) => {
console.log(user);
console.log("Test1");
if (err) return res.status(500).send({ "message": 'Server error!!', "status": '500' });
console.log("Test2");
if (!user[0]) return res.status(404).send({ "message": 'User not found!', "status": '404' });
console.log("Test3");
console.log(user);
const result = bcrypt.compareSync(form_password, user[0].password);
if (!result) return res.status(401).send({ "message": 'Password not valid!!', "status": '401' });
const expiresIn = 24 * 60 * 60;
const accessToken = jwt.sign({ id: user[0].id }, SECRET_KEY, {
expiresIn: expiresIn
});
res.status(200).send({ "user": user, "access_token": accessToken, "expires_in": expiresIn, "message": 'Success!!', "status": '200' });
});
});
My login code in IONIC 4:
login(form){
this.authService.login(form.value).subscribe(result => {
this.router.navigateByUrl(`dashboard`);
},
error => {
this.showError = true;
console.log(error);
this.errorMessage = error.statusText;
});
}
I want to show "Password not valid!!", however its showing "Unauthorized"
pay aftention to the object returned.
this.errorMessage = error.statusText;
should be
this.errorMessage = error.error.message

Using async in express

Below is my rest API endpoint /signup. The problem I'm having now is that the endpoint does not stop after validateEmail. Even after it failed email form-validation and res.send() is done, the endpoint continues. So I'm keep getting the error 'Error: Can't set headers after they are sent.'. I would like to be able to finish the endpoint inside its functions like validateEmail , checkEmailInUse, makeUser, and so on.
router.post("/signup", async (req, res, next) => {
const { email, password } = req.body;
const users = req.app.get("users");
validateEmail(res, email);
await checkEmailInUse(res, users, email);
const user = await makeUser(res, users, email, password);
res.send({ message: "POST signup request OK", user });
});
function validateEmail(res, email) {
const isEmail = emailFilter.test(email);
if (!isEmail) {
res.status(400).send({
error: {
message: "Requested email is not email type",
type: "FormatValidation",
location: "validateEmail"
}
});
return;
}
}
async function checkEmailInUse(res, users, email) {
const query = { email };
try {
const user = await users.findOne(query);
if (user) {
res.send({ message: "The email is already used" });
}
} catch (err) {
res.status(400).send({
error: {
message: "Failed to find user",
type: "DatabaseError",
location: "checkEmailInUse"
}
});
return;
}
}
The code keeps going after a failed validate because you call:
validateEmail(res, email);
and then your code just keeps going. This is normal flow of control in Javascript. Your function keeps executing lines of code until you return in the function. The same issue is true for checkEmailInUse(). If you want to sometimes send the response inside those functions and be done, then you need a return value from those functions that you can check and then use if statements to determine whether your code should do more or not.
Following your style of sending the error response inside the validation functions (which is not how I would probably structure things), you could return values from those functions and test those return values in the request handler like this:
router.post("/signup", async (req, res, next) => {
const { email, password } = req.body;
const users = req.app.get("users");
if (validateEmail(res, email)) {
if (await checkEmailInUse(res, users, email)) {
const user = await makeUser(res, users, email, password);
res.send({ message: "POST signup request OK", user });
}
}
});
function validateEmail(res, email) {
const isEmail = emailFilter.test(email);
if (!isEmail) {
res.status(400).send({
error: {
message: "Requested email is not email type",
type: "FormatValidation",
location: "validateEmail"
}
});
return false;
}
return true;
}
async function checkEmailInUse(res, users, email) {
const query = { email };
try {
const user = await users.findOne(query);
if (user) {
res.send({ message: "The email is already used" });
return false;
} else {
return true;
}
} catch (err) {
res.status(400).send({
error: {
message: "Failed to find user",
type: "DatabaseError",
location: "checkEmailInUse"
}
});
return false;
}
}
}
But, I think you might find this is simpler if you get rid of the local functions because then when you send a response, you can just directly return from the main function and be done. Here's how that could look:
router.post("/signup", async (req, res, next) => {
function err(res, message, type, location) {
res.status(400).send({error: {message, type, location}});
}
const { email, password } = req.body;
if (!emailFilter.test(email)) {
err(res, "Requested email is not email type", "FormatValidation", "validateEmail");
return;
}
const users = req.app.get("users");
try {
const user = await users.findOne({email});
if (user) {
res.send({ message: "The email is already used" });
return;
}
} catch(e) {
err(res, "Failed to find user", "DatabaseError", "checkEmailInUse");
return;
}
try {
const user = await makeUser(res, users, email, password);
res.send({ message: "POST signup request OK", user });
} catch(e) {
err(res, "Failed to make user", "DatabaseError", "makeUser");
}
}