mongoose save to 2 collection - javascript

Hello guys i really need help for this one . It's been bugging me for how many days
model/user.js
var UserSchema = mongoose.Schema({
username:{
type: String,
unique: true,
index:true
},
password:{
type:String
},
email:{
type:String,
required: true
// unique: true
},
authToken:{
type: String,
required: true,
unique: true
},
IsAuthenticated:{
type: Boolean,
required: true
},
name:{
type:String
},
field:{
type:String
},
e_money:{
type:Number //this is the integer form in mongoose
}
});
//accesible variable from the outside
var User = module.exports = mongoose.model('users', UserSchema);
var InfoUser = module.exports = mongoose.model('infouser', UserSchema);
and how i save is like this
var User = require('../models/user);
var newUser = new User({
name: name,
email: email,
authToken: authToken,
IsAuthenticated: false,
username: username,
password: password,
field: field,
e_money: e_money //temporary emoney
});
var newUser2 = new InfoUser({
name: name,
email: email,
authToken: authToken,
IsAuthenticated: false,
username: username,
password: password,
field: field,
e_money: e_money //temporary emoney
});
//save the newly created user to database
User.createUser(newUser,function(err, user){
if(err) throw err;
console.log(user);
)};
User.createUser(newUser2,function(err,user){
if(err) throw err;
console.log(user);
)};
What is the problem it always says that the infouser is not defined. Can someone plase

The problem is that you are exporting two different models through the same module.exports. Instead I would recommend that you export them separately:
model/user.js
// You can add instance methods like this:
UserSchema.methods.createUser = function(user) {
// Whatever you want to do here
};
var User = mongoose.model('users', UserSchema);
var InfoUser = mongoose.model('infouser', UserSchema);
exports.User = User;
exports.InfoUser = InfoUser;
/*
You could also do this as:
module.exports = { User: User, InfoUser: InfoUser };
*/
Then when you want to use them:
var User = require('../models/user').User;
var InfoUser = require('../models/user').InfoUser;

Related

How to Export Functions from Mongoose Model and Use it in a Controller in NodeJs

I want to create certain functions in my mongoose models and export them and then use them in my controllers.
But when i try to export and use that function in my controller it just tells me that it is not a function.
For instance i am trying to create a register function in my User model and use it in my controller, but it is throwing an error
"TypeError: User.register is not a function
"
What am i doing wrong?
Here is my code:
User.js:
const usersSchema = new Schema({
name: { type: String, required: true },
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, unique: true },
verified: { type: Boolean, default: false },
})
exports.register = async (studentID, name, username, email, password, verified ) => {
const exists = await this.find({ email })
if(exists) {
throw Error("User Already Exists")
}
const salt = await bcrypt.genSalt(10)
const hash = await bcrypt.hash(password, salt)
let userDocument = {
name: name,
username: username,
email: email,
password: hash,
verified: verified
}
const user = await this.insertOne(userDocument)
return user
}
UsersController.js:
const User = require('../models/User')
router.post('/register', (req, res, next) => {
const { studentID, name, username, email, password, verified } = req.body
User.register(req.body).then((response) => {
if(response) {
res.json({
msg:"registered"
})
} else {
res.json({
msg:"failed"
})
}
})
});
use -> "module.exports = mongoose.model('User', userSchema)" at end of you model's file in order to use your "users" in other controller functions.
Below I've tweaked your code a little bit.
user.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const usersSchema = new Schema({
name: { type: String, required: true },
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, unique: true },
verified: { type: Boolean, default: false },
});
module.exports = mongoose.model('User', userSchema);
usersController.js:
const bcrypt = require('bcryptjs');
const User = require('../models/user');
router.post('/register', async (req, res, next) => {
const { studentID, name, username, email, password, verified } = req.body;
try {
const exists = await User.findOne({ email: email });
if (exists) {
throw Error("User Already Exists");
}
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
let userDocument = {
name: name,
username: username,
email: email,
password: hash,
verified: verified
}
const user = new User(userDocument); // instead of insertOne, create an new object of that model and use .save() method to save the data in collection.
const result = await user.save();
res.status(201).json({
msg: "registered"
});
} catch (err) {
const error = new Error(err);
error.httpStatusCode = 500;
return next(error);
}
});

Mongoose save function is not working and returns empty {} object

I'm working on creating Auth API using Mongo and Nodejs. I have done the initial part. But when i hit the register API, it returns an empty object. Here's my scheme:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
min: 6,
max: 255
},
email: {
type: String,
required: true,
max: 255,
min: 6
},
password: {
type: String,
required: true,
max: 1024,
min: 6
},
date: {
type: Date,
default: Date.now
}
});
const User = mongoose.model('User', userSchema);
module.exports = User;
And here's where the request is being sent:
const router = require('express').Router();
const User = require('../model/User');
router.post('/register', async (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
try{
const savedUser = await user.save();
res.send(savedUser);
}catch(err){
res.status(400).send(err);
}
})
module.exports = router;
Now the user.save is not working for some reason. Not sure what i'm doing wrong. Thanks in advance.
It automatically gets the _id when it creates an object from the User Scheme.So it would be pointless to reassign
try{
await user.save();
res.send(user);
}catch(err){
res.status(400).send(err);
}

Login verification and Password recovery with JWT

I'm working on a web app and I wanna try using JWT for my user authentication and password recovery. I need JWT to verify the valid user from my DB. I tried this:
login.js:
var User = require("../model/user/registerSchema").User;
var bcrypt = require('bcrypt');
var utils = require('../util/util'),
config = require('../config'),
jwt = require('jsonwebtoken');
/* Login Route. */
route = (app)=>{
//POST
app.post ('/login', (req, res) => {
let {userName, password} = req.body;
if (!utils.noEmptyParams(req.body)) res.json({success: false, message: config.messages.NO_DATA});
else
User.findOne({userName, password}, {password: 0})
.exec()
.then(user => {
if (user) {
user = JSON.parse(JSON.stringify(user));
jwt.sign(user, config.jwt.secret, config.jwt.options, (err, token) => {
res.json({
success: true,
user,
token,
});
});
} else {
res.json({success: false, message: config.messages.INVALID_CREDENTIALS});
}
})
.catch(error => {
utils.error(error);
res.json({success: false});
});
});
}
module.exports.route = route;
registerSchema.js
var mongoose = require("mongoose"),
db = global.db,
bcrypt = require('bcrypt');
var User = new mongoose.Schema();
// MONGOOSE MODEL CONFIGURATION
const RegisterSchema = new mongoose.Schema({
access:{
type: String,
required:[true, 'please select proffession']
},
phone: {
type: String,
required: [true, 'Please add a username'],
unique: true
},
firstName: {
type: String,
required: [true, 'Please enter your firstname']
},
lastName: {
type: String,
required: [true, 'Please add your last name']
},
password: {
type: String,
required: [true, 'Please add a password']
},
userName: {
type: String,
required: [true, 'Please add an email address'],
unique: true
},
companyName: {
type: String
},
});
RegisterSchema.pre('save', function(next){
var user = this;
bcrypt.hash(user.password, 10, function(err, hash){
if(err){
return next(err);
}
user.password= hash;
next()
})
})
module.exports = mongoose.model('User', RegisterSchema);
I am running on Node version: v9.4.0, I'm using postman to test. When I try posting the require fields,
{
"userName": "njksdnf#fds.com",
"password": "1234567"
}
I got this error:
TypeError: Cannot read property 'findOne' of undefined
at app.post (/home/user/Home/Node/Routers/login.js:19:18)
I have seen WT-user-authentication-API-bolilerplate
, but it doesn't seem to help fully.
Any idea on how I can resolve it and how JWT can be used in this case for password recovery?
For the
TypeError: Cannot read property 'findOne' of undefined
at app.post (/home/user/Home/Node/Routers/login.js:19:18)
gotten from postman, all thanks to Striped in the comment. removing the.User did the whole magic for me.
Making my code to now be:
var User = require("../model/user/registerSchema");
instead of:
var User = require("../model/user/registerSchema").User;
Still left with the question "Any idea on how JWT can be used in this case for password recovery?

How to save nested mongoDB properties with mongoose?

Let say that i want to make a user schema with nested properties:
var userSchema = new mongoose.Schema({
username: { type: String, unique: true, lowercase: true },
/* ... some other properties ... */
profile: {
firstName: { type: String, default: '' },
/* ... some other properties ... */
},
});
module.exports = mongoose.model('User', userSchema);
Now if i want to save a user in a nodejs framework like ExpressJs, i will save it like so:
var user = new User({
username: req.body.username,
profile.firstName: req.body.firstName /* this is what i want to achive here */
});
user.save(function(err) {
if (!err) {
console.log('User created');
}
});
And i want to know if my Schema is good, or it's best practice to make all the properties in the root, as this:
var userSchema = new mongoose.Schema({
username: { type: String, unique: true, lowercase: true },
firstName: { type: String },
/* ... some other properties ... */
},
});
Your schema is good, but you cant define nested properties on the root of a new object as you did in your second code sample without quoting them. It should look like this:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var User = mongoose.model('User', {
username: String,
profile: {
firstName: String
}
});
var user1 = new User(
{
username: 'Zildjian',
'profile.firstName':'test'
});
user1.save(function (err) {
if (err) // ...
console.log('meow');
process.exit(0);
});
Although I would recommend nesting it properly like this
var user1 = new User(
{
username: 'Zildjian',
profile: {
firstName:'test'
}
});

Got undefined is not a function when tried to use methods function by node.js

i am working on the authenticate function by node.js.
So when i tried to use methods.comparePassword function that i made on top to validate the password that user put on the form,
i got an error but can't figure out why?
first i have UserSchema like this.
// user schema
var UserSchema = new Schema({
name: String,
username: {
type: String,
required: true,
index: {
unique: true
}
},
password: {
type: String,
required: true,
select: false
}
});
var User = mongoose.model('User', UserSchema);
Then i created the methods to comparePassword like this.
// method to compare a given password with the database hash
UserSchema.methods.comparePassword = function(password) {
var user = this;
return bcrypt.compareSync(password, user.password);
};
Then i made the route to authenticate and generate the token to users like this.
apiRouter.post('/authenticate',function(req,res){
// find the user
// select the name username and password explicitly
User.findOne({
username: req.body.username
}).select('name username password').exec(function(err, user) {
if(err) throw err;
// no user with that username was found
if(!user){
res.json({
success: false,
message: 'Authentication failed. User not found.'
});
} else if(user){
// check if password matches
//console.log(req.body.password);
var validPassword = user.comparePassword(req.body.password);
//var validPassword = true; If i use this everything works fine.
if (!validPassword) {
res.json({
success: false,
message: 'Authentication failed. Wrong password.'
});
} else {
// if user is found and password is right
// create a token
var token = jwt.sign({
name: user.name,
username: user.username
}, superSecret, {
expiresInMinutes: 1440 // expires in 24 hours
});
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
});
});
But when i send the request to the server i got an error like this.
var validPassword = user.comparePassword(req.body.password);
^
TypeError: undefined is not a function
at Promise.<anonymous>
Then when i changed var validPassword = true;
Everything works fine.
Anyone know how to fix this?
Thanks!
Make sure you define these methods after creating the schema, but before creating the model.
// user schema
var UserSchema = new Schema({
name: String,
username: {
type: String,
required: true,
index: {
unique: true
}
},
password: {
type: String,
required: true,
select: false
}
});
// method to compare a given password with the database hash
UserSchema.methods.comparePassword = function(password) {
var user = this;
return bcrypt.compareSync(password, user.password);
};
var User = mongoose.model('User', UserSchema);

Categories