Let's say we have two file, user.js users.js in user.js we have. Why can we do module.exports.. we can use in it diff .js file? what does "@returns Promise If callback has been omitted"
means it is from the bcrypt.genSalt function?
I also have a github repo, so please take a look if you have a bit of time. after cloning it
stuck in terminal
result { error: null,
value:
{ email: 'max@mail.com',
username: 'max',
password: '1234',
confirmationPassword: '1234' },
then: [Function: then],
catch: [Function: catch] }
hash undefined
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const bcrypt = require('bcryptjs');
const userSchema = new Schema({
email: String,
username: String,
password: String
});
const User = mongoose.model('user', userSchema);
module.exports = User;
module.exports.hashPassword = (password) => {
return hash = bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(password, salt, function(err, hash) {
});
});
};
in users.js we have have
const express = require('express');
const router = express.Router();
const Joi = require('joi');
const User = require('../models/user');
const userSchema = Joi.object().keys({
email:Joi.string().email().required(),
username:Joi.string().required(),
password:Joi.string().regex(/^[a-zA-Z0-9]{3,15}$/).required(),
confirmationPassword:Joi.any().valid(Joi.ref('password')).required()
});
router.route('/register')
.get((req, res) => {
res.render('register');
})
.post(async (req, res, next) => {
try{
const result = Joi.validate(req.body,userSchema);
console.log('result',result);
if(result.error) {
req.flash('error', 'Data is not valid, please try again');
res.redirect('/users/register');
return;
//console.log('result',result);
}
// checking if email is already taken
const user = await User.findOne({'email':result.value.email });
if (user){
req.flash('error','Email is already in use');
res.redirect('/users/register');
return;
}
// console.log('hash',hash);
// Hash the password
const hash = await User.hashPassword(result.value.password);
console.log('hash',hash);
} catch(error) {
next(error);
}
});
module.exports = router;
based the example given by bcrypt
var bcrypt = require('bcryptjs');
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash("B4c0/\/", salt, function(err, hash) {
// Store hash in your password DB.
});
});
I think the problem lies in this line:
const hash = await User.hashPassword(result.value.password);
This implies that User.hashPassword(result.value.password)
should be returning a promise (but it returns a reference to the wrong promise).
module.exports.hashPassword = (password) => {
return hash = bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash(password, salt, function (err, hash) {});
});
};
Perhaps modifying the above to return a promise may help.. Like so:
module.exports.hashPassword = (password) => {
var salt = await bcrypt.genSalt(10);
return bcrypt.hash(password, salt);
};
To answer your question about @returns Promise If callback has been omitted
:
Bcrypt methods are asynchronous. Which means they return immediately and process in the background. When the result is available, the function makes this available to the calling code either via a callback function or a promise.
Consider the following API for genSalt
from the docs:
genSalt(rounds, minor, cb)
rounds - [OPTIONAL] - the cost of processing the data. (default - 10)
minor - [OPTIONAL] - minor version of bcrypt to use. (default - b)
cb - [OPTIONAL] - a callback to be fired once the salt has been generated. uses eio making it asynchronous. If cb is not specified, a Promise is returned if Promise support is available.
err - First parameter to the callback detailing any errors. salt - Second parameter to the callback providing the generated salt.
What that says is genSalt
can take three arguments: genSalt(rounds, minor, cb)
Sample using callbacks
If the calling code wants the result via a callback, it can pass a function which looks like function(err, salt){}
as the cb
parameter.
bcrypt.genSalt(rounds, minor, function(err, salt){
if(err){
//Handle error
return;
}
// Salt is available here
console.log(salt);
});
Sample using promises
If the cb parameter is not passed (null or undefined) the function returns a Promise instead.
var promise = bcrypt.genSalt(rounds, minor);
promise
.then(function(salt){
// Salt is available here
console.log(salt);
})
.catch(function(err){
// Handle error
});