MongoDB save function not being entered by program - javascript

I have the following module,
module.exports.registerUser = (userData) => {
return new Promise((resolve, reject) => {
if (userData.password !== userData.password2) {
reject("Passwords do not match!");
}
console.log(userData); //prints correctly
let newUser = new iUser(userData);
console.log(newUser); //prints correctly
newUser.save((err) => {
console.log("REACHED"); //DOES NOT ENTER
if (err) {
reject(err.code === 11000 ? 'Username already taken!' :
`Error creating User: ${err}`);
} else {
console.log(newUser);
resolve(newUser);
}
process.exit();
});
})
};
For some reason, the .save() is never invoked and line 10 is never reached... any thoughts?
Edit:
With the registerUser() module, my data-service-auth.js source file so far is:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var userSchema = new Schema({
"userName": {
type: String,
unique: true
},
"email": String,
"password": String,
"loginHistory": {
"userAgent": String,
"dateTime": Date
}
});
let iUser;
module.exports.initialize = () => {
return new Promise(function (resolve, reject) {
let db = mongoose.createConnection("mongodb://user:pass#ds237409.mlab.com:37409/web322_a6");
db.on('error', function (err) {
console.log("error!");
reject(err);
});
db.once('open', function() {
console.log("enteringgggggggggggg");
iUser = mongoose.model("iUser", userSchema);
resolve();
});
resolve();
});
};
module.exports.registerUser = (userData) => {
return new Promise((resolve, reject) => {
if (userData.password !== userData.password2) {
reject("Passwords do not match!");
}
console.log(userData);
let newUser = new iUser(userData);
newUser.save((err) => {
console.log("REACHED"); //DOES NOT ENTER
if (err) {
reject(err.code === 11000 ? 'Username already taken!' :
`Error creating User: ${err}`);
} else {
console.log(newUser);
resolve(newUser);
}
process.exit();
});
})
};
My register form POSTs to my server.js file, which has a route,
app.post("/register", (req, res) => {
dataServiceAuth.registerUser(req.body).then((data) => {
res.render('register', {successMessage: "User Created"});
}).catch((err) => {
console.log("Error: " + err);
res.render('register', {errorMessage: err, userName: req.body.userName});
})
});
And my register.hbs view is, (apologies if formatting is terrible, new coder here):
<h2>Register</h2>
<hr />
<form method="post" action="/register">
{{!-- form --}}
</form>
{{#if errorMessage }}
<div class="alert">
<strong>Error:</strong> {{errorMessage}}</div>
{{else if successMessage}}
<div class="success">
<strong>Success:</strong> {{successMessage}}
</div><a class="btn-right"
href="/login">Proceed to Log in</a>
<br />
<br />
<br />
{{/if}}
I assume it has to be the .save() function, because console.log("REACHED"); is never reached and executed, however calls to console.log(userData) or console.log(newUser); after that instance is created yield expected results.

Related

Node Js: Remove string array element from mongoDB

I have a user schema as follows:
const UserSchema = new mongoose.Schema({
skills: [String]
});
module.exports = mongoose.model("User", UserSchema);
And a Fetch request to delete a skill as follows:
const deleteItem = async (id) => {
try {
await fetch(`http://localhost:5000/api/user/deleteskill`, {
method: "DELETE",
headers: { "Content-Type": "application/JSON", token: accessToken },
body: JSON.stringify({ userid: userid , skill:id}),
})
.then((res) => res.json())
.then((data) => {
console.log("USER SKILLS:", data.userskills);
});
} catch (err) {
console.log(err);
}
};
Server
const deleteSkill = async (req, res) => {
try {
const user = await User.findById(req.body.userid)
//user.skills.pull(req.body.skill);
// removeskill = user.skills.filter(function(item) {
// return item !== req.body.skill
// })
if (user.skills.includes(req.body.skill)) {
res.status(400).json("Item Still Exists");
} else {
res.status(200).json("Item Deleted");
}
} catch (error) {
res.status(500).send({ error: error.message });
}
};
the array is in the following structure
[
'skill1', 'java', 'skill5'
]
I have tried to remove the user skill from the array in several ways but I still get res.status(400).json("Item Still Exists");. What I'm doing wrong?
Use the findOneAndUpdate method to find a document with the user id and update it in one atomic operation:
const deleteSkill = async (req, res) => {
try {
let message = "Item Deleted";
let status = 200;
const user = await User.findOneAndUpdate(
{ _id: req.body.userid },
{ $pull: { skills: req.body.skill } },
{ new: true }
)
if (user && user.skills.includes(req.body.skill)) {
message = "Item Still Exists";
status = 400;
} else if (!user) {
message = "User Not Found";
status = 404;
}
res.status(status).send({ message });
} catch (error) {
res.status(500).send({ error: error.message });
}
};
I believe you want to remove skills from the database then the following function could help you out.
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
var myquery = { userid: userid, skillid: skillid};
dbo.collection("skills").deleteOne(myquery, function(err, obj) {
if (err) throw err;
console.log("1 document deleted");
db.close();
});
});
You have a method of removing elements from arrays, if you want to remove the first one you could use array.shift (more on it here), but if you want to delete it completely from your database you could always, find it and then update it.
User.update({ _id: userid }, { $pull: { "skills": "[skill]" }})

Console output in Mongoose promise not working

I am just working on an analysis project. I have a create method in node but I don't know why suddenly this is happening. I have connected to the database successfully. and wrote created a mongoose model successfully.Now in below code promise.then() is not visited. document is not created. but if I removed any required field, it throws a error as expected.
my create method:
create: function (doc) {
return new Promise((resolve, reject) => {
bcrypt.hash(doc.password, saltRounds).then((hash) => {
doc.password = hash;
console.log(doc); //works
Account.create(doc).then((account) => {
console.log(account); //not working, no error, successful execution, code exit 0.
resolve(account);
}).catch((err) => {
console.log(account); //nothing printed
reject(err);
});
}).catch(err => {
console.log(account); //nothing printed
reject(err);
});
});
}
my database connection in database/db.js
const mongoose = require('mongoose');
require('dotenv').config();
const database = {
connect: function () {
mongoose.connect(
process.env.MONGO_URI + '?retryWrites=true',
{ useNewUrlParser: true, useUnifiedTopology: true }
).then(
function () {
console.log('database connected successfully');
}).catch(error => {
console.log(error);
});
}
};
module.exports = database;
My whole controller code controllers/account.js:
Account = require('../models/account');
const bcrypt = require('bcrypt');
const saltRounds = 10;
authController = {
create: function (doc) {
return new Promise((resolve, reject) => {
bcrypt.hash(doc.password, saltRounds).then((hash) => {
doc.password = hash;
let promise = Account.create(doc);
promise.then((account) => {
console.log(account);
resolve(account);
}).catch((err) => {
console.log(err);
reject(err);
});
}).catch(err => {
console.log(err);
reject(err);
});
});
},
show: function (email) {
return new Promise((resolve, reject) => {
let filter = {email: email};
Account.findOne(filter).then((account) => {
resolve(account);
}).catch((err) => {
reject(err);
});
});
},
update: function (id, update) {
return new Promise((resolve, reject) => {
let filter = {_id: id};
Account.findOneAndUpdate(filter, update).then((account) => {
resolve(account);
}).catch((err) => {
reject(err);
});
});
},
destroy: function (id) {
return new Promise((resolve, reject) => {
let filter = {_id: id};
Account.findOneAndDelete(filter).then(() => {
resolve({deleted: true});
}).catch((err) => {
reject(err);
});
});
},
compare: function (doc) {
return new Promise((resolve, reject) => {
let filter = {email: doc.email};
Account.findOne(filter).then(user => {
bcrypt.compareSync(doc.password, user.password).then((result) => {
resolve(result);
}).catch((err) => {
reject(err);
});
}).catch((err) => {
reject(err);
});
});
}
};
module.exports = authController;
My model for account in models/account.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const accountSchema = new Schema({
first: {
type: String,
required: true
},
last: {
type: String,
required: false
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
required: true
},
boards: [{
type: mongoose.Schema.Types.ObjectId, ref: 'Board',
required: false
}]
},
{
timestamps: true
});
Account = mongoose.connection.model('User', accountSchema);
module.exports = Account;
my test.js code:
const accountCtrl = require('./controllers/account');
const account = {
first: "User 1",
last: "Last 1",
email: "email1#tasks.com",
password: "password",
role: "test",
};
accountCtrl.create(account).then((result) => {console.log(result)}).catch((err) => {console.log(err)});

Why am I getting Promise Pending despite using await in my controller?

I have a repository where I connect directly to my model to insert some data, it creates the data successfully but when I connect my controller to this repository, I get a nulled response, if I log it in the repository itself I get Promise . Please checkout my code below:-
Repository.js
exports.register = (request) => {
const data = UserModel.findOne({email: request.email})
.then(user => {
if(user)
{
return {status: 400, message: 'Email Already exist'}
} else {
return bcrypt.genSalt(10, (err, salt) => {
const newUser = new UserModel({
username: request.username,
email: request.email,
password: request.password
});
return bcrypt.hash(newUser.password, salt, async (err, hash) => {
if(err) throw err;
newUser.password = hash;
return newUser.save()
.then(user => {
const token = jwt.sign({id: user._id}, process.env.JWT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
return {status: 200, message: 'Successfully Registered', auth: true, token: token, user: user}
})
.catch(err => {
return {status: 400, message: err}
})
})
})
}
})
console.log(data) // This part is return Promise <pending>
return data;
};
Controller.js
exports.SeedRegisteration = async (req, res, next) => {
try {
let element = await userRepo.register({username: "Testin", email: "Testin#test.com", "password":
"joe" });
return await res.status(200).json({ status: 200, data: element })
} catch (e) {
return res.status(400).json({ status: 400, message: e.message });
}
};
Works fine but does not return data
Here's the register function using the Promise version of bcrypt (if you don't supply a callback, the bcrypt functions return a Promise
exports.register = (request) =>
UserModel.findOne({
email: request.email
})
.then(user => {
if (user) {
throw 'Email Already exist'
}
})
.then(() => bcrypt.genSalt(10))
.then(salt => {
const newUser = new UserModel({
username: request.username,
email: request.email,
password: request.password
});
return bcrypt.hash(newUser.password, salt)
.then((hash) => {
newUser.password = hash;
return newUser.save();
})
}).then(user => {
const token = jwt.sign({
id: user._id
}, process.env.JWT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
return {
status: 200,
message: 'Successfully Registered',
auth: true,
token: token,
user: user
}
}).catch(err => {
return {
status: 400,
message: err
}
});
Note: there is ONE nested .then - this code could be perfectly flat if you used async/await in register - however I was not prepared to perform such a big rewrite for the answer. Now that the code is in a nice almost flat promise chain, it's relatively simple to convert the whole thing into async/await style
There are too many return statements which return promise. Please update your code in to the following:
exports.register = (request) => {
return new Promise((resolve, reject) => {
try {
UserModel.findOne({ email: request.email })
.then(user => {
if (user) {
return reject({ status: 400, message: 'Email Already exist' })
} else {
bcrypt.genSalt(10, (err, salt) => {
const newUser = new UserModel({
username: request.username,
email: request.email,
password: request.password
});
bcrypt.hash(newUser.password, salt, async (err, hash) => {
if (err) return reject(err);
newUser.password = hash;
newUser.save()
.then(user => {
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
return resolve({ status: 200, message: 'Successfully Registered', auth: true, token: token, user: user })
})
.catch(err => {
return reject({ status: 400, message: err })
})
})
})
}
}).catch(err => {
return reject(err)
})
} catch (error) {
return reject(error)
}
});
};

I am not getting the mongoose queried user as the returned value

This is my apollo resolver and I want to return the user but it does not return anything and if I return the query itself then I cannot do the password checking
my code:
login: (parent, { email, password }, context, info) => {
User.findOne({ email }, function(err, user) {
if (user.length) {
bcrypt.compare(password, user[0].password, function(err, res) {
if (res) {
console.log(user[0]); // this has the user
return user[0]; // but this does not return anything
} else {
throw new ApolloError("failed");
}
});
} else {
throw new ApolloError("failed");
}
});
}
I have done this solution and it is working perfectly
login: async (parent, { email, password }, context, info) => {
const user = await attemptSignIn(email, password);
return user;
}
const attemptSignIn = async (email, password) => {
const message = "Incorrect email or password. Please try again.";
const user = await User.findOne({ email });
if (!user || !(await matchesPassword(user, password))) {
throw new AuthenticationError(message);
}
return user;
};
matchesPassword = (user, password) => {
return compare(password, user.password);
};

.then is undefined when I try to save in MongoDB

I'm new to node.js.
I got this message:
TypeError: Cannot read property 'then' of undefined
Here is the code:
router.post("/signup", (req, res) => {
const userRegister = new UserRegister({
_id: new mongoose.Types.ObjectId(),
nickname: req.body.nickname,
email: req.body.password,
password: req.body.password,
level: 0
});
console.log(req.body.nickname + " " + req.body.email + " " + req.body.password);
userRegister
.save()
.then(doc => {
console.log(doc);
res.status(200).json({
message: "User created"
});
})
.catch(err => {
if (err)
console.log("error => " + err)
res.status(409).json({
message: "ERROR"
})
});
});
and the Schema:
const mongoose = require("mongoose");
const userRegister = mongoose.Schema({
_id : mongoose.Schema.Types.ObjectId,
nickname: String,
email: String,
password: String,
level: Number
});
module.exports = mongoose.model("UserRegister", userRegister);
I don't really understand why it says ".then undefined".
(the body is good)
It seems like function "save" does not return Promise. But in source code it does...
https://github.com/Automattic/mongoose/blob/master/lib/model.js#L385
Also you can try "create" method.
https://github.com/Automattic/mongoose/blob/master/lib/model.js#L2646
Maybe it will be hellpfull:
const result = new SomeModel({...});
new Promise((resolve, reject) => {
// Save model
result.save(err => {
if (err) {
return reject(new Error(`Error with exam ersult save... ${err}`));
}
// Return saved model
return resolve(result);
})
.then(res => {
return res;
})
.catch(err => {
throw new Error(err);
});
check if the model is the promising type or not if this is not the promising then use callback
mongoose promises
assert.ok(user instanceof Promise); // this return ture or false
router.post("/signup", (req, res) => {
const userRegister = new UserRegister({
_id: new mongoose.Types.ObjectId(),
nickname: req.body.nickname,
email: req.body.password,
password: req.body.password,
level: 0
});
console.log(req.body.nickname + " " + req.body.email + " " + req.body.password);
var user = userRegister.save()
assert.ok(user instanceof Promise);
// if assert.ok return true then use user.then
// else use callback userRegister.save( function(doc){ })
user.then(doc => {
console.log(doc);
res.status(200).json({
message: "User created"
});
})
.catch(err => {
if (err)
console.log("error => " + err)
res.status(409).json({
message: "ERROR"
})
});
});
router.post("/signup", async (req, res) => {
try{
const userRegister = await UserRegister.create({
_id: new mongoose.Types.ObjectId(),
nickname: req.body.nickname,
email: req.body.password,
password: req.body.password,
level: 0
});
}
catch(err){
console.log("error => " + err)
res.status(409).json({
message: "ERROR"
})
}
console.log(userRegister);
res.status(200).json({
message: "User created"
});
});

Categories

Resources