NodeJs mongoose CastError on method findById - node.js

I have a problem with mongoose, when i use the method findByIdi receive error :
CastError: Cast to ObjectId failed for value "protected" at path "_id"
My _id is valid tested by mongoose.Types.ObjectId.isValid(_id);
I also tested to convert my string _id to ObjectId: mongoose.Types.ObjectId(_id) same error...
My Model is :
var UserSchema = new Schema({
_id: {type:ObjectIdSchema, default: function () { return new ObjectId()} },
email: { type: String, unique: true, required: true },
pseudonyme: { type: String, unique: true, required: true },
password: { type: String, required: true }})
I use node v6.7.0 and mongoose v4.6.5
Thks in advance for your help,
Full Code :
const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
//payload { _id: "58109f58e1bc7e3f28751cdb",email: "antoine.drian#laposte.net",exp: 1477494763,firstName: "antoine",iat: 1477484683,lastName: "drian"}
var isValid = mongoose.Types.ObjectId.isValid(payload._id);
if(!isValid) done(null, false);
var ObjectId = mongoose.Types.ObjectId;
var _id = ObjectId(payload._id);
User.findById( _id , function(err, user) {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});
});
models/User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectIdSchema = Schema.ObjectId;
var ObjectId = mongoose.Types.ObjectId;
var bcrypt = require('bcrypt');
// set up a mongoose model
var UserSchema = new Schema({
// _id: {type: Schema.Types.ObjectId, auto: true},
email: { type: String, unique: true, required: true },
pseudonyme: { type: String, unique: true, required: true },
password: { type: String, required: true },
profile: {
firstName: { type: String, required: true },
lastName: { type: String, required: true },
birthdate: { type: Date },
gender: { type: String, enum: ['Male', 'Female'] },
}
}, {
timestamps: true
});
UserSchema.pre('save', function(next) {
var user = this;
if (this.isModified('password') || this.isNew) {
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
return next();
}
});
UserSchema.methods.comparePassword = function(passw, cb) {
bcrypt.compare(passw, this.password, function(err, isMatch) {
if (err) {
return cb(err);
}
cb(null, isMatch);
});
};
module.exports = mongoose.model('User', UserSchema);

I found the solution it was just a route conflict between two routes with ExpressJS.
There is no relation between the both.
Thks all people for your help

Try removing the _id from your schema.
var UserSchema = new Schema({
email: { type: String, unique: true, required: true },
pseudonyme: { type: String, unique: true, required: true },
password: { type: String, required: true }
});
Try using the playload_id directly without casting it like below
User.findById( payload._id , function(err, user) {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});

first don't define _id in your Schema, and change 'isValid', use this instead
var UserSchema = new Schema({
email: { type: String, unique: true, required: true },
pseudonyme: { type: String, unique: true, required: true },
password: { type: String, required: true }
})
and if is there an error keep it as first parameter EX : done(err) otherwise use null, EX: done(null, result)
const jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) {
var _id = mongoose.mongo.ObjectId(payload._id);
User.find( {_id : _id} , function(err, user) {
if (err) { return done(err); }
if (user) {
done(null, user);
} else {
done(new Error('User not found!!!'));
}
});
});

Related

Routing in NodeJs

I am working on an eCommerce application, and I am trying to save users in my database but when I hit the API in the postmen then instead of :
res.json({
name: user.name,
email: user.email,
id: user._id
});
});
**instead of this code following code is running
user.save((err, user) => {
if (err) {
return res.status(400).json({
err: "NOT able to save user in DB"
});
}
//the complete code of my "auth.js" file is as following:
const User = require("../models/user");
exports.signup = (req, res) => {
const user = new User(req.body);
user.save((err, user) => {
if (err) {
return res.status(400).json({
err: "NOT able to save user in DB"
});
}
res.json({
name: user.name,
email: user.email,
id: user._id
});
});
};
exports.signout = (req, res) => {
res.json({
message: "User signout"
});
};
///and the complete code of my user model file is as following:
var mongoose = require("mongoose");
const crypto = require("crypto");
const uuidv1 = require("uuid/v1");
var userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
maxlength: 32,
trim: true
},
lastname: {
type: String,
maxlength: 32,
trim: true
},
email: {
type: String,
trim: true,
required: true,
unique: true
},
userinfo: {
type: String,
trim: true
},
encry_password: {
type: String,
required: true
},
salt: String,
role: {
type: Number,
default: 0
},
purchases: {
type: Array,
default: []
}
},
{ timestamps: true }
);
userSchema
.virtual("password")
.set(function(password) {
this._password = password;
this.salt = uuidv1();
this.encry_password = this.securePassword(password);
})
.get(function() {
return this._password;
});
userSchema.methods = {
autheticate: function(plainpassword) {
return this.securePassword(plainpassword) === this.encry_password;
},
securePassword: function(plainpassword) {
if (!plainpassword) return "";
try {
return crypto
.createHmac("sha256", this.salt)
.update(plainpassword)
.digest("hex");
} catch (err) {
return "";
}
}
};
module.exports = mongoose.model("User", userSchema);
SO please anyone tell me how to solve this problem while hiting this code to api mongo shell is also opend and mean while i also keep ROBO3T connected.

How can I create a users role in Node.js?

I want to create a "users" role in Node.js. I have both "moderator" and "admin" accounts but I want to restrict some pages from the moderator. I have to build a middleware but it restricts both the admin from the protected page.
This is my route:
function checkRole(role) {
return function (req, res, next) {
const user = User.findById(req.user._id);
if (user.roleId === role) {
next();
} else {
req.flash('error_msg', 'Payment Page is Restricted');
res.redirect('back')
}
}
}
And this is my users model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var userSchema = new Schema({
name:{
type: String,
required: true
},
email:{
type: String,
required: true
},
gender:{
type: String
},
nickname:{
type: String
},
twitter:{
type: String
},
skype:{
type: String
},
username:{
type: String,
required: true
},
password:{
type: String,
required: true
},
roleId: { type: String, lowercase: true, trim: true, enum: ['admin', 'moderator'] },
resetPasswordToken: String,
resetPasswordExpires: Date
}, {timestamps: true})
userSchema.pre('save', function(next) {
var user = this;
var SALT_FACTOR = 12;
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();
});
});
});
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);
I included the checkRole function in the page I want to restrict the moderator from, but the admin is being restricted as well. I don't know where this error is coming from.

Undefined _id populate with express, moongose/MongoDB on Nodejs

Already have the following petition of my client, need than on one request to the database extract a document joining to other documents in one, I decided, to use function populate of MongoDB with moongose, but already im stuck in a following problem:
issue
models
models/User.js:
'use strict';
var mongoose, Schema, UserSchema, schemaOptions, bcrypt;
mongoose = require('mongoose');
bcrypt = require('bcrypt');
Schema = mongoose.Schema;
schemaOptions = {
toObject: {
virtuals: true
}
,toJSON: {
virtuals: true
},
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
new: true,
runValidators: true
};
UserSchema = Schema({
_id:{
type:Number,
unique: true,
index: true
},
provider:String,
id:{
type: String
},
displayName:{
type: String,
required: [true, 'Scribe the Full name']
},
name: {
familyName:{type: String,required: [true, 'Scribe the last name']},
givenName:{type: String,required: [true, 'Scribe the first name']},
middleName:{type: String,required: [true, 'Scribe the middle name']}
},
emails:[{
value:{
type: String,
unique: true,
lowercase: true,
index: true,
validate: {
validator: function(v) {
return /^[a-zA-Z0-9\._-]+#[a-zA-Z0-9-]{2,}[.][a-zA-Z]{2,4}$/.test(v);
},
message: '{VALUE} is not a valid email!'}
},
type:{
type: String,
lowercase: true
}
}],
email:{
type: String,
unique: true,
lowercase: true,
index: true,
validate: {
validator: function(v) {
return /^[a-zA-Z0-9\._-]+#[a-zA-Z0-9-]{2,}[.][a-zA-Z]{2,4}$/.test(v);
},
message: '{VALUE} is not a valid email for autenticate!'
},
required: [true, 'Scribe a Email']
},
password: {
type: String,
required: [true, 'Scribe a password']
},
photos:[{
type: String
}],
alias: {
type: String,
required: [true, 'Scribe the alias'],
unique: true
},
birthday:{
type: Date,
required: [true, 'Select a birthday']
},
idiom: {
type: String,
required: [true, 'Select a idiom']
},
country: {
type: Number,
required: [true, 'Select a valid country'],
min:1,
max:231
},
rolId:{
type: { type: mongoose.Schema.ObjectId, ref: 'Rol' }
},
deletedAt: { type: Date, default: null }
},schemaOptions);
// Execute before each user.save() call
UserSchema.pre('save', function(next) {
var user = this;
// Break out if the password hasn't changed
if (!user.isModified('password')) return callback();
// Password changed so we need to hash it
bcrypt.genSalt(10, 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();
});
});
});
//metodo para autenticar la clave recibida
UserSchema.methods.verifyPassword = function(password, next) {
bcrypt.compare(password, this.password, function(error, isMatch) {
if (error) {
next(error);
};
next(null, isMatch);
});
};
module.exports = mongoose.model('User',UserSchema);
2. models/Rol.js:
'use strict';
var mongoose, Schema, RolSchema, schemaOptions;
mongoose = require('mongoose');
Schema = mongoose.Schema;
schemaOptions = {
toObject: {
virtuals: true
}
,toJSON: {
virtuals: true
},
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
new: true,
runValidators: true
};
RolSchema = Schema({
_id:{
type:Number,
unique: true,
index: true
},
name:{
type: String,
unique: true,
uppercase: true,
required: [true, 'Scribe a Rol']
},
deleted_at: { type: Date, default: null }
},schemaOptions);
module.exports = mongoose.model('Rol',RolSchema);
controllers/UserController.js:
'use strict';
var validator = require('validator');
var User = require('../models/User');
var Rol = require('../models/Rol');
function loggin(req, res){ console.log(req.user); return
res.status(200).send({user:req.user}); }
function createUser(req, res) {
var params , user, full_name, firstName, secondName, arrayOfName,tempUser;
params = req.body;
full_name = params.name+" "+params.last_name;
arrayOfName = params.name.split(" ");
firstName = arrayOfName[0];
secondName = arrayOfName1;
User.find({},function (error, users) {
if(error){
return res.status(500).send({message: 'Error al devolver los marcadores del servidor'});
}
Rol.findById(params.rol,function (error, rol) {
if(error){
return res.status(500).send({message: 'Error al devolver los roles del servidor'});
}
if(!rol){
return res.status(404).send({message: 'No hay rol creado! con el id: '+params.rol+', comuniquese con el
administrador'});
}
if(users.length === 0){
user = new User();
user._id = 1;
user.displayName = full_name;
user.name.familyName = params.last_name;
user.name.givenName = firstName;
user.name.middleName = secondName;
user.email = params.email;
user.password = params.password;
user.alias = params.username;
user.birthday = params.age;
user.idiom = params.idiom;
user.country = params.ubication;
user.rolId = rol._id;
user.deleted_at = null;
user.save(function (error, userStored){
console.log(error);
if(error){
return res.status(500).send({message:"Error al guardar el usuario por primera ves"});
}
return res.status(200).send({user:userStored});
});
}else{
tempUser = User.findOne({ 'email': params.email }, function (error, userOnDataBase) {
if(error){
return res.status(500).send({message: 'Error al devolver los marcadores del servidor'});
}
if(!userOnDataBase){
user = new User({
"_id":users[0]._id+1,
"displayName":full_name,
"name.familyName":params.last_name,
"name.givenName":firstName,
"name.middleName":secondName,
"email":params.email,
"password":params.password,
"alias":params.username,
"birthday":params.age,
"idiom":params.idiom,
"country":params.ubication,
"rolId":rol._id,
"deleted_at":null
}).save(function (error, userStored){
if(error){
return res.status(500).send({message:"Error al guardar el usuario"});
}
return res.status(200).send({user:userStored});
});
}else{
if (userOnDataBase.email === users[0].email){
return res.status(409).send({message: 'Correo utilizado actualmente existe!'});
}
}
});
}
});
}).limit(1).sort('-_id'); }
function getUser(req, res) {
var id = req.params.id;
res.status(200).send({user_id:id}); }
function updateUser(req, res) {
var id = req.params.id;
res.status(200).send({user_id:id}); }
function deleteUser(req, res) {
var id = req.params.id;
res.status(200).send({user_id:id}); }
module.exports = {
loggin, createUser, getUser, updateUser, deleteUser };
Already the collection rols have documents.

How create custom methods on my models with moogose

already, i want to call a method on my model, for compare the password given with the password encrypted on my database, im used a custom method on my schema, but appear the following error, when tried to execute the controller, i supose than i want to do, only can be used with "new" object, objects than already are on my database cant access to the method, thanks in advance for any help:
issue
models/User.js
'use strict';
var mongoose, Schema, UserSchema, schemaOptions, bcrypt;
mongoose = require('mongoose');
bcrypt = require('bcrypt');
Schema = mongoose.Schema;
schemaOptions = {
toObject: {
virtuals: true
}
,toJSON: {
virtuals: true
},
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
new: true,
runValidators: true
};
UserSchema = Schema({
_id:{
type:Number,
unique: true,
index: true
},
provider:String,
id:{
type: String
},
displayName:{
type: String,
required: [true, 'Scribe the Full name']
},
name: {
familyName:{type: String,required: [true, 'Scribe the last name']},
givenName:{type: String,required: [true, 'Scribe the first name']},
middleName:{type: String,required: [true, 'Scribe the middle name']}
},
emails:[{
value:{
type: String,
unique: true,
lowercase: true,
index: true,
validate: {
validator: function(v) {
return /^[a-zA-Z0-9\._-]+#[a-zA-Z0-9-]{2,}[.][a-zA-Z]{2,4}$/.test(v);
},
message: '{VALUE} is not a valid email!'}
},
type:{
type: String,
lowercase: true
}
}],
email:{
type: String,
unique: true,
lowercase: true,
index: true,
validate: {
validator: function(v) {
return /^[a-zA-Z0-9\._-]+#[a-zA-Z0-9-]{2,}[.][a-zA-Z]{2,4}$/.test(v);
},
message: '{VALUE} is not a valid email for autenticate!'
},
required: [true, 'Scribe a Email']
},
password: {
type: String,
required: [true, 'Scribe a password']
},
photos:[{
type: String
}],
alias: {
type: String,
required: [true, 'Scribe the alias'],
unique: true
},
birthday:{
type: Date,
required: [true, 'Select a birthday']
},
idiom: {
type: String,
required: [true, 'Select a idiom']
},
country: {
type: Number,
required: [true, 'Select a valid country'],
min:1,
max:231
},
rolId:{
type: Number,
required: [true, 'Select a rol'],
default: 1
},
deletedAt: { type: Date, default: null }
},schemaOptions);
// Execute before each user.save() call
UserSchema.pre('save', function(next) {
var user = this;
if(this.isModified('password') || this.isNew){
bcrypt.genSalt(10, function (error, salt){
if(error){
console.log(error);
return next(error);
}
bcrypt.hash(user.password, salt, function (error, hash){
if (error) {
console.log(error);
return next(error);
}
user.password = hash;
console.log("hashing the password!");
next();
});
});
}else{
console.log("the password dont changed!");
return next();
}
});
//metodo para autenticar la clave recibida
UserSchema.methods.verifyPassword = function(password, next) {
bcrypt.compare(password, this.password, function(error, isMatch) {
if (error) {
//return next(error);
next(error);
return false;
};
//return next(null, isMatch);
next(null,isMatch);
return true;
});
};
module.exports = mongoose.model('User',UserSchema);
controllers/UserControllers.js
'use strict';
var validator = require('validator');
var User = require('../models/User');
var Rol = require('../models/Rol');
var config = require('../config/database');
var jwt = require('jwt-simple');
function login(req, res){
var params = req.body;
User.find({email: params.email},function (error, user) {
if (error) {
return res.status(500).send({message: 'Error al devolver los marcadores del servidor'});
};
if (!user) {
return res.status(404).send({message: 'El usuario con el correo designado no se encontro!'});
}else{
User.verifyPassword(params.email, function (error, isMatch){
if(error){
console.log(error);
return false;
}
if (isMatch) {
var token = jwt.encode(user, config.secret);
return res.status(200).send({token:'JWT '+token});
}else{
return res.status(403).send({message: 'La clave no es correcta!'});
}
});
return res.status(200).send({token:user});
}
}).limit(1);
}
.
.
.
module.exports = {
login, createUser, getUser, updateUser, deleteUser
};

Mongoose objectId is not saving in another collection

I am new to mongoose and nodejs. Please help me to understand what is wrong in my code while saving collection. My user.js looks like below
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');
var UserSchema = new Schema ({
name: { type: String, required: true },
username:{ type:String, required: true, index:{ unique: true}},
password:{ type: String, required: true, select: false},
email:{ type: String, required: true, select: true},
mobile:{ type: String, required: true, select: true},
nativecid:{ type: Schema.Types.ObjectId, ref:'City'},
regdate:{ type: Date, default: Date.now },
did:{ type: String, required: false }
});
UserSchema.pre('save', function(next){
var user = this;
if(!user.isModified('password')) return next();
bcrypt.hash(user.password, null, null, function(err, hash){
if(err) return next(err);
user.password = hash;
next();
});
});
UserSchema.methods.comparePassword = function(password){
var user = this;
return bcrypt.compareSync(password, user.password);
};
module.exports = mongoose.model('User', UserSchema);
And my City model ie city.js looks like below
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CitySchema = new Schema({
name: { type: String, required: true },
status: { type: Boolean, default: true },
date: { type: Date, default: Date.now }
});
module.exports = mongoose.model( 'City', CitySchema );
City is already stored in database as below
{ "_id" : ObjectId("56a4a0adb0f445561cfd4e37"), "name" : "New York", "date" : ISODate("2016-01-24T10:00:13.220Z"), "status" : 1, "__v" : 0 }
I want this ObjectId of New York should be saved in user collection while user signups. I am trying like below but not succeed.
var User = require('../models/user');
var City = require('../models/city');
api.post('/signup', function(req, res){
var user = new User({
name: req.body.name,
username: req.body.username,
password: req.body.password,
email: req.body.email,
mobile: req.body.mobile
});
City
.findOne({ name: "New York" })
.populate('_id')
.exec(function (err, city1) {
if(err){
res.send(err);
return;
}
console.log('The creator is %s', city1.name);
return user.nativecid = city1._id;
})
user.save(function(err){
if(err){
res.send(err);
return;
}
res.json({
success: true,
message: 'User created successfully!'
});
});
});
I am not understanding what is wrong. Please advice me.
Just save user in city.findOne (nested) and may be no need to populate you should use projection.
City.findOne({ name: "New York" }, {name:1}) // ID return defaulat
.exec(function (err, city1) {
if(err){
res.send(err);
return;
}
console.log('The creator is %s', city1.name);
user.nativecid = city1._id;
user.save(function(err1){
if(err1){
res.send(err1);
return;
}
res.json({
success: true,
message: 'User created successfully!'
});
});
})

Resources