Error: data and salt arguments required (Async) - node.js

I have a problem with Schema.pre('save'), in my model 'user', cannot get 'this' for the hashed of my password with bcrypt.
my app.js, Simple connect in mongodb using mongoose
mongoose.connect('mongodb://localhost/gederson', {
useMongoClient: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('Connected on mongo');
});
app.listen(process.env.PORT || 3000, () => {
console.log('listening');
});
index(app, db);
post(app, db);
admin(app, db);
module.exports = app;
my route, I created the route for create user in my application, but in pre 'save' cannot get the 'this' for hash password.
const Users = db.model('Users');
const newUser = {
username: req.body.username,
email: req.body.email,
password: req.body.password,
};
Users.create(newUser, (err) => {
if (err) throw err;
res.status = 201;
return res.send('User created');
});
my model user, the code pre 'save'
const bcrypt = require('bcrypt');
UserSchema.pre('save', (next) => {
const user = this;
bcrypt.hash(user.password, 10, (err, hash) => {
if (err) {
return next(err);
}
user.password = hash;
return next();
});
});
const Users = mongoose.model('Users', UserSchema);
module.exports = Users;
Stack Error:
events.js:183
throw er; // Unhandled 'error' event
^
Error: data and salt arguments required
at /home/gedersonchiquesi/ProjetosDev/wos/node_modules/bcrypt/bcrypt.js:114:16
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
[nodemon] app crashed - waiting for file changes before starting...

I ran into a similar issue today.
I resolved the matter by removing the ES6 syntax (arrow function).
UserSchema.pre('save', function(next) {
const user = this;
bcrypt.hash(user.password, 10, function(err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
})
});

because you are passing the blank value of the inputs on that function
if test on postman or else data input needed
{
"name":"test",
"email":"test#test.com",
"password":"123456"
}
add see my code example for datastore
router.post("/register-user", (req, res, next) => {
bcrypt.hash(req.body.password, 10).then((hash) => {
const user = new userSchema({
name: req.body.name,
email: req.body.email,
password: hash
});
user.save().then((response) => {
res.status(201).json({
message: "User successfully created!",
result: response
});
}).catch(error => {
res.status(500).json({
error: error
});
});
});
});

My issue was my server wasn't accepting the correct data type.
Had to include the following on server.js file:
app.use(express.json()); &
app.use(express.urlencoded({extended: true}));

Related

TypeError: Cannot read properties of null (reading 'password')

const router = require('express').Router()
const User = require('../models/User.js')
router.get('/', async (req, res) => {
res.render('pages/register.ejs')
})
router.post('/', async (req, res) => {
const username = req.body.username
const email = req.body.email;
const password = req.body.password
const newUser = new User({
username: username,
email: email,
password: password
})
console.log(newUser.toJSON())
newUser.save((err) => {
if (err) {
res.send(err)
} else {
res.send('user created successfully')
}
})
User.findOne({ username:username, email: email, password: password }, (err, foundResult) => {
if (err) {
res.send(err)
}else{
if(foundResult.password === password && foundResult.email === email && foundResult.username === username){
res.send('User yet created')
}
}
})
})
module.exports = router
In this code of a simple login and registration system I have taken what is entered in the password input and used it in such a way as to insert it into the DB. But when I submit the form to register it gives me this error
node:events:368
throw er; // Unhandled 'error' event
^
TypeError: Cannot read properties of null (reading 'password')
at C:\Users\Administrator\Desktop\coding\project\fullstack\ecommerce\routes\registerRoute.js:34:28
at C:\Users\Administrator\Desktop\coding\project\fullstack\ecommerce\node_modules\mongoose\lib\model.js:4994:18
at processTicksAndRejections (node:internal/process/task_queues:78:11)
Emitted 'error' event on Function instance at:
at C:\Users\Administrator\Desktop\coding\project\fullstack\ecommerce\node_modules\mongoose\lib\model.js:4996:15
at processTicksAndRejections (node:internal/process/task_queues:78:11)
Some ideas. Thanks too much
I think this is the better way to doing this.
If you use async/await version then must be in try/catch block..
router.post('/register' , async (req , res) => {
console.log(req.body);
// res.json({message: req.body});
const { username, email, password } = req.body;
if(!username || !email|| !password) {
return res.status(422).json({error:"Please filled the field correctly"});
}
try {
const userExist = await User.findOne({username:username});
if (userExist) {
res.send({message:"Username Already Exist !!!"});
return res.status(422).json({error:"Username already Exist"});
}
const user = new User({ username , email , password});
await user.save();
res.status(201).json({ message:"User Registered Successfully!!" })
} catch(err) {
console.log("showing errors" , err);
}
})

TypeError: login.findOne(...).toArray is not a function

I have this function, whcih bascially gets the usernmae and password of the users input from the front-end form, and then checks it in mongodb:
app.post('/login', (req, res, next) => {
var username = req.body.username;
var password = req.body.password;
//connecting to the mongo client
client.connect().then (() => {
//defining database name and collection
const database = client.db("myFirstDatabase");
const login = database.collection("login");
//connecting to the mongo client
MongoClient.connect(uri, function(err, db) {
if (err) throw err;
//finding all documents inside array
login.findOne({"username": username}).toArray(function(err, result) {
if (err) throw err;
result.forEach(results =>
bcrypt.compare(password, results.password, function(err, result) {
if (result === true) {
req.session.loggedin = true
next()
} else {
res.redirect('/login')
}
})
);
db.close();
});
});
})
})
however, it is giving me this error:
TypeError: login.findOne(...).toArray is not a function
i've never encountered this error before. how do i fix this?
Try this way
login.findOne({"username": username}, function(err,user)
{ console.log(user); });

Mongoose findOne function is not working with authentication

I am working on a model here:
// user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
// Define collection and schema for Users
let User = new Schema(
{
firstName: String,
lastName: String,
emailaddress: String,
password: String,
},
{
collection: 'users'
}
);
// authenticate input against database documents
User.statics.authenticate = ((emailaddress, password, callback) => {
User.findOne({ emailaddress: emailaddress })
.exec(function(error, user){
if(error){
return callback(error)
} else if (!user){
console.log('User not found!');
}
bycrypt.compare(password, user.password, function(err, result){
if(result === true){
return callback(null, user);
} else {
return callback();
}
})
})
});
module.exports = mongoose.model('User', User);
As you can see on my model I put the User.statics.authenticate on my codes to do some authentication. And then on my login.js route file:
const path = require('path');
const express = require('express');
const router = express.Router();
const db = require('../../database/index');
const axios = require('axios');
const User = require('../../database/models/user');
router.get('/', (req, res) => {
console.log('hi there this is working login get');
});
router.post('/', (req, res) => {
var emailaddress = req.body.emailaddress;
var password = req.body.password;
if( emailaddress && password ){
User.authenticate(emailaddress, password, function(err, user){
if(err || !user){
console.log('Wrong email or password!');
} else {
req.session.userId = user._id;
return res.redirect('/');
}
});
} else {
console.log('both fields are required...');
}
});
module.exports = router;
I called the function and then User.authenticate function and also I created the route for root w/c is the sample that I want to protect and redirect the user after login:
router.get('/', (req, res) => {
if(! req.session.userId ){
console.log('You are not authorized to view this page!');
}
User.findById(req.session.userId)
.exect((err, user) => {
if(err){
console.log(err)
} else {
res.redirect('/');
}
})
});
Upon clicking submit on my react form it returns this error:
TypeError: User.findOne is not a function
at Function.User.statics.authenticate (/Users/mac/Documents/monkeys/database/models/user.js:35:8)
I checked the Mongoose documentation and it seems I am using the right syntax.Any idea what am I doing wrong here? Please help! Sorry super beginner here!
PS. I've already installed and set up the basic express session too.
UPDATES:
I remove the arrow function from my call and use this.model.findOne but still get the typerror findOne is not a function
// authenticate input against database documents
User.statics.authenticate = function(emailaddress, password, callback){
this.model.findOne({ emailaddress: emailaddress })
.exec(function(error, user){
if(error){
return callback(error)
} else if (!user){
console.log('User not found!');
}
bycrypt.compare(password, user.password, function(err, result){
if(result === true){
return callback(null, user);
} else {
return callback();
}
})
})
};
findOne is a method on your User model, not your user model instance. It provides its async results to the caller via callback:
User.findOne({field:'value'}, function(err, doc) { ... });

Node js error "process with a non-zero exit code"

I developing a REST API using node js and express with MongoDB.
I have developed an endpoint to insert the user into DB and works fine. Now I have added the login function with jwt and now when I run my app and try to insert my user I receive this error:
an app is listening on port 3000
(node:3650) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Expected "payload" to be a plain object.
(node:3650) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I'm using a node js version: 8.9.3 on mac
Any help, please?
# this is the code about user add:
var router = require('express').Router();
var bcrypt = require('bcryptjs');
var User = require('../models/user');
var jwt = require('jsonwebtoken');
var constants = require('../config/constants');
router.post('/',(req, res) => {
// add user --> user = { username: 'test', email: 'test#tes.com', pwd: 'Test'}
var user = new User({
username: req.body.user.username,
email : req.body.user.email,
passhash: bcrypt.hashSync(req.body.user.pwd, 10)
});
user.save().then(
(newuser) => {
var sessionToken = jwt.sign(newuser._id, constants.JWT_SECRET, {expiresIn: 60*60*24});
res.json({
user: newuser,
message: 'success',
sessionToken: sessionToken
});
},
(err) => {
res.send(500, err.message);
}
);
});
module.exports = router;
and this is the code about login:
var router = require('express').Router();
var bcrypt = require('bcryptjs');
var jwt = require('jsonwebtoken');
var constants = require('../config/constants');
var User = require('../models/user');
router.post('/', (req, res) => {
User.findOne({ username: req.body.user.username}).then(
(user) => {
if(user){
bcrypt.compare(req.body.pwd, user.passhash, (err, matches) => {
if (matches) {
var sessionToken = jwt.sign(user._id, constants.JWT_SECRET, { expiresIn: 24*60*60 });
res.json({
user:user,
message: 'succesfully authed',
sessionToken: sessionToken
});
}else{
res.json({
user: {},
message: 'failed to auth',
sessionToken: ''
});
}
});
}else{
res.json({
user: {},
message: 'failed to auth',
sessionToken: ''
});
}
},
(err) => {
// could not find users
res.json(err);
}
);
});
module.exports = router;
I have tested the add user with postman and I have seen that when I receive the message posted, the user is inserted into db
If both API methods are declared in the same file, the problem can be because you are declaring twice same path + verb:
router.post('/', (req, res) => {

mongoosejs find specific record

i want to find a specific record in mongoose. i'm trying to make a login/register form and im kind of new to node.js..
for now i have this code:
app.post('/register', function(request, response)
{
console.log('REGISTER OK');
//set connection to mongodb.
mongoose.connect('mongodb://localhost');
var db = mongoose.connection;
//Connect to mongodb.
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback()
{
console.log('connection succeed.');
//Create User schema.
var userSchema = mongoose.Schema(
{
username: String,
password: String
});
//User model.
var UserModel = mongoose.model('User', userSchema);
var user = new UserModel(
{
username: request.body.username,
password: request.body.password
});
user.save(function(error, data)
{
if(error)
console.log(error);
else
{
response.render('register',
{
'Title': Title,
'result': data
});
UserModel.find(function(error, data)
{
if(error)
console.log(error);
else
console.log(data);
});
}
});
});
});
i dont quite get the find method of mongoose, i just need to find the username in order to do some function, is there a function that moongose has to avoid record if this exists already?
UserModel.findOne ({ name: "someName" }, function (err, user) {
if (err) console.log (err);
if (!user) console.log ('user not found');
// do something with user
});

Resources