I create a loginapp in nodejs but i want to verify if the email(or username) il already in the database.
router.post('/register', function(req, res) {
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
req.checkBody('username', 'Please enter a username').notEmpty();
req.checkBody('email', 'pls enter a email adress').notEmpty().isEmail();
req.checkBody('password', 'pls enter a password').notEmpty();
req.checkBody('password2', 'the password dont match').equals(req.body.password);
var errors = req.validationErrors();
if(errors) {
res.render('register',{
errors:errors,
})
} else {
var newUser = new User({
email:email,
username: username,
password: password
});
User.createUser(newUser, function(err, user){
if(err) throw err;
console.log(user);
});
req.flash('success_msg', 'u create an accoun, u can log');
res.redirect('/users/login');
}
})
How can a do a verify why an error msg if the email is already in the database ?
You can call findOne on the collection with the specified email. It resolves to null if no document matches. You can use that so as to detect whether or not there is already a user with the same email in the database.
You didn't provide the relevant part of the code to guess the architecture of you database, but you're probably going to use something like the following:
const { MongoClient } = require('mongodb');
const email = 'john#doe.com';
// wraps everything in an async function
(async () => {
// connect to database
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const users = client.db('your-db-name').collection('users');
// look for an existing user
let possibleDuplicate = await users.findOne({email});
if (possibleDuplicate===null) {
// email is not taken
// do something...
} else {
// email is taken
// do something...
}
})()
Related
I'm using Node, Express, & Mongoose trying to get this POST request to work using Postman but it keeps giving me the 500 status error. I also tried posting with just the username & instead of giving me the expected 400 status error it just gave me a 500 error again.
const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt')
const User = require('../models/userModel');
const registerUser = async (req, res) => {
try {
//get the username & password from the req.body
const { username, password } = req.body;
//check if the username is unique
const uniqueCheck = await User.findOne(username);
if (uniqueCheck) {
res.status(403).json('Username already exists');
}
//hash password
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
//check all fields are filled
if (!username || !password) {
res.status(400).json('Please fill in all fields')
} else {
//create user with username & password that is assigned to the hash version of it
const user = await User.create(username, { password: hash });
res.status(201).json(user);
}
} catch (error) {
res.status(500).json({ error: 'Problem registering user' });
}
}
As already I told you in the comment, you should ad a console.error statement in the catch block to better understand where is the problem.
Also, if the first if is matched, a response is sent to the client but the code execution will countinue, triyng to repliyng again to the client and giving you another error. You should return in the first if block to avoid it.
Check the following solution with comments on relevant edits
const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt')
const User = require('../models/userModel');
const registerUser = async (req, res) => {
try {
//get the username & password from the req.body
const { username, password } = req.body;
//check if the username is unique
const uniqueCheck = await User.findOne(username);
if (uniqueCheck) {
return res.status(403).json('Username already exists'); // --> !!! add a return statement here
}
//hash password
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
//check all fields are filled
if (!username || !password) {
res.status(400).json('Please fill in all fields')
} else {
//create user with username & password that is assigned to the hash version of it
const user = await User.create(username, { password: hash });
res.status(201).json(user);
}
} catch (error) {
console.error(error) // --> !!! log errors here
res.status(500).json({ error: 'Problem registering user' });
}
}
I am trying to work on a scenario where , user registers and it sends Email to both the user and the admin. I am working on this using node.JS / nodemailer/ MongodDB and the likes. Now I want to do something like this.
Once the register button is clicked, it saves data to the Database, then sends the email to both parties. The data is saved to the Database, no issues but the email part does not Work. My source code is looking thus
'use strict';
var mongoose = require('mongoose'),
jwt = require('jsonwebtoken'),
bcrypt = require('bcrypt'),
nodemailer = require('nodemailer'),
User = mongoose.model('User');
function dispatch_emails(admin_email, user_email, fullname, company_name){
const transporter = nodemailer.createTransport({
service:'gmail',
host: 'smtp.gmail.com',
port:'587',
auth:{
user: '***************#gmail.com',
pass: '**************'
},
secureConnection: 'false',
tls: {
ciphers: 'SSLv3',
rejectUnauthorized: false
}
});
const mailOptions = {
from :'**************#gmail.com',
to: user_email,
subject: 'Account Registration Successful!',
html : '<h3>Attention,'+fullname+' , </h3><p><h3>Your Account has been successfully setup.</h3></p><p> Please allow a maximum of 24 - 48 Hours for Review and succesful setup and approval of your online account.</p></br>Regards,</br> Online Services.'
};
const AdminNotifyEmail = {
from :'**************#gmail.com',
to: admin_email,
subject: 'Account Registration for '+user_email+', with Fullname : '+fullname+' ('+company_name+')',
html : '<h3>Attention Admin , </h3><p>A new User has registered his Access with the following Information: </br> <strong>Username : '+user_email+'</strong></br><strong>Company Name : '+company_name+'</strong></br><strong>Date of Registration : '+Date.Now+'</strong></p>'
};
transporter.sendMail(mailOptions,function(error,info){
if(error)throw error;
return res.send({error:false, data: info, message: 'OK'});
})
transporter.sendMail(AdminNotifyEmail,function(error,info){
if(error)throw error;
return res.send({error:false, data: info, message: 'OK'});
})
}
exports.register = function(req,res){
var admin_email = req.body.admin_email;
var newUser = new User(req.body);
newUser.hash_password = bcrypt.hashSync(req.body.password, 10);
newUser.save(function(err,user){
if(err){
return res.status(400).send({
message : err
});
}else{
dispatch_emails(admin_email, newUser.user_email, newUser.fullname, newUser.company_name);
user.hash_password = undefined;
return res.json(user);
}
})
};
exports.sign_in = function(req,res){
User.findOne({
email : req.body.email
},function(err,user){
if (err) throw err;
if (!user || !user.comparePassword(req.body.password)){
return res.status(401).json({message: 'Cannot Login, Authentication Failed'})
}
return res.json({token :jwt.sign({email: user.email, fullname: user.fullname, _id: user._id}, 'RESTFULAPI')})
})
};
exports.loginRequired = function(req,res,next){
if(req.user){
next();
}else{
return res.status(401).json({message: 'unauthorized User'});
}
};
exports.profile = function(req,res,next){
if(req.user){
req.send(req.user);
next();
}else{
return res.status(401).json({message: 'Invalid Token'});
}
}
The data is saved to the database without trouble, just this Email. How do i fix this, any ideas?
After a struggle i have been able to get it to send Emails
Changing from
exports.register = function(req,res){
var admin_email = req.body.admin_email;
var newUser = new User(req.body);
newUser.hash_password = bcrypt.hashSync(req.body.password, 10);
newUser.save(function(err,user){
if(err){
return res.status(400).send({
message : err
});
}else{
dispatch_emails(admin_email, newUser.user_email, newUser.fullname, newUser.company_name);
user.hash_password = undefined;
return res.json(user);
}
})
};
To this
exports.register = function(req,res){
var admin_email = req.body.admin_email;
var newUser = new User();
newUser.company_name = req.body.company_name;
newUser.fullname = req.body.fullname;
newUser.user_email = req.body.user_email;
newUser.phone_number = req.body.phone_number;
newUser.timezone = req.body.timezone;
newUser.hash_password = bcrypt.hashSync(req.body.password, 10);
newUser.save(function(err,user){
if(err){
return res.status(400).send({
message : err
});
}else{
dispatch_emails(admin_email, newUser.user_email, newUser.fullname, newUser.company_name);
user.hash_password = undefined;
return res.json(user);
}
})
};
And the whole Information sends to the emails without worries. Thanks everyone.
Hopefully it can help someone in Future.
I have to implement a functionality for the user who can after login change the password to new one.
For that I want to update the hash and salt value for new password set. How can I do that?
Since on registration I am saving the password first time in hash and salt form in mongoDB.
How can I update that now?
Here is the code I am trying to use for password change:
router.get('/api/changePassword', function(req,res,next){
req.checkBody('oldPass', 'Empty Password').notEmpty();
req.checkBody('newPass', 'Password do not match').equals(req.body.confirmPassword).notEmpty();
var user = new User();
user.setPassword(req.body.newPass);
user.save(function (err,data) {
if (err) {
res.render('register', {errorMessages: err});
} else {
console.log("password set successfully");
}
})
})
But here I doubt that it will get updated into the existing user's database since I am creating the object user again here and saving it. Will it create again a new user in Collections and update the hash and salt value for that? How to then update the existing user password hash and salt value?
Below is the hash and salt model User schema code:
userSchema.methods.setPassword = function(password) {
this.salt = crypto.randomBytes(16).toString('hex');
this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64, 'sha1').toString('hex');
};
userSchema.methods.validPassword = function(password) {
var hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64, 'sha1').toString('hex');
return this.hash === hash;
};
module.exports = mongoose.model('User', userSchema);
And this is the route code of registartion page, first time when user registers and put password:
router.route('/register')
.get(function(req, res, next) {
res.render('register', { title: 'Register a new account'});
})
.post(function(req, res, next) {
req.checkBody('name', 'Empty Name').notEmpty();
req.checkBody('email', 'Invalid Email').isEmail();
req.checkBody('location', 'Empty Location').notEmpty();
req.checkBody('password', 'Empty Password').notEmpty();
req.checkBody('password', 'Password do not match').equals(req.body.confirmPassword).notEmpty();
var errors = req.validationErrors();
if (errors) {
res.render('register', {
name: req.body.name,
email: req.body.email,
location:req.body.location,
errorMessages: errors
});
} else {
var user = new User();
user.name = req.body.name;
user.email = req.body.email;
user.location = req.body.location;
user.setPassword(req.body.password);
user.save(function (err,data) {
if (err) {
res.render('register', {errorMessages: err});
} else {
console.log("user saved successfully");
}
})
Sorry, my previous explanation was incorrect, so I am going to write this as an answer. You won't actually be able to access the User object in the method alone, so what you will have to do is something like the following:
create a function with User.find() that returns the user.
Then pass in this user as a parameter to the new method you created as I described in the comment above, and continue to .update() this user that was passed into the setPassword() method as a parameter.
So your methods for the schema should be:
createPassword()
validPassword()
setPassword()
and the part of your code where you actually have the function that uses these methods to set this data should look something like:
function findUser() {
return User;
}
function setPassword(password) {
User.setPassword(User, password, passwordValid /*This is a boolean*/)
}
I am a beginner working with node and I am attempting to allow for user registration on a project. However, anytime I press the register button on my page I receive this error:
ReferenceError: bcrypt is not defined
at model.<anonymous> (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/models/User.js:29:5)
at callMiddlewareFunction (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:482:23)
at model.next (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:58:7)
at _next (/Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:106:10)
at /Users/hossamalsheikh/Documents/Personal Projects/Web Apps/Gaming/node_modules/kareem/index.js:507:38
at processTicksAndRejections (internal/process/task_queues.js:79:11)
I don't understand what the issue could be. I gave both downloaded and required the bcryptjs module. Here is my code:
// Modules required to run the application
const express = require('express');
const bcrypt = require('bcryptjs');
// Creates 'mini app'
const router = express.Router();
// User model
const User = require('../models/User');
// Login Page
router.get('/login', function(req, res){
res.render("./home/login");
});
// Registration Page
router.get('/register', function(req, res){
res.render("./home/register");
});
// Registration
router.post('/register', function(req, res){
const { name, email, password, password2 } = req.body;
let errors = [];
// Check requried fields
if(!name || !email || !password || !password2){
errors.push({ msg: 'Please fill in all feilds' });
}
//Check passwords match
if(password !== password2){
errors.push({ msg: "Passwords do not match" });
}
// Check password length
if(password.length < 6){
errors.push({ msg: "Password should be at least six characters long" });
}
// Checks for any errors and prevents registration/redirection
if(errors.length > 0){
res.render('./home/register', {
errors,
name,
email,
password,
password2
});
}
else{
// Validation passed
User.findOne({ email: email })
.then(function(user){
if(user){
// User exists
errors.push({ msg: "Email is already registered" });
res.render('./home/register', {
errors,
name,
email,
password,
password2
});
} else {
const newUser = new User({
name: name,
email: email,
password: password
});
// Hash Password
bcrypt.genSalt(10, function(err, salt){
bcrypt.hash(newUser.password, salt, function(err, hash){
if(err){
throw err;
}
// Sets the password to the hashed password
newUser.password = hash;
newUser.save().then(function(user){
res.send('/users/login');
}).catch(function(err){
console.log(err);
});
});
});
}
});
}
});
module.exports = router;
Thank you for any assistance.
I am trying to build a user registration forum for a web app.
To refactor my code I created a folder named api and defined some routes in index.js (/api/routes/index.js).
Now I wanted to route my signup form to this route in (/api/routes/index.js) so that the data can go to user_sign_up function which is defined in (api/controllers/users.js)
my app.js looks like:
// some code
var routesApi = require('./api/routes/index');
app.use('/api', routesApi);
// some code
my (/api/routes/index) looks like:
// some code
var ctrlevents = require('../controllers/users');
router.post('/registeruser', ctrlevents.user_sign_up);
// some code
module.exports = router;
In server folder of my app, I have views folder under which all .html files are present.
How do I define routes for action attribute in signup form?
my users.js looks like:
module.exports.user_sign_up = (req, res) => {
// some code
};
I tried:
<form method="POST" action="/registeruser">
got this:
enter image description here
Following is working but getting 500 status.
<form method="POST" action="/api/registeruser">
Adding user_sign_up function:
/* GET signup data */
module.exports.user_sign_up = (req, res) => {
Name: req.body.username;
email: req.body.email;
password: req.body.password;
cpassword: req.body.cpassword;
console.log('ghfhghgh');
console.log(email);
console.log(password);
console.log(cpassword);
req.checkBody('Name', 'Name is required').notEmpty();
req.checkBody('email', 'Email is required').notEmpty();
req.checkBody('password', 'Password is required').notEmpty();
req.checkBody('cpassword', 'Passwords do not match').equals(req.body.password);
let errors = req.validationErrors();
if (err) {
res.render('register', {
errors:errors
});
}
else {
let newUser = new User({
Name:Name,
email:email,
password:password
})
}
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) {
console.log(err);
}
newUser.password = hash;
newUser.save((err) => {
if(err) {
console.log(err);
return;
}
else {
req.flash('success', 'Welcome to TechPath');
req.redirect('/blog');
}
})
});
})
};
As I understand, you want the action attribute in your sign up form. Since you already created a route registeruser which also has controller user_sign_up, just pass registeruser to your form as action. It should be working.
<form method="POST" action="/registeruser">
</form>
Edit:
I created a similar structure to yours, my code works well. Try to compare your code and my code and keep me updated if your issue is resolved or not.
I think you have to assign value using = sign
Name = req.body.username;
email = req.body.email;
password = req.body.password;
cpassword = req.body.cpassword;