i have this code:
i want to have another fields with the user like their phone number, but I don't know how I can add them
const userSchema = new mongoose.Schema({
username: String,
password: String
//// here i want to add another property
});
userSchema.plugin(passportLocalMongoose);
const User = mongoose.model('user', userSchema);
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
and my registering is this:
User.register({ username: req.body.username }, req.body.password, function (err) {
if (err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function () {
res.redirect("/");
});
}
});
I don't know where to add the new field
You're almost there! I would recommend to add the field within your schema.
const userSchema = new mongoose.Schema({
username: String,
password: String
phoneNumber: String,
});
Then on your register call you will pass the data into the User.register method.
const user = {
username: req.body.username,
phoneNumber: req.body.phoneNumber,
}
User.register(new User(user), req.body.password, function (err) {
// your callback logic
How can i access for example username and put it in profile page ?
model/db.js
const mongoose = require('mongoose');
const stDB = mongoose.Schema({
username : {
type: String,
required: true
},
email : {
type: String,
required: true
},
password : {
type: String,
required: true
}
});
module.exports = mongoose.model('db', stDB);
views/profiles/instructor.hbs
<h5>I want access username from db and put it here!</h5>
index.js
const users = require('../model/db'); // db that username stored in it (model/db.js)
//instructor
router.get('/profiles/instructor', function (req, res, next) {
res.render('./profiles/instructor', {
title: 'Instructor'
});
});
router.post('/signup', function (req, res, next){
const newUser = new users({
username : req.body.username,
email : req.body.email,
password : req.body.password,
});
users.findOne({email : req.body.email}, (err, doc)=>{
if(err){
console.log('ERR while getting username =>' + err);
return ;
}
if(doc){
res.send('this email is already registered before!');
return ;
}
newUser.save((err, doc)=>{
if(err){
console.log('err' + err)
}else{
console.log(doc)
res.redirect('/login')
}
});
});
// etc.....
I'm using Node.js with Mongoose and Passport trying to get the user to save to the DB but keep encountering the error where No Username was given. I can get it to save if just using using username and password but as soon as I try to add more fields I get the issue. This is the code I have:
app.js
const userSchema = new mongoose.Schema ({
firstname: String,
lastname: String,
username: String,
password: String,
userLevel: {type: Number},
profileImage: String,
title: String
});
//ENABLE PASSPORT LOCAL
userSchema.plugin(passportLocalMongoose, {
selectFields: ' firstname lastname username password userLevel profileImage title'
});
//CREATE NEW model
const User = new mongoose.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.get('/control', (res, req) => {
if (req.isAuthenticated()) {
res.render('control');
} else {
res.redirect('/login')
}
});
app.post("/register", (req, res) => {
User.register(new User(
{firstname: req.body.firstname},
{lastname: req.body.lastname},
{username:req.body.username},
{userLevel: 1},
{profileImage:"not set"},
{title:"not set"}
),
req.body.password,
(err, user) => {
if (err) {
console.log(err);
console.log(req.body.username);
} else {
passport.authenticate('local')(req, res, () =>{
res.redirect('/control');
});
}
});
});
Figured it out! I was using individual objects rather that just the one object :
User.register((
{firstname: req.body.firstname,
lastname: req.body.lastname,
username: req.body.username,
userLevel: 1,
profileImage:"not set",
title:"not set"
}),
req.body.password,
(err, user) => {
if (err) {
console.log(err);
console.log(req.body.username);
} else {
passport.authenticate('local')(req, res, () =>{
res.redirect('/control');
});
}
});
});
I am getting an error ValidationError: Path password is required, when trying to register a new User. I am new to Node, programming, and authentication.
Here is the code I have, and then I will walk through what I have done to try to trouble shoot it.
User model and schema
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var bcrypt = require("bcrypt-nodejs");
var UserSchema = new mongoose.Schema({
username: {type: String, unique: true, required: true},
password: {type: String, unique: true, required: true},
// avatar: String,
firstName: String,
lastName: String,
email: {type: String, unique: true, required: true},
resetPasswordToken: String,
resetPasswordExpires: Date,
// isAdmin: {type: Boolean, default: false}
});
UserSchema.plugin(passportLocalMongoose);
//save function -- hashes and then saves the password
UserSchema.pre('save', function(next) {
var user = this;
var SALT_FACTOR = 5;
if (!user.isModified('password')) return next();
bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, null, function(err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
//compares and checks password
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);
Here is my app.js file:
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
expressSanitizer = require("express-sanitizer"),
passport = require("passport"),
cookieParser = require("cookie-parser"),
LocalStrategy = require("passport-local"),
session = require("express-session"),
nodemailer = require("nodemailer"),
bcrypt = require("bcrypt-nodejs"),
async = require("async"),
crypto = require("crypto"),
flash = require("connect-flash"),
moment = require("moment"),
User = require("./models/user"),
// seedDB = require("./seeds"),
methodOverride = require("method-override");
// APP CONFIG
mongoose.connect("mongodb://localhost/blog", {useMongoClient: true});
//PRODUCTION CONFIG - LIVE URL GOES HERE!
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/assets"));
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
app.use(methodOverride("_method"));
app.use(cookieParser('secret'));
//require moment
app.locals.moment = require('moment');
// seedDB(); //seed test data!
// PASSPORT CONFIGURATION
app.use(require("express-session")({
secret: "It's a secret to everyone!!",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) return done(err);
if (!user) return done(null, false, { message: 'Incorrect username.' });
console.log(user);
User.comparePassword(password, function(err, isMatch) {
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Incorrect password.' });
}
});
});
}));
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
app.use(function(req, res, next){
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
next();
});
// REQUIRE ROUTES
var commentRoutes = require("./routes/comments"),
bpostRoutes = require("./routes/bposts"),
indexRoutes = require("./routes/index");
//USE ROUTES
app.use("/", indexRoutes);
app.use("/bposts", bpostRoutes);
app.use("/bposts/:id/comments", commentRoutes);
//RUN SERVER
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The Server Has Started!");
});
Here is the index.js route file for posting new Users
// handle sign up logic
router.post("/register", function(req, res) {
var newUser = new User({
username: req.sanitize(req.body.username),
firstName:req.sanitize(req.body.firstName),
lastName: req.sanitize(req.body.lastName),
email: req.sanitize(req.body.email),
});
console.log(newUser);
// if (req.body.adminCode === 'secretcode123') {
// newUser.isAdmin = true;
// }
User.register(newUser, req.body.password, function(err, user) {
if (err) {
console.log(err);
return res.render("register", { error: err.message });
}
passport.authenticate("local")(req, res, function() {
req.flash("success", "Successfully Signed Up! Nice to meet you " + req.body.username);
res.redirect("/bposts");
});
});
});
As you can see in the index.js
I did a console.log(newUser) and it brings back the entire newUser object.
{ username: 'apple',
firstName: 'apple',
lastName: 'apple',
email: 'apple#gmail.com',
_id: 5a2eac41720dc60acffa02f4 }
Outside of this I am not sure what other testing I could do to locate whats happening behind the scenes. Any help or pointers on how to think about this kind of problem in the future so I can resolve it myself would be awesome. Thanks.
Here is the full StackTrace as well if it helps:
{ ValidationError: User validation failed: password: Path `password` is required.
at MongooseError.ValidationError.inspect (/home/ubuntu/workspace/node_modules/mongoose/lib/error/validation.js:57:23)
at formatValue (util.js:351:36)
at inspect (util.js:185:10)
at exports.format (util.js:71:24)
at Console.log (console.js:43:37)
at /home/ubuntu/workspace/routes/index.js:35:21
at /home/ubuntu/workspace/node_modules/passport-local-mongoose/index.js:213:33
at /home/ubuntu/workspace/node_modules/mongoose/lib/model.js:4038:16
at /home/ubuntu/workspace/node_modules/mongoose/lib/services/model/applyHooks.js:175:17
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
errors:
{ password:
{ ValidatorError: Path `password` is required.
at MongooseError.ValidatorError (/home/ubuntu/workspace/node_modules/mongoose/lib/error/validator.js:25:11)
at validate (/home/ubuntu/workspace/node_modules/mongoose/lib/schematype.js:782:13)
at /home/ubuntu/workspace/node_modules/mongoose/lib/schematype.js:829:11
at Array.forEach (native)
at SchemaString.SchemaType.doValidate (/home/ubuntu/workspace/node_modules/mongoose/lib/schematype.js:789:19)
at /home/ubuntu/workspace/node_modules/mongoose/lib/document.js:1528:9
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
message: 'Path `password` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'password',
value: undefined,
reason: undefined,
'$isValidatorError': true } },
_message: 'User validation failed',
name: 'ValidationError' }
Basically you defined that you need a password in your models.
var UserSchema = new mongoose.Schema({
username: {type: String, unique: true, required: true},
password: {type: String, unique: true, required: true}, // <-- See here
firstName: String,
lastName: String,
email: {type: String, unique: true, required: true},
resetPasswordToken: String,
resetPasswordExpires: Date
});
But when you are saving you aren't passing it a password:
var newUser = new User({
username: req.sanitize(req.body.username),
firstName:req.sanitize(req.body.firstName),
lastName: req.sanitize(req.body.lastName),
email: req.sanitize(req.body.email),
/* password: req.sanitize(req.body.password) // <- Probably missing something like this.*/
});
I didn't write the following blog, but I think it might be helpful for you.
https://github.com/DDCreationStudios/Writing/blob/master/articles/AuthenticationIntro.md#user-registration
The way you did the passport authentication, it does not need to have the password required true in the user schema. Passport will automatically check the password if it's missing. If password is missing, passport will throw an error. So no need to make the password required true because passport will do the same job internally. This worked for me.
user.js
var userSchema=new mongoose.Schema({
username:{type:String,required:true},
email:{type:String,required:true},
password:String
});
server.js
app.post("/signUp",(req,res)=>{
User.register(new User({username:req.body.username,email:req.body.email}),req.body.password,(err,user)=>{
if(err){
console.log(err);
}else{
passport.authenticate("local")(req,res,()=>{
res.redirect("/");
});
}
});
});
var UserSchema = new mongoose.Schema({
username: {type: String, unique: true, required: true},
password: String ,//remove previous line and just add String to password field.
// avatar: String,
firstName: String,
lastName: String,
email: {type: String, unique: true, required: true},
resetPasswordToken: String,
resetPasswordExpires: Date,
// isAdmin: {type: Boolean, default: false}
});
You had this issue because you set the password field in your schema to
password: {type: String, required: true},
. You do not need that.
Use the info below and you will be fine.
password: {type: String}
See the working code below:
**user.js**
const mongoose = require('mongoose');
const passportLocalMongoose = require('passport-local-mongoose');
const userSchema = new mongoose.Schema({
username: {type: String, required: true},
password: {type: String} // no need to add required!
});
**server.js**
app.post('/register', (req, res) => {
const { username, password } = req.body;
User.register(new User({ username }), password, (err,user) => {
if (err) {
return res.render('register', { message: err.message, messageType:
'error', user: req.user });
}else{
passport.authenticate('local')(req, res, () => {
res.redirect('/dashboard');
});
}
});
});
I am trying to access the same database/model for a sign-up and sign-in function but everytime I try to run my node app I get this error message "cannot overwrite 'user' model once compiled" here's my code:
//sign-up schema
var Schema = new mongoose.Schema({
_id: String,
name: String,
username: String,
password: String,
age: Number
});
var user = mongoose.model('users', Schema);
//sign-up login
app.post('/new', function(req, res) {
new user({
_id: req.body.email,
name: req.body.name,
username: req.body.username,
password: req.body.password,
age: req.body.age
}).save(function(err, doc){
if(err) res.json(err);
else res.send('Successfully Signed up');
});
});
//login schema
var Schema = mongoose.Schema;
var UserDetail = new Schema({
username: String,
password: String
}, {
collection: 'users'
});
var UserDetails = mongoose.model('users', UserDetail);
//login logic
passport.use(new LocalStrategy(function(username, password, done) {
process.nextTick(function() {
UserDetails.findOne({
'username': username,
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
if (user.password != password) {
return done(null, false);
}
return done(null, user);
});
});
}));
You can still use the same schema to lookup.
Schema
var Schema = new mongoose.Schema({
_id: String,
name: String,
username: String,
password: String,
age: Number
});
var user = mongoose.model('users', Schema);
Registration
app.post('/new', function(req, res) {
new user({
_id: req.body.email,
name: req.body.name,
username: req.body.username,
password: req.body.password,
age: req.body.age
}).save(function(err, doc) {
if (err) res.json(err);
else res.send('Successfully Signed up');
});
});
Login
passport.use(new LocalStrategy(function(username, password, done) {
process.nextTick(function() {
user.findOne({
'username': username
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false);
}
if (user.password !== password) {
return done(null, false);
}
return done(null, user);
});
});
}));
If you don't want to return the password in the response, just add
delete user.password;
before the callback.