mongoose updating a field in a MongoDB not working - mongodb

I have this code
var UserSchema = new Schema({
Username: {type: String, index: true},
Password: String,
Email: String,
Points: {type: Number, default: 0}
});
[...]
var User = db.model('User');
/*
* Function to save the points in the user's account
*/
function savePoints(name, points){
if(name != "unregistered user"){
User.find({Username: name}, function(err, users){
var oldPoints = users[0].Points;
var newPoints = oldPoints + points;
User.update({name: name}, { $inc: {Points: newPoints}}, function(err){
if(err){
console.log("some error happened when update");
}
else{
console.log("update successfull! with name = " + name);
User.find({Username: name}, function(err, users) {
console.log("updated : " + users[0].Points);
});
}
});
});
}
}
savePoints("Masiar", 666);
I would like to update my user (by finding it with its name) by
updating his/her points. I'm sure oldPoints and points contain a
value, but still my user keep being at zero points. The console prints
"update successful".
What am I doing wrong? Sorry for the stupid / noob question.
Masiar

It seems you are doing a few unstandard things:
Use findOne instead of find if you want to load just one user
Calling Model.update should be done to update records that you have not loaded
$inc is adding oldPoints, so the new value will be 2*oldPoints + newPoints
You are using name as the conditional query instead of Username
I would rewrite the code into something like this:
User.findOne({Username: name}, function(err, user){
if (err) { return next(err); }
user.Points += points;
user.save(function(err) {
if (err) { return next(err); }
});
});

follow my code guy
User.update({ username: "faibaa" },
{ $inc: { point: 200000 } }, function(err,data){
return res.send(data);
});

Related

How do you validate password using mongoose for mongoDB in an express app for logging in a user?

I am trying to have a user log in by their email and password. MongoDb docs shows hashing the password with bcrypt in the user model. It also provides a nice way to validate the password in the model as well. My problem is how to I use that validation from the "controller"? I am very aware "if (req.body.password === user.password)" will not work because one is hashed and the other is not.
I have been searching for answers for hours and can't seem to find that connection on how I use that "UserSchema.methods.comparePassword" method in my post request to log in. This isn't completely a real log in, just trying to get the password to validate and send back a key once logged in. Here are the docs: https://www.mongodb.com/blog/post/password-authentication-with-mongoose-part-1
// This is my UserModel
let mongoose = require('mongoose'),
Schema = mongoose.Schema,
bcrypt = require('bcrypt'),
SALT_WORK_FACTOR = 10
var hat = require('hat');
let UserSchema = new Schema({
email: {
type: String,
required: true,
index: {
unique: true
}
},
password: {
type: String,
require: true
},
api_key: {
type: String
}
});
UserSchema.pre('save', function(next) {
var user = this;
// only hash the password if it has been modified (or is new)
if (!user.isModified('password')) return next();
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
// hash the password using our new salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
// override the cleartext password with the hashed one
user.password = hash;
user.api_key = hat();
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);
// This is the sessions.js
let UserModel = require('../../../models/user.model');
var express = require('express');
var router = express.Router();
router.post('/', (req, res, next) => {
UserModel.findOne(
{
$or: [
{ email : req.body.email }
]
}
)
.then(user => {
if (req.body.password === user.password) {
res.setHeader("Content-Type", "application/json");
res.status(200).send(JSON.stringify({
"api_key": `${user.api_key}`
}));
} else {
res.status(404).send("Incorrect email or password")
}
})
.catch(error => {
res.setHeader("Content-Type", "application/json");
res.status(500).send({error})
})
})
module.exports = router
If I just find user by email, everything works fine. Just need to figure out how to use the compare password method in the user model. Thanks!
Maybe have something like this in your model:
User = require('./user-model');
.......
User.findOne({ username: 'jmar777' }, function(err, user) {
if (err) throw err;
user.comparePassword('Password123', function(err, isMatch) {
if (err) throw err;
console.log('Password123:', isMatch); // -> Password123: true
});
........
Other resources:
http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt
https://www.abeautifulsite.net/hashing-passwords-with-nodejs-and-bcrypt
https://medium.com/#mridu.sh92/a-quick-guide-for-authentication-using-bcrypt-on-express-nodejs-1d8791bb418f
Hope it helps!

Mongoose - pushing refs - cannot read property "push" of undefined

I would like to add a category and then if successed, push it's ref to user' collection. That's how I'm doing this:
That's mine "dashboard.js" file which contains categories schema.
var users = require('./users');
var category = mongoose.model('categories', new mongoose.Schema({
_id: String,
name: String,
ownerId: { type: String, ref: 'users' }
}));
router.post('/settings/addCategory', function(req, res, next) {
console.log(req.body);
var category_toAdd = new category();
category_toAdd._id = mongoose.Types.ObjectId();
category_toAdd.name = req.body.categoryName;
category_toAdd.ownerId = req.body.ownerId;
category.findOne({
name: req.body.categoryName,
ownerId: req.body.ownerId
}, function(error, result) {
if(error) console.log(error);
else {
if(result === null) {
category_toAdd.save(function(error) {
if(error) console.log(error);
else {
console.log("Added category: " + category_toAdd);
<<<<<<<<<<<<<<<<<<<THE CONSOLE LOG WORKS GOOD
users.categories.push(category_toAdd);
}
});
}
}
});
Here is my "users.js" file which contains "users" schema.
var categories = require('./dashboard');
var user = mongoose.model('users', new mongoose.Schema({
_id: String,
login: String,
password: String,
email: String,
categories: [{ type: String, ref: 'categories' }]
}));
So, the category add proccess works well and I can find the category in database. The problem is when I'm trying to push the category to user.
This line:
users.categories.push(category_toAdd);
I get this error:
Cannot read property "push" of undefined.
I need to admit once more that before that pushing there is console.log where the category is printed properly.
Thanks for your time.
The users object is a Mongoose model and not an instance of it. You need the correct instance of the users model to add the category to.
dashboard.js
...
category_toAdd = {
_id: mongoose.Types.ObjectId(),
name: req.body.categoryName,
ownerId: req.body.ownerId
};
// Create the category here. `category` is the saved category.
category.create(category_toAdd, function (err, category) {
if (err) console.log(err);
// Find the `user` that owns the category.
users.findOne(category.ownerId, function (err, user) {
if (err) console.log(err);
// Add the category to the user's `categories` array.
user.categories.push(category);
});
});

Rollback Transaction for Multiple Models in Waterline ODM in Sails (For Mongo DB )

I am using Sails and Waterline ORM with Mongo Database .
I have two models User and Profile with One to One relationship.
Below is the code I've written for Transaction with Rollback logic. I think there can be a much better logic than this as the current logic is very clumsy.
Questions :
Does Waterline or Sails provide any functionality for Rollback purpose?
Is there any better way of doing this ?
User.create(newUser).then(function (data) {
var newProfile = {
displayName: data.name,
email: data.email,
user: data._id
}
return Profile.create(newProfile);
}).then(function (profileData) {
sails.log.info("Profile Data " + JSON.stringify(profileData));
// Update the user with Profile Info
User.update(newUser._id, {profile: profileData._id}).then(function (updatedUser) {
return updatedUser;
}, function (err) {
// TODO Rollback logic if the User Updation Fails
})
}, function (err) {
sails.log.error("Failed to Create Profile for the User . Deleting the created User");
var criteria = {
email: data.email
}
User.destroy(criteria).then(function (user) {
sails.log.error("Deleted the Created User " + JSON.stringify(user));
throw new Error("ERROR CREATING User");
}, function (err) {
sails.log.error("ERROR DELETING USER");
throw new Error("ERROR DELETING USER", err);
})
});
To question 1 : no.
I would be tempted to do something like this:
async.waterfall([
function(callback){
User.create(newUser).then(function(data){
callback(null, data);
})
.catch(function(err){
callback(err, null, null); // don't need to rollback anything
})
},
function(data, callback){
Profile.create({
displayName: data.name,
email: data.email,
user: data._id
})
.then(function(profile){
callback(null, data, profile)
})
.create(function(err){
callback(err, data._id, null); // only need user's id
})
},
function(userData, profileData, callback){
User.update(userData._id, {profile: profileData._id})
.then(function(updatedUser){
callback(null, updatedUser);
})
.catch(function(err){
callback(err, userData._id, profileData._id); // can roll back both
})
}
], function(err, userData, profileData){
if(err) {
sails.log.error(err);
// do rollback, userData is user's ID, profileData is profile id
// if either one is undefined, then it doesn't exist
} else {
// userData is user object from the last update, return it!
}
})
I don't know if it is better, but it seems more readable, and it handles the errors for any of the three writing phases.

Can't get data from mongodb

I am trying to access a document and get the results to console. Mongoose debug shows that there is a document, yet returns an empty record.
//mongoose connect to db
var db = mongoose.createConnection('mongodb://localhost/mean-dev1/', function(err) {
if (err) throw err;
});
db.once('open', function callback() {
var tripSchema = mongoose.Schema(
{ title: String,
fromDate: Date,
tillDate: Date,
price: Number,
details: String,
availability: Number
});
// Model definition
var TripObj = db.model('TripObj', tripSchema, 'tripmodel');
TripObj.find(function(err, data) {
if (!err){
console.log('%s', data); //gets undefined
console.log("written...", data);
}else{
throw err;
process.exit();
}
});
}
and here is the console output
...
Migrations: Up to date at version 003
Mongoose: tripmodel.find({}) { fields: { title: 1 } }
is undefined?
written... []
Figured it out, the problem was with my initial connection. So changed the code a bit.
//connects to mongoose datasource and populates the data.json file in app
mongoose.disconnect();
mongoose.connect('mongodb://localhost/tripDB/', function(err) {
if (err) throw err;
}),
Schema = mongoose.Schema
var db = mongoose.connection;
db.once('open', function callback() {
var tripSchema = mongoose.Schema(
{
availability: Number,
details: String,
fromDate: Date,
price: Number,
tillDate: Date,
title: {type:String, ref:'TripObj'}
});
// Model definition
var TripObj = mongoose.model('TripObj', tripSchema, 'trips');
TripObj.find(function(err, data) {
if (!err){
var newdata = data;
//console.log('%s is undefined?', newdata);
fs.writeFileSync(path.join(__dirname, '../../../../' + 'content/themes/traveller/assets/js' + '/data.json'), JSON.stringify(newdata));
console.log("written succesfully", data);
process.exit();
}else{
throw err;
}
});
});

How to set up mongo db in local and then in remote?

I have got the mongo db commands from the below link.
http://try.mongodb.org/
I have a project and I am able to run it. In the project we use mongodb, angular js, node js and express server.
I am able to create user from the login page.The users are stored in mongo db. I would like to know what are the users in the database.
Initially I did not install any mongodb. But some how, the user and password was stored in localhost. I hope my project will be having certain libraries.
But later, in order to learn mongo, i installed mongo to my PC. I started the mongo db and it is running successfully in the link
http://localhost:28017/.
MongoDB starting : pid=6300 port=27017 dbpath=\data\db\ 64-bit host=new-PC
Question 1
I would like to list out the users in the db, that is used by my project. Will installation of mongo db help me in some way? If not without starting mongo db, can i know where are the user details saved by my project?
Question 2
How can I set up mongo db in remote so that it is available in the internet?
Code
- Creating UserSchema
var UserSchema = new Schema({ name: String, email: { type: String, unique: true }, hashed_password: String, provider: String, salt: String, facebook: {}, twitter: {}, github: {}, google: {} });
mongoose.model('User', UserSchema);
- Code for creating user
var mongoose = require('mongoose'), User = mongoose.model('User'), q = require('q'), _ = require('lodash');
exports.create = function(req, res, next) { var reqUser = new User(req.body); var email = reqUser.email; if(!reqUser.email) { res.send(400, {message: 'Email is mandatory!'}); }
var message = null;
reqUser.provider = 'local';
var savePromise = q.when(User.findOne({'email': reqUser.email}).exec());
savePromise.then(function(user) {
return reqUser;
if(user == null)
{
return reqUser;
} else
{
if(reqUser.provider!=user.provider && !user.hashed_password)
{
user.password = reqUser.password;
} else {
throw new Error("User alredy exists!");
}
console.log("In Else");
console.log(user);
return user;
}
}, function(err){
console.log("In Error 1");
}
).then(function(user){
console.log("In then 2");
console.log(user);
return user.save();
}, function(err){
console.log("In error 2");
console.log(err);
}).then(function(obj){
console.log("In then 3");
console.log(obj);
}).fail(function(error){
console.log("In Fail");
console.log(error);
}).done(function(){
// console.log(user);
console.log("in done");
});
console.log("Returning 400 at the end");
user.save(function(err) {
if (err) {
console.log(err);
message = 'Unknowd error occured, please try again!';
if(err.code=11000)
{
message = 'User with this email already exist. Existing user? please login here';
User.findOne({
email: user.email
}, function(err, dbuser) {
if (err) {
return res.json(400, { message: message });
}else {
if(dbuser.provider!=user.provider)
{
console.log("In If");
console.log(dbuser);
if(!dbuser.hashed_password)
{
console.log("In another if");
dbuser.password = user.password;
dbuser.save(function(err){
if(err)
{
console.log(err);
}
return res.json(dbuser);
});
}else
{
console.log("Returning error");
return res.json(400, { message: message })
}
} else
{
return res.json(400, { message: message });
}
}
});
}
}else
{
return res.json(user);
}
//console.log("Returning success");
});
};
Thanks,
Sabarisri
To answer question #2 first,
you will need either an instance of mongoDB on your own server or get a hosted one.
See for example Database-as-a-service. There are quite a lot of possibilites, check out some other offers.
Your first question is confusing me. It would be helpful to see the code that creates a user.
Installation:
http://docs.mongodb.org/manual/tutorial/install-mongodb-on-windows/
Coding :
http://docs.mongohq.com/languages/nodejs.html
How to secure MongoDB with username and password