error 'user.findOneAndUpdate is not a function' but data updated - node.js

i'm trying to use findOneAndUpdate for change password on mongoose, it's work, database updated
but error message show
"error": "user.findOneAndUpdate is not a function"
this my routes
router.post('/changepass', async (req, res) => {
const { phone, password } = req.body;
try {
const user = await User.findOneAndUpdate({phone},{password})
await user.findOneAndUpdate();
res.send({ user });
} catch (err) {
console.log(err)
res.status(422).send({ error: err.message });
}
});
and this my userSchema
userSchema.pre('findOneAndUpdate', function(next) {
const update = this.getUpdate()
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(update.password, salt, (err, hash) => {
this.getUpdate().password = hash;
return next();
})
})
});
please help me, i'm stuck for hours on this

try removing this line await user.findOneAndUpdate(); This line is causing the error and as per official docs it should be not there
router.post('/changepass', async (req, res) => {
const { phone, password } = req.body;
try {
const user = await User.findOneAndUpdate({phone},{password})
res.send({ user });
} catch (err) {
console.log(err)
res.status(422).send({ error: err.message });
}
});
here is doc reference - https://mongoosejs.com/docs/tutorials/findoneandupdate.html

Related

I am using bcryptjs to hash my password so I got an error but in catch(err) don't give me any error

this is the controller and if I do it whitout hashing it works but with hashing it give me an error and I cannot handle in catch(err)
this is the controller and if I do it whitout hashing it works but with hashing it give me an error and I cannot handle in catch(err)
this is the controller and if I do it whitout hashing it works but with hashing it give me an error and I cannot handle in catch(err)
const { throws } = require("assert");
const { bcrypt } = require("bcryptjs");
const User = require("../models/user");
// #desc register new user
// #routes POST /users/register
exports.createUser = async (req, res) => {
const errors = [];
try {
await User.userValidation(req.body);
const { fullname, email, password } = req.body;
const user = await User.findOne({ email });
if (user) {
errors.push({ message: "کاربری با این ایمیل موجود است" });
return res.render("register", {
pageTittle: "صحفه ثبت نام",
path: "/register",
errors: errors,
});
}
bcrypt.genSalt(10, (err, salt) => {
if (err) throw err;
console.log(err);
bcrypt.hash(password, salt, async (err, hash) => {
if (err) throw err;
await User.create({
fullname,
email,
password: hash,
});
res.redirect("/users/login");
});
});
} catch (err) {
err.inner.forEach((e) => {
errors.push({
name: e.path,
message: e.message,
});
});
}
return res.render("register", {
pageTittle: "صحفه ثبت نام",
path: "/register",
errors: errors,
});
};

Express routes not sending response Heroku-Postgres code H12

I'm having an issue with my routes not sending responses to the frontend. I only have 3 routes so far, only two send responses, but neither are doing so. I am using node-postgres(pg). My register route seems to be working because when I register a user, it is reflected in the database. Here are the two routes in question.
// login
app.post('/api/v1/login', checkInput, async (req, res, next) => {
console.log(req.body)
try {
// find user
db.query(`SELECT * FROM users WHERE username = $1`, [req.body.username], async (err, user) => {
if (err) throw err;
// user not found
if (!user) {
res.send({message: 'error'});
} else {
// compare passwords
const matchedPassword = await bcrypt.compare(req.body.password, user.password);
// password doesn't match
if (!matchedPassword) {
res.send({message: 'error'});
} else {
// user found
req.session.user = user.username;
req.session.auth = true;
res.send({message: 'success'});
}
}
})
} catch (error) {
next(error);
}
});
// register
app.post('/api/v1/register', checkInput, async (req, res, next) => {
console.log(req.body)
try {
// check if user already exists
db.query(`SELECT username FROM users WHERE username = $1`, [req.body.username], (err, user) => {
if (err || user) {
res.send({message: 'error'});
}
});
// user doesn't exist so create user
// encrypt password
const salt = await bcrypt.genSalt(3);
const hashPassword = await bcrypt.hash(req.body.password, salt);
db.query(`INSERT INTO users (username, password) VALUES ($1, $2)`, [req.body.username, hashPassword], (err, user) => {
if (err) {
res.send({message: 'error'});
} else {
res.send({message: 'success'});
}
});
} catch (error) {
next(error);
}
});
Any help would be appreciated!

Login Authentification: No response from Rest API after Post Request

I recently switched from php development to Javascript (I'm really amazed by the performance and possibilities).
Currently I try to create a simple authentification function (Username,hashed Password checked to mariadb Database)
After following some tutorials I managed to create the following structure:
But when I try to test the API via Postman and Insomnia I just get no response. Not even an Error Code. Just going on forever, just like an infinite Loop?
I'm thankful for any tip as I'm new to this. Thanks in advance.
My Stack: React, Nodejs, Mariadb, Express & Jwt / bcryptjs
My Express Router router.js:
router.post('/login', (req, res, next) => {
pool.query(
`SELECT * FROM TABLE WHERE username = ${pool.escape(req.body.username)};`,
(err, result) => {
// user does not exists
if (err) {
throw err;
return res.status(400).send({
msg: err
});
}
if (!result.length) {
return res.status(401).send({
msg: 'Username or password is incorrect!'
});
}
// check password
bcrypt.compare(
req.body.password,
result[0]['password'],
(bErr, bResult) => {
// wrong password
if (bErr) {
throw bErr;
}
if (bResult) {
const token = jwt.sign({
username: result[0].username,
userId: result[0].id
},
process.env.API_SecretKey, {
expiresIn: '2h'
}
);
return res.status(200).send({
msg: 'Logged in!',
token,
user: result[0]
});
}
return res.status(401).send({
msg: 'Username or password is incorrect!'
});
}
);
}
);
});
router.post('/sign-up', userMiddleware.validateRegister, (req, res, next) => {
pool.query(
`SELECT * FROM TABLE WHERE LOWER(username) = LOWER(${pool.escape(
req.body.username
)});`,
(err, result) => {
if (result.length) {
return res.status(409).send({
msg: 'This username is already in use!'
});
} else {
// username is available
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).send({
msg: err
});
} else {
// has hashed pw => add to database
pool.query(
`INSERT INTO TABLE (SecurityID, userPassword, username, userOTP) VALUES ('${pool.escape}', ${pool.escape(
req.body.SecurityID,
req.body.username,
req.body.password,
req.body.userOTP
)}, ${pool.escape(hash)}, now())`,
(err, result) => {
if (err) {
throw err;
return res.status(400).send({
msg: err
});
}
return res.status(201).send({
msg: 'Registered!'
});
}
);
}
});
}
}
);
pool.end;
});
router.get('/secret-route', userMiddleware.isLoggedIn, (req, res, next) => {
console.log(req.userData);
res.send('This is the secret content. Only logged in users can see that!');
});
module.exports = router;
My Middleware users.js
module.exports = {
validateRegister: (req, res, next) => {
// username min length 3
if (!req.body.username || req.body.username.length < 3) {
return res.status(400).send({
msg: 'Passwort:' + req.body.username + 'Please enter a username with at least 3 chars',
});
}
// password min 6 chars
if (!req.body.password || req.body.password.length < 6) {
return res.status(400).send({
msg: 'Passwort:' + req.body.password + 'Please enter a password with at least 6 chars'
});
}
// password (repeat) does not match
if (
!req.body.password_repeat ||
req.body.password != req.body.password_repeat
) {
return res.status(400).send({
msg: 'Both passwords must match'
});
}
next();
},
isLoggedIn: (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
const decoded = jwt.verify(
token,
process.env.API_SecretKey
);
req.userData = decoded;
next();
} catch (err) {
return res.status(401).send({
msg: 'Your session is not valid!'
});
}
}
};
My index.js:
const express = require("express");
const DigitalMangement = express();
const cors = require('cors');
require("dotenv").config();
DigitalMangement.use(cors());
DigitalMangement.use(express.json());
// add routes
const router = require('./Routes/router.js');
DigitalMangement.use("/api", router);
DigitalMangement.listen(process.env.Application_Port, () => {
console.log("Server is running on Port " + process.env.Application_Port)
});
I haven't reviewed the whole code but, if you throw the error the code block will not continue. In this case, it won't be logged or sent as a response. Try removing the throw err line and rerun the code.
if (err) {
throw err; //! here
return res.status(400).send({
msg: err
});
}
Thanks for all the help fellow Coders:
It seems to be that the import MariaDB isn't 100% correct in this situation.
I changed it to mariadb/callback and it started to work.
The MariaDB library returns Promises and mariadb/callback allows callbacks.

got `{}` when set a field in mongodb to `undefined` using mongoose

I'm facing a weird problem
I'm using mongoose 5.12.8, I try to delete a user's image with this route
router.delete('/users/me/avatar', auth, async(req, res) => {
try {
req.user.avatarObj = undefined
await req.user.save()
res.send({ message: "Deleted user's avatar" })
} catch (error) {
res.status(500).send(error.message)
}
});
but when I use get route, i got req.user.avatarObj is still an empty object {}
//get user avatar
router.get('/users/:id/avatar', async(req, res) => {
try {
const user = await User.findById(req.params.id);
console.log(user.avatarObj) // print {} ?????????
console.log(user) //user has no avatarObj field
if (user && user.avatarObj) {
res.set('Content-Type', user.avatarObj.contentType);
res.send(user.avatarObj.data);
} else {
throw new Error('Not found user or image');
}
} catch (err) {
res.status(404).send({ error: err.message });
}
});
this is my userSchema
avatarObj: {
data: Buffer,
contentType: String
}
and some middleware
//hash plain text password before saving
userSchema.pre('save', async function(next) {
const user = this
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 10)
}
next()
});
//remove all tasks before remove user
userSchema.pre('remove', async function(next) {
await Task.deleteMany({ owner: this._id })
next()
});
My question is: Why user.avatarObj is still an empty object?
Thank you guys!

how to resolve data and hash error in node js bcrypt

Error: data and hash arguments required
i am doing simple, login signup and forgot password in node js using
bcrypt hash
code : for login
app.post('/login', (req, res) => {
console.log('login');
let {email, password} = req.body;
User.updateOne({email: email}, ' email password', (err, userData) => {
if (!err) {
let passwordCheck = bcrypt.compareSync(password, userData.password);
if (passwordCheck) {
console.log('login2');
req.session.user = {
email: userData.email,
id: userData._id
};
req.session.user.expires = new Date(Date.now() + 3 * 24 * 3600 * 1000);
res.status(200).send('You are logged in, Welcome!');
} else {
res.status(401).send('incorrect password');
console.log('login3');
}
} else {
res.status(401).send('invalid login credentials');
console.log('login4');
}
});
});
code for signUp :
app.post('/signup', (req, res) => {
let {email, password} = req.body;
let userData = {password: bcrypt.hashSync(password, 5, null), email };
console.log('out save');
let newUser = new User(userData);
newUser.save().then(error => {
if (!error) {
console.log('in save');
return res.status(200).json('signup successful');
} else {
if (error.code === 11000) {
return res.status(409).send('user already exist!');
} else {
console.log(JSON.stringigy(error, null, 2));
return res.status(500).send('error signing up user');
}
}
});
});
i have tried console logging few lines and turned out that the code doesn't go into signup
newUser.save();
tell me where i'm going wrong
The issue is with this line newUser.save().then(error => {. Do you notice the .then(). That is a resolved promise so it wouldn't be returning an error. Typically you would see something like this.
Promise()
.then((result) => {
// result is a resolved promise
})
.catch((error) => {
// error is a rejected promise
})
So you should try changing your code to this:
newUser.save()
.then(result => {
console.log('in save')
return res.status(200).json('signup successful')
})
.catch(error => {
if (error.code === 11000) {
return res.status(409).send('user already exist!')
} else {
console.log(JSON.stringigy(error, null, 2))
return res.status(500).send('error signing up user')
}
})
It looks like you're using mongoose, here is the API docs for Document.prototype.save() https://mongoosejs.com/docs/api.html#document_Document-save
Their documentation uses callback functions for the most part but if you scroll to the end of the .save() documentation you will see they show one example with a promise.
bcrypt.compareSync takes 2 parameters; passwordToCheck, passwordHash
You are getting error "bcrypt Error: data and hash arguments required"
This error means one or both parameters are either null or undefined,
In your case you need to make sure that password, userData.password are correctly going in function bcrypt.compareSync

Resources