Mongoose userModel is not defined - node.js

I'm pretty new with nodejs and mongoDB. I have created a registration and user schema but it doesn't recognize this and send the following error:
ReferenceError: userModel is not defined
When I trace the error, I found that it doesn't recognize this keyword.
Here is user.js code:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
var userSchema = new Schema({
teamName: {
type: String,
unique: true,
trim: true,
required: true
},
faculty: {
type: String,
required: true
},
email: {
required: true,
unique: true,
trim: true,
type: String
},
password: {
required: true,
type: String
},
score: {
type: Number,
default: 0
}
});
userSchema.pre('save', function(next) {
var user = this;
bcrypt.hash(user.password, 10, (err, hash) => {
if (err) return next(err)
user.password = hash;
next();
});
})
var userModel = mongoose.model('User', userSchema);
module.exports = userModel;
server.js
router.post('/register', (req, res) => {
var newUser = {
teamName: req.body.teamName,
faculty: req.body.faculty,
email: req.body.email,
password: req.body.password
}
userModel.create(newUser, (err, user) => {
if (err) {
console.log('[Registratoin]: ' + err);
} else {
console.log(user)
console.log('[Registration]: Done');
// req.session.userID = user._id;
res.redirect('/scoreboard')
}
});
});

The this keyword in the pre-save hook in your model is not the issue.
ReferenceError: userModel is not defined
ReferenceError: "x" is not defined means that the userModel is undefined from the scope you're calling it from. (Thus you're referencing a non-existent value)
I have include it like var userModel = require('the_path')
As you're requiring and exporting the userModel correctly. I would double check the path you're importing the module from.

Related

Circular Dependency Error for deleteMany MongoDB

I am writing the Model for my Web App API, and am getting the following circular dependency error:
Warning: Accessing non-existent property 'deleteMany' of module exports inside circular dependency
(Use node --trace-warnings ... to show where the warning was created)
.
Here is my code:
const validator = require('validator')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
const Task = require('./task')
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const userSchema = new Schema({
email: {
type: String,
unique: true,
required: true,
trim: true,
lowercase: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Email is invalid.')
}
}
},
password: {
type: String,
required: true,
trim: true,
minLength: 8
},
name: {
type: String,
unique: true,
required: true,
trim: true
},
tokens: [{
token: {
type: String,
required: true
}
}]
})
userSchema.pre('save', async function(next) {
const user = this
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
}
next() // run the save() method
})
userSchema.pre('deleteOne', {document: true, query: false}, async function(next) {
const user = this
await Task.deleteMany({owner: user._id})
next()
})
userSchema.methods.toJSON = function() {
const user = this
const userObject = user.toObject()
delete userObject.password
delete userObject.__v
delete userObject.tokens
return userObject
}
userSchema.methods.generateAuthToken = async function () {
const user = this
const token = jwt.sign({ _id: user._id.toString() }, process.env.JSON_WEB_TOKEN_SECRET)
user.tokens = user.tokens.concat({ token })
await user.save()
return token
}
userSchema.statics.findByCredentials = async (email, password) => {
const user = await User.findOne({email})
if (!user) {
throw new Error('Unable to login')
}
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) {
throw new Error('Unable to login')
}
return user
}
userSchema.virtual('tasks', {
localField: '_id',
foreignField: 'owner',
ref: 'Task'
})
const User = mongoose.model('User', userSchema);
module.exports = User
Any idea what could be going wrong? I have checked my Node.js and MongoDB versions and updated them, but continue to get this same error when I try to delete. I can provide further details of my code if necessary. The problem area in question is the one leading with userScheme.pre('deleteOne'....

Trying to add new user to database (MongoDB) getting this error

I am trying to save a user to MongoDB database using post request as follow, but I got the error TypeError: User is not a function. I can't figure out anything wrong with it. The output says that error is present on the line " const user = new User(req.body);"
postman output nodejs output
is my userschema wrong or the export method is wrong.
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"
});
};
//user schema
var mongoose = require("mongoose");
const crypto = require('crypto');
const uuidv1 = require('uuid/v1');
var userSchema = new mongoose.Schema({
name:{
type:String,
required:true,
maxlenght:32,
trim: true
},
lastname:{
type: String,
maxlenght: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 = {
authenticate: 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.export = mongoose.model("User",userSchema)
Here is the issue with the code.
Line 1: const user = new User(req.body);
Line 2: user.save((err, user) => {
JS is now confused about user which is a constant variable to that of the user which is the return value of the save action.
So, to get rid of this, rename the return value of save action to something else like responseUserObj. Thus your above two lines of code should now be
const user = new User(req.body);
user.save((err, responseUserObj) => {
Happy coding.

Mongoose - Multiple models for 1 schema

I am using mongoose v5.2.17.
I was wondering is it possible to have multiple models map to the 1 schema.
For example - I have the following model
const mongoose = require('mongoose');
const validator = require('validator');
const jwt = require('jsonwebtoken');
const _ = require('lodash');
const bcrypt = require('bcryptjs');
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true,
minlength: 1,
unique: true,
validate: {
validator: validator.isEmail,
message: '{VALUE} is not a valid email',
},
},
password: {
type: String,
required: true,
minlength: 6,
},
isTrialUser: {
type: Boolean,
default: true,
},
isAdminUser: {
type: Boolean,
default: false,
}
});
UserSchema.methods.toJSON = function () {
const user = this;
const userObject = user.toObject();
return _.pick(userObject, ['_id', 'email', 'isTrialUser']);
};
UserSchema.pre('save', function (next) {
const user = this;
if (user.isModified('password')) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(user.password, salt, (hashErr, hash) => {
user.password = hash;
next();
});
});
} else {
next();
}
});
const User = mongoose.model('User', UserSchema);
module.exports = { User, UserSchema };
Is it possible for me to create another AdminModel where admin specific methods can live?
I also want to return all data from the toJSON method from the AdminModel.
Please let me know if this is possible or if there is a better way to perform such a task
Thanks
Damien
If I am understanding you correctly you want to inherit the UserModel in an AdminModel and decorate that one with extra methods etc. For that you can use util.inherits (or the so called Mongoose discriminators) like so:
function BaseSchema() {
Schema.apply(this, arguments);
this.add({
name: String,
createdAt: Date
});
}
util.inherits(BaseSchema, Schema);
var UserSchema = new BaseSchema();
var AdminSchema = new BaseSchema({ department: String });
You can read more about it in Mongoose docs.
There is also a good article on the mongoose discriminators here

Mongoose error in required properties

I'm connecting a Angular 2 app to MongoDB via Mongoose.
I'm trying to store some data, but i obtain an error on all required properties.
I set up a schema, serverside:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var uniqueValidator = require("mongoose-unique-validator");
var schema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
nome: {
type: String,
required: true
},
cognome: {
type: String,
required: true
},
dataNascita: {
type: Date
},
telefono: {
type: String
},
classifica: {
type: String
}
});
schema.plugin(uniqueValidator);
module.exports = mongoose.model("User", schema);
The user object is clearly filled:
Mongoose responds with an error:
Thanks in advance for any help.
Max
Update:
The call from a Angular service:
#Injectable()
export class AuthService {
constructor(private http: Http) {
}
addUser(utente: Utente) {
const body = JSON.stringify(utente);
return this.http.post('http://localhost:3000/utente', body)
.map((response: any) => {
console.log(response);
response.json();
})
.catch((error: Response) => Observable.throw(error.json()
));
}
}
The Moongose call:
var express = require('express');
var router = express.Router();
var User = require('../models/users');
router.post('/', function (req, res, next) {
var user = new User({
email: req.body.email,
password: req.body.password,
nome: req.body.nome,
cognome: req.body.cognome,
dataNascita: req.body.dataNascita,
telefono: req.body.telefono,
classifica: req.body.classifica
});
console.log(res);
user.save(function (err, result){
console.log(err);
console.log(res);
if (err){
return res.status(500).json({
titolo: "Errore durante il salvataggio",
errore: err
});
}
res.status(201).json({
messaggio: 'Utente salvato correttamente',
oggetto: res
});
});
});

NodeJS/Mongoose: exports.function and module.exports incompatibility

This is my User.js
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = mongoose.Schema({
email: {
type: String,
unique: true
},
password: String,
});
var User = mongoose.model('User', UserSchema);
function createDefaultUsers() {
User.find({}).exec(function (err, collection) {
if (collection.length === 0) {
User.create({
email: 'name#eemail.com',
password: 'password0',
});
}
exports.createDefaultUsers = createDefaultUsers;
module.exports = mongoose.model('User', UserSchema);
I call createDefaultUsers in another file to create initial users.
But when this gives me the following error:
userModel.createDefaultUsers();
^ TypeError: Object function model(doc, fields, skipId) {
if (!(this instanceof model))
return new model(doc, fields, skipId);
Model.call(this, doc, fields, skipId); } has no method 'createDefaultUsers'
But if I comment out module.exports = mongoose.model('User', UserSchema); it compiles fine.
What am I doing wrong.
Cheers.
In this case, you should attach that function as a static method and export the model.
var mongoose = require('mongoose');
var bcrypt = require('bcrypt-nodejs');
var UserSchema = mongoose.Schema({
email: {
type: String,
unique: true
},
password: String,
});
UserSchema.statics.createDefaultUsers = function createDefaultUsers(cb) {
return User.find({}).exec(function (err, collection) {
if (collection.length === 0) {
User.create({
email: 'name#eemail.com',
password: 'password0',
}, cb);
} else {
if (cb) {
cb(err, collection);
}
}
});
};
var User = mongoose.model('User', UserSchema);
module.exports = User;
Now you can use it directly from the model (which is likely very similar to how you're already using it):
require('./models/user').createDefaultUsers();

Resources