I'd need some help on returning values after saving a new entry to my db using mongoose.
This is how my controller looks:
var userModel = require('../models/users');
module.exports = {
findAll: function(req, res) {
userModel.user.findAll(function(err, users) {
return res.json(users);
});
},
findId: function(req, res) {
var id;
id = req.params.id;
userModel.user.findId(id, function(err, user) {
return res.json(user);
});
},
addUser: function(req, res) {
newUser = new userModel.user;
newUser.username = req.body.username;
newUser.password = req.body.password;
newUser.addUser(function(err, user) {
return res.json(user);
});
}
};
And here's my users.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
module.exports = {
findAll: UserSchema.statics.findAll = function(cb) {
return this.find(cb);
},
findId: UserSchema.statics.findId = function(id, cb) {
return this.find({
_id: id
}, cb);
},
addUser: UserSchema.methods.addUser = function(cb) {
return this.save(cb);
}
};
This all works ok, but it only returns me the newly added user with addUser. I would like to get all the entries, including the newsly added one, as a return value. Just like using "findAll". How would be able to do this?
Yes, like bernhardw said there doesn't seem to be a way to return anything but the added document with save().
I followed his advice and called findAll() inside addUser() and it all works perfect now -> I can return all my users after saving a new new one. Thanks.
Related
I am taking password input from the user and encrypting the password using crypto, then saving into the database. This is my code, here I am storing the encrypted password into the encry_password property that comes from the userSchema. But, this is giving me error that "this.securePassword" is not a function.
const mongoose = require("mongoose");
const crypto = require("crypto");
const { v1: uuidv1 } = require("uuid");
const 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,
},
usrinfo: {
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((password) => {
this._password = password;
this.salt = uuidv1();
this.encry_password = securePassword(password, uuidv1());
console.log(this.encry_password);
})
.get(() => {
return this._password;
});
// const authenticate = function (plainPassword, encry_password) {
// return securePassword(plainPassword) === encry_password;
// };
const securePassword = function (plainPassword, salt) {
if (!plainPassword) return "";
try {
return crypto.createHmac("sha256", salt).update(plainPassword).digest("hex");
} catch (error) {
return "";
}
};
module.exports = mongoose.model("User", userSchema);
Route for user signup
exports.signup = (req, res) => {
console.log(req.body);
const user = new User(req.body);
user.save((err, user) => {
if (err) {
console.log(err);
res.status(400).json({
err: "Note able to save the user in database"
});
} else {
res.json(user);
}
});
};
first of all, in this situation you shouldn't use virtual
Virtuals
Virtuals are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage.
but in the scope of virtual, this cannot access to method, you can not access to the method like your manner, it's a example of method usage in mongoose
const Animal = mongoose.model('Animal', animalSchema);
const dog = new Animal({ type: 'dog' });
dog.findSimilarTypes((err, dogs) => {
console.log(dogs); // woof
});
you can check the method documantation:
if you want just access to securePassword in your manner you can like this and delete method mongoose complately because this is not the place to use method:
UserSchema.virtual("password")
.set((password) => {
this._password = password;
this.salt = uuidv1();
console.log("This is running");
this.encry_password = securePassword(password, this.salt);
console.log(encry_password);
})
.get(() => {
return this._password;
});
const authenticate = function (plainPassword, encry_password) {
return securePassword(plainPassword) === encry_password;
};
const securePassword = function (plainPassword, salt) {
if (!plainPassword) return "";
try {
return crypto
.createHmac("sha256", salt)
.update(plainPassword)
.digest("hex");
} catch (error) {
return "";
}
};
if you want to create authenticate service, change your manner, and don't use virtual for password and use pre save
before saving information about users in db this tasks will be done
check the pre documentation
userSchema.pre("save", async function (next) {
try {
this.password = securePassword (plainPassword, salt);
} catch (error) {
console.log(error);
}
});
after created a hash password save informations like this :
const userSchema = new mongoose.Schema({
.
.
.
password: { //convert encry_password to password
type: String,
}
.
.
.
}, { timestamps: true });
//every time want to user save this method called
userSchema.pre('save', function (next) {
this.salt = uuidv1()
this.password = securePassword(this.password, this.salt)
next()
})
//for have a clean routes, you can create a static methods
userSchema.statics.Create = async (data) => {
let model = new User(data);
let resUser = await model.save(); //save your user
return resUser;
};
const securePassword = function (plainPassword, salt) {
if (!plainPassword) return "";
try {
return crypto.createHmac("sha256", salt).update(plainPassword).digest("hex");
} catch (error) {
return "";
}
};
let User = mongoose.model("User", userSchema)
module.exports = {User};
change controller like this :
let {User} = require("./path of user schema")
exports.signup = async (req, res) => {
try {
console.log(req.body);
const user = await User.create(req.body); //create a user
res.json(user);
} catch (error) {
console.log(err);
res.status(400).json({
err: "Note able to save the user in database",
});
}
};
NOTE : in req.body, name of password field, should be password
It looks like the scope of the securePassword function is defined inside userSchema, and you're trying to call it in userSchema.virtual.
Not able to save the data in Google Datastore DB not getting any error, can somebody help me to find the fix
Console.log result as below
entityKey: Key { namespace: undefined, kind: 'User', path: [Getter] },
entityData:
{ firstname: 'Abcd',
lastname: 'Abcd',
email: 'abcd#gmail.com',
password: '123454',
createdOn: 'Abcd',
[Symbol(KEY)]: Key { namespace: undefined, kind: 'User', path: [Getter] } },
Ref - https://www.npmjs.com/package/gstore-node
const express = require('express');
const router = express.Router();
const { check, validationResult } = require('express-validator');
var User =require('../models/user');
//get register page
router.get('/register',function(req,res){
res.render('register')
});
//get login page
router.get('/login',function(req,res){
res.render('login')
});
router.post('/register', [
check('Name').isEmpty().withMessage('The Name is required'),
check('Email').isEmail().withMessage('Email is requried'),
//check('Password').isEmpty().withMessage('pass is requried'),
//check('Password','Password is Requried').isEmpty(),
// check('Password2','Password Not Match').equals('password2'),
], (req, res,next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.render('register',{
error:errors.mapped()
})
}else{
console.log()
const newUser = new User ({
firstname:req.body.name,
lastname:req.body.name,
email :req.body.Email,
password :req.body.Password,
createdOn:req.body.name
});
console.log("Data1",newUser)
const createUser = (req, res) => {
const entityData = User.sanitize(req.body);
const user = new User(entityData);
console.log("Data2",createUser)
user.save()
.then((entity) => {
res.json(entity.plain());
})
.catch((err) => {
// If there are any validation error on the schema
// they will be in this error object
res.status(400).json(err);
})
};
req.flash('success_msg','you are registered and can login now');
res.redirect('/users/login');
}
});
module.exports=router;
const { Gstore, instances } = require('gstore-node');
const { Datastore } = require('#google-cloud/datastore');
const gstore = new Gstore();
const datastore = new Datastore({
projectId: 'sinuous250616',
});
gstore.connect(datastore);
// Save the gstore instance
instances.set('unique-id', gstore);
const bcrypt = require('bcrypt');
// Retrieve the gstore instance
const ggstore = instances.get('unique-id');
const { Schema } = ggstore;
/**
* A custom validation function for an embedded entity
*/
const validateAccessList = (value, validator) => {
if (!Array.isArray(value)) {
return false;
}
return value.some((item) => {
const isValidIp = !validator.isEmpty(item.ip) && validator.isIP(item.ip, 4);
const isValidHostname = !validator.isEmpty(item.hostname);
return isValidHostname && isValidIp;
});
}
//Create the schema for the User Model
const userSchema = new Schema({
firstname: { type: String, required: true },
lastname: { type: String, optional: true },
email: { type: String, validate: 'isEmail', required: true },
password: { type: String, read: false, required: true },
createdOn: { type: String, default: gstore.defaultValues.NOW, write: false, read: false }
});
/**
* List entities query shortcut
*/
const listSettings = {
limit: 15,
order: { property: 'lastname' }
};
userSchema.queries('list', listSettings);
/**
* Pre "save" middleware
* Each time the entity is saved or updated, if there is a password passed, it will be hashed
*/
function hashPassword() {
// scope *this* is the entity instance
const _this = this;
const password = this.password;
if (!password) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
bcrypt.genSalt(5, function onSalt(err, salt) {
if (err) {
return reject(err);
};
bcrypt.hash(password, salt, null, function onHash(err, hash) {
if (err) {
// reject will *not* save the entity
return reject(err);
};
_this.password = hash;
// resolve to go to next middleware or save method
return resolve();
});
});
});
// add the "pre" middleware to the save method
userSchema.pre('save', hashPassword);
/**
* Export the User Model
* It will generate "User" entity kind in the Datastore
*/
module.exports = gstore.model('User', userSchema);
*I think there is a problem with User model **
You should have a User model like this in /models/user.js (put models at the root of your application) to define User:
const { instances } = require('gstore-node');
const bscrypt = require('bcrypt-nodejs');
// Retrieve the gstore instance
const gstore = instances.get('unique-id');
const { Schema } = gstore;
var usersSchema = new Schema({
firstname:{type:String},
lastname:{type:String},
email:{type:String},
password :{type:String},
createdOn: Date
})
var User = gstore.model('User', usersSchema);
module.exports = User;
And you forgot to use to save with save()
var newUser = new User ({
firstname:req.body.name,
lastname:req.body.name,
email :req.body.Email,
password :req.body.Password,
createdOn: new Date() // there is a problem here.... use new Date()
});
newUser.save(); //<======= it is abscent so it won't save
Trying to wrap my head around the following issue for couple days now.
I have a web app, that takes login, afterwards, the user can create a list of students. I am trying to make the list being visible to the user who posted it ONLY.
Below is my work so far.
students.controller.js
const express = require('express');
var router = express.Router();
var bodyParser = require('body-parser')
const mongoose = require('mongoose');
const passport = require('passport');
const Student = require('../models/student');
const passportConfig = require('../config/passport');
const app = express();
router.get('/',passportConfig.isAuthenticated,(req, res) => {
res.render('students');
});
router.post('/',(req, res) => {
InsertRecord(req, res);
});
function InsertRecord(req, res){
var student = new Student();
student.fullName = req.body.fullname;
student.phone = req.body.phone;
student.save((err, doc) => {
if (!err)
res.redirect('students/list');
else {
console.log(' Error during insertion: '+ err);
}
});
}
router.get('/list',passportConfig.isAuthenticated, (req, res) => {
Student.find((err, docs) => {
if (!err) {
res.render('list', {
list:docs
});
}
else {
console.log('Error in retrieving students: '+ err);
}
});
});
module.exports = router;
Model Schema Student.js
const mongoose = require('mongoose');
var ObjectId = mongoose.Schema.Types.ObjectId;
const studentSchema = new mongoose.Schema({
fullName: {
type: String
},
phone: {
type: Number
},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
}
});
const Student = mongoose.model('Student', studentSchema);
module.exports = Student;
User.js Schema
const bcrypt = require('bcrypt');
const crypto = require('crypto');
const mongoose = require('mongoose');
const Student = require('../models/student');
const userSchema = new mongoose.Schema({
email: { type: String, unique: true },
password: String,
passwordResetToken: String,
passwordResetExpires: Date,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
},
snapchat: String,
facebook: String,
twitter: String,
google: String,
github: String,
instagram: String,
linkedin: String,
steam: String,
tokens: Array,
profile: {
name: String,
gender: String,
location: String,
website: String,
picture: String
}
}, { timestamps: true });
/**
* Password hash middleware.
*/
userSchema.pre('save', function save(next) {
const user = this;
if (!user.isModified('password')) { return next(); }
bcrypt.genSalt(10, (err, salt) => {
if (err) { return next(err); }
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) { return next(err); }
user.password = hash;
next();
});
});
});
/**
* Helper method for validating user's password.
*/
userSchema.methods.comparePassword = function comparePassword(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
cb(err, isMatch);
});
};
/**
* Helper method for getting user's gravatar.
*/
userSchema.methods.gravatar = function gravatar(size) {
if (!size) {
size = 200;
}
if (!this.email) {
return `https://gravatar.com/avatar/?s=${size}&d=retro`;
}
const md5 = crypto.createHash('md5').update(this.email).digest('hex');
return `https://gravatar.com/avatar/${md5}?s=${size}&d=retro`;
};
const User = mongoose.model('User', userSchema);
module.exports = User;
Please let me know if anything else is needed.
How about using JWT?
JWT is token-based Authorization way. You can store user's email or _id in jwt.
When user logged in, the server provide jwt that store user's email. When user requested the list with jwt, you can find the student with user's _id in jwt like student.findById({author: token.id}).
You don't have to make jwt module but you can use jsonwebtoken that already provided.
I have schema created now i want to save new document to collection but its not happening with below code, I am new to mongodb any help will be appreciated.
routes.js
var Diagram = require('./diagram');
router.post('/saveNewDiagram',function(req,res){
Diagram.save(req.body);
});
diagram.js
var diagram = require('./diagram.model');
var mongoose = require('mongoose');
var Diagram = {
update: function(req, res) {
diagram.update({
_id: req._id
}, {
$set: {
'string': req.string
}
}, function(err, result) {
if (err) {
return res.status(500).send(err);
} else {
console.log("successfully updated document");
}
});
},
save: function(req, res) {
var newDiagram = new diagram();
newDiagram.save(req.body);
}
}
module.exports = Diagram;
model.js
var DiagramSchema = new mongoose.Schema({
text: String,
owner: {type: String, ref:'User'},
groups: [{type: String, ref: 'Group'}],
users: [{type: String, ref: 'User'}],
string: String
});
module.exports=mongoose.model('Diagram', DiagramSchema);
You did wrong in save function, you save function should be like
save: function(req, res) {
var newDiagram = new diagram(req.body);
newDiagram.save();
}
and make sure req.body only have string and/or text fields. You may like to add following check
save: function(req, res) {
var diagramData = {
string: req.body.string,
text: req.body.text
}
var newDiagram = new diagram(diagramData);
newDiagram.save();
}
While studying node I am trying to create a little commentthread application. Since the book I am using is a little outdated, I had to adjust the model provided in the book to get the application running. However, I think something is still wrong with my model, because a part of the data is stored as object Object. Does anyone see the problem in the model?
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var ReplySchema = new Schema();
ReplySchema.add({
username: String,
subject: String,
timestamp: { type: Date, default: Date.now },
body: String,
replies:[ReplySchema]
}, { _id: true });
var CommentThreadSchema = new Schema({
title: String,
replies:[ReplySchema]
});
mongoose.model('Reply', ReplySchema);
mongoose.model('CommentThread', CommentThreadSchema);
The result in Mongo:
{ _id: 56c8c91b011c7db2608159d6,
'[object Object]timestamp': Sat Feb 20 2016 21:14:19 GMT+0100 (CET), '[object Object]replies': [] }
The controller
var mongoose = require('mongoose'),
CommentThread = mongoose.model('CommentThread'),
Reply = mongoose.model('Reply');
exports.getComment = function(req, res) {
CommentThread.findOne({ _id: req.query.commentId })
.exec(function(err, comment) {
if (!comment){
res.json(404, {msg: 'CommentThread Not Found.'});
} else {
res.json(comment);
}
});
};
exports.addComment = function(req, res) {
CommentThread.findOne({ _id: req.body.rootCommentId })
.exec(function(err, commentThread) {
if (!commentThread){
res.json(404, {msg: 'CommentThread Not Found.'});
} else {
var newComment = Reply(req.body.newComment);
newComment.username = generateRandomUsername();
addComment(req, res, commentThread, commentThread,
req.body.parentCommentId, newComment);
}
});
};
function addComment(req, res, commentThread, currentComment,
parentId, newComment){
if (commentThread.id == parentId){
console.log(newComment);
commentThread.replies.push(newComment);
updateCommentThread(req, res, commentThread);
} else {
for(var i=0; i< currentComment.replies.length; i++){
var c = currentComment.replies[i];
if (c._id == parentId){
c.replies.push(newComment);
var replyThread = commentThread.replies.toObject();
updateCommentThread(req, res, commentThread);
break;
} else {
addComment(req, res, commentThread, c,
parentId, newComment);
}
}
}
};
function updateCommentThread(req, res, commentThread){
CommentThread.update({ _id: commentThread.id },
{$set:{replies:commentThread.replies}})
.exec(function(err, savedComment){
if (err){
res.json(404, {msg: 'Failed to update CommentThread.'});
} else {
res.json({msg: "success"});
}
});
}
function generateRandomUsername(){
//typically the username would come from an authenticated session
var users=['Mojos', 'Milo', 'Mihaal', 'Haly', 'MilodeBaesz', 'Mihaly'];
return users[Math.floor((Math.random()*5))];
}