Tried searching the net for 2 days and still could not find a specific answer. I have the below node.js code for user routes and models. How can I check if the username and email has never appear in the MongoDB, and prompt the user a message if there is?
model:
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
// User Schema
var UserSchema = mongoose.Schema({
username:{type: String , required:true, index: true, unique:true},
email:{type: String, required:true, index: true, unique:true},
password:{type: String, required:true}
});
module.exports = mongoose.model('User', UserSchema)
route:
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var bcrypt = require('bcryptjs');
// Get Homepage
router.get('/', function(req, res){
res.render('index');
});
router.get('/register',function(req,res){
res.render('register');
});
// submit form
router.post('/submit', function(req, res){
// retrieve data from posted HTML form
var username = req.body.username;
var email = req.body.email;
var password = req.body.password;
var password_confirm = req.body.password_confirm;
// express validator
req.checkBody('username','Username is required').notEmpty();
req.checkBody('email','Email is required').notEmpty();
req.checkBody('email','Invalid email').isEmail();
req.checkBody('password','Password is required').notEmpty();
req.checkBody('password','Password must contain at least 6 characters').isLength({min:6});
req.checkBody('password_confirm','Password mismatch').equals(req.body.password);
// store the errors
var errors = req.validationErrors();
if(errors){res.render('register',{errors:errors});}
else {
// hash password
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync(password, salt);
password=hash;
// load data into model
var newUser = new User ({username:username, email:email, password:password});
// save the new user
newUser.save(function(err,newUser){
if(err){console.error(err);}
// console.error is same, but in stderr form
else{
console.log('new user saved successfully');
console.log(newUser);
}
});
res.redirect('/');
}
});
module.exports = router;
app.post('/authenticate', function(req, res) {
var user = new User({
username: req.body.username
});
user.save(function(err) {
if (err) {
if (err.name === 'MongoError' && err.code === 11000) {
// Duplicate username
return res.status(500).send({ succes: false, message: 'User already exist!' });
}
// Some other error
return res.status(500).send(err);
}
res.json({
success: true
});
});
})
You have to catch the error and return it to the front end of your application. This code above should demonstrate how to achieve this by using server status 500. Regarding searching the web, this answer and question are quite similar to this previous question:
How to catch the error when inserting a MongoDB document which
violates an unique index?
I hope this helped to some extend.
Related
I am trying to have a user log in by their email and password. MongoDb docs shows hashing the password with bcrypt in the user model. It also provides a nice way to validate the password in the model as well. My problem is how to I use that validation from the "controller"? I am very aware "if (req.body.password === user.password)" will not work because one is hashed and the other is not.
I have been searching for answers for hours and can't seem to find that connection on how I use that "UserSchema.methods.comparePassword" method in my post request to log in. This isn't completely a real log in, just trying to get the password to validate and send back a key once logged in. Here are the docs: https://www.mongodb.com/blog/post/password-authentication-with-mongoose-part-1
// This is my UserModel
let mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcrypt'),
SALT_WORK_FACTOR = 10
var hat = require('hat');
let UserSchema = new Schema({
email: {
type: String,
required: true,
index: {
unique: true
}
},
password: {
type: String,
require: true
},
api_key: {
type: String
}
});
UserSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
// hash the password using our new salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
// override the cleartext password with the hashed one
user.password = hash;
user.api_key = hat();
next();
});
});
});
UserSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
};
module.exports = mongoose.model('user', UserSchema);
// This is the sessions.js
let UserModel = require('../../../models/user.model');
var express = require('express');
var router = express.Router();
router.post('/', (req, res, next) => {
UserModel.findOne(
{
$or: [
{ email : req.body.email }
]
}
)
.then(user => {
if (req.body.password === user.password) {
res.setHeader("Content-Type", "application/json");
res.status(200).send(JSON.stringify({
"api_key": `${user.api_key}`
}));
} else {
res.status(404).send("Incorrect email or password")
}
})
.catch(error => {
res.setHeader("Content-Type", "application/json");
res.status(500).send({error})
})
})
module.exports = router
If I just find user by email, everything works fine. Just need to figure out how to use the compare password method in the user model. Thanks!
Maybe have something like this in your model:
User = require('./user-model');
.......
User.findOne({ username: 'jmar777' }, function(err, user) {
if (err) throw err;
user.comparePassword('Password123', function(err, isMatch) {
if (err) throw err;
console.log('Password123:', isMatch); // -> Password123: true
});
........
Other resources:
http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt
https://www.abeautifulsite.net/hashing-passwords-with-nodejs-and-bcrypt
https://medium.com/#mridu.sh92/a-quick-guide-for-authentication-using-bcrypt-on-express-nodejs-1d8791bb418f
Hope it helps!
While sending a post request i written the following code :
var email = req.body.email ;
var newDetails = { email: email };
Details.create(newDetails);
console.log(newDetails);
while sending the request. The console.log shows me the correct details,
However in the mongo shell the only collection that exist is "details" and it's empty .
That's the Mongoose Schema:
var mongoose = require("mongoose");
var DetailsSchema = mongoose.Schema({
email: String
});
module.exports = mongoose.model("Details", DetailsSchema);
I'm using NodeJS.
Thanks in advance.
Your Mongoose Model should be like
const mongoose = require("mongoose");
const Scheme = mongoose.Schema;
const DetailsSchema = new Scheme({
email: String
});
module.exports = mongoose.model("Details", DetailsSchema);
Node js Code should be like
var detailsModel = require('../model/Details.js');//path of mongoose model
var detailsData = new detailsModel();
detailsData.email = req.body.email;
detailsData.save(function (err, savedJob) {
if (err) {
return res.send(err);
} else {
return res.send(savedJob);
}
});
To save data in mongoDB's Database
You can use this way
var detailsData = new detailsModel();
detailsData.save()
.then(business => {
res.status(200).json({'Details': 'newDetails added successfully'});
})
.catch(err => {
res.status(400).send("unable to save to database");
});
With this, you can also handle error easily.
I have a problem. I'm trying to save answers from a survey. My problem is that I'm sending these answers through axios and they are showing in the console.log from the server, which means that my data is reaching the server safely. But data is not being saved. Also no error is shown.
Server.js
router.route('/answers')
//post answers to database
.put(function(req, res){
var survey = new Survey();
survey.name = req.body.name;
survey.email = req.body.email;
survey.q_id = req.body.q_id;
survey.q_text = req.body.q_text;
survey.answer = req.body.answer;
console.log(Survey.collection)
survey.save(function(err){
if(err){
console.log(err)
return ;
}
res.send(survey);
});
})
Survey.js (Model)
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = mongoose.Schema.Types.ObjectId;
var question = new Schema({
q_text:String,
order: Number,
options:[{
type: {type: String},
value: {type: String}
}]
});
module.exports = mongoose.model('Question',question);
Code that is posting the data
const url = 'http://localhost:3100/api/answers';
axios.put(url, survey)
.then(res => {
console.log('Successfully posted');
console.log(res);
setSubmitting(false);
setStatus({submitted: true});
})
.catch(err => {
console.log(err);
})
Try this :
survey.save(function(err, savedSurvey){
if(err){
console.log(err)
return ;
}
res.send(savedSurvey);
});
hi i am trying to remove a value from mongoDB but instead of removing a specific value the code is deleting all users from the schema lol.
var mongoose = require('mongoose');
var User = require('../../models/UserModel');
module.exports.unfollow = function(req, res){
var thefollowee = req.body.followee;
var thefollower = req.body.follower;
User.find({_id: thefollower}).remove({following: thefollowee}).exec();
User.find({_id: thefollowee}).remove({followers: thefollower}).exec();
res.json({ message: 'Unfollowed'});
};
the followee is pointing to the id of the person being followed,
the follower is pointing to the id of the user who follows the followee.
ok so i got it by using the $pull method
var mongoose = require('mongoose');
var User = require('../../models/UserModel');
module.exports.unfollow = function(req, res){
var thefollowee = req.body.followee;
var thefollower = req.body.follower;
User.findByIdAndUpdate(thefollowee, { $pull: { followers: req.body.follower }}, function (err, user) {
if (err)
return handleError(err);
});
User.findByIdAndUpdate(thefollower, { $pull: { following: req.body.followee }}, function (err, user) {
if (err)
return handleError(err);
});
res.json({ message: 'Unfollowed'});
};
I am trying to post a form through express. For some reason when I am posting, it is posting about 4-8 times. It seems that when autocomplete is involved it using the keystrokes.
I am also using gulp and wanted to know how to post using express or if I should post separately in a javascript file.
Code Example
ADD USER FILE (which is included in my server file)-
var express = require('express');
var passport = require('passport');
var form = require('express-form');
var field = form.field;
var User = require('../models/user');
var router = express.Router({
mergeParams: false
});
router.get('/user/add', function (req, res) {
res.render('users/add', {
user: req.user,
message: req.flash('addUserMessage')
});
});
router.post('/user/add', function (req, res) {
User.findOne({ 'email' : req.body.email }, function (err, user) {
if (err)
res.redirect('/error');
if (user) {
req.flash('addUserMessage', 'This email exists already');
res.redirect('/user/add');
} else {
var newUser = new User();
newUser.email = req.body.email;
newUser.firstName = req.body.firstName;
newUser.lastName = req.body.lastName;
newUser.save(function(err) {
if (err)
throw err;
req.flash('addUserMessage', 'Success');
res.redirect('/user/add');
});
}
});
});