Password to be hashed during PATCH request - express

During patch request, along with other changes (e.g. "name" and "email" if required) password changed and then to be hashed.
I have the following code so far patch route:
router.patch("/edit/:_id", (req, res, next) => {
User.findOneAndUpdate({_id : req.params._id},
{$set:
{
email: req.body.email,
name: req.body.name,
password: req.body.password
},
},
{
new : true,
upsert: true,
omitUndefined: true
}
)
.then(user => res.json(user))
.catch(err => console.log(err));
});
Model/Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
var ObjectId = mongoose.Schema.Types.ObjectId;
// Create Schema
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("users", UserSchema);
I want to use "bcryptjs" to hash user's password. Please en-light me. Thanks in advance.

All I did in order to solve, add findOneandUpdate pre hooks on schema.
Here is code:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
var ObjectId = mongoose.Schema.Types.ObjectId;
const bcrypt = require("bcryptjs");
// Create Schema
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
UserSchema.pre('findOneAndUpdate', async function (next) {
await this.updateOne({},{ $set: { password: bcrypt.hashSync(this.getUpdate().$set.password, 10) }})
});
module.exports = User = mongoose.model("users", UserSchema);

Related

updateMany mongoose using stored values

Hello Guys I have a product model I want to create a route that it updates all the list of products by updating quantity to (quantity=quantity-quantity_added)
and quantity_added to 0
//mongoose
const mongoose = require("mongoose");
//schema
const schema = mongoose.Schema;
//product schema
const productSchema = new schema(
{
name: { type: String, require: true },
description: { type: String, require: false },
image_url: { type: String, require: true },
price: { type: Number, require: true },
quantity: { type: Number, require: true },
rating: { type: Number, require: true },
quantity_added: { type: Number, require: true,dafualt:0 }
},
{
timestamps: true,
}
);
//export
module.exports = Product = mongoose.model("product", productSchema);
Hope you got the idea guys and you can help !

user.setPassword is not a function

I'm trying to change the user's password with the setPassword() passport local mongoose instance method, but I'm getting an error that says "user.setPassword is not a function".
This is my code
const change_password = (req, res) => {
const password = req.body.password
console.log(password);
User.find({
_id: req.user._id
}).then((user) => {
user.setPassword(password, function() {
console.log('user password changed')
user.save()
res.status(200).json( { msg : 'The password has been changed' })
})
}).catch(e => {
console.log(e);
})
}
And this is my user Schema
const mongoose = require('mongoose');
const passportLocalMongoose = require('passport-local-mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
// required: true
},
googleId: {
type: String,
},
photoUrl: {
type: String,
},
githubId: {
type: String,
},
twitterId: {
type: String,
},
facebookId: {
type: String,
},
bio: {
type: String,
},
email: {
type: String,
},
phoneNumber: {
type: String,
},
})
UserSchema.plugin(passportLocalMongoose, { usernameField: 'email' });
const User = mongoose.model('User', UserSchema);
module.exports = User;
User.find() will return an array of users matching the query, hence the error.
Because there should be (at most) one user in the database matching req.user._id, use findOne instead. Also note that findOne() can return null in case there were no users matching the query:
User.findOne({ _id: req.user._id }).then(user => {
if (! user) return res.sendStatus(404);
user.setPassword(…);
});

How should i connect Schema models in Mongoose?

i want to make a User, Post and comment. connect them together and when i create a Post, it should be connected to one of my users. I don't know why i get an unusual error. Error:
ID cannot represent value: <Buffer 5e 9b f1 3e e9 49 61 38 fc 1a 6f 59>
these are all of my code so if you know whats my problem please help me fix it. Thanks
typeDefs:
import { gql } from 'apollo-server-express';
export const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
age: Int
posts: [Post!]!
comments: [Comment!]!
}
type Post {
id: ID!
title: String!
body: String!
published: Boolean!
author: User!
comments: [Comment!]!
}
type Comment {
id: ID!
text: String!
author: User!
post: Post!
}
`
UserSchema:
import mongoose, { mongo } from 'mongoose';
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
age: {
type: Number,
required: false
},
posts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}
],
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
});
module.exports = mongoose.model('User',userSchema);
PostSchema:
import mongoose from 'mongoose';
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
body: {
type: String,
required: true
},
published: {
type: Boolean,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
});
module.exports = mongoose.model('Post',postSchema);
CommentSchema:
import mongoose from 'mongoose';
const commentSchema = new mongoose.Schema({
text: {
type: String,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
post: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}
});
module.exports = mongoose.model('Comment',commentSchema);
Resolver:
import Users from './models/User';
import Posts from './models/Post';
import Comments from './models/Comment';
export const resolvers = {
Mutation: {
createUser: async (parent, args, context, info) => {
const user = new Users(args);
await user.save();
return user;
},
createPost: async (parent, { title, body, published, author }, context, info) => {
const user = await Users.findById(author);
if (!user) {
console.log("User not found")
}
console.log(user)
const post = new Posts({ title, body, published, author: user.id });
await post.save();
user.posts.push(post);
await user.save();
return post;
}
}
}
I have found the solution and you should use type: mongoose.Schema.Types.ObjectId and ref: 'Comment' and after that inside resolvers you should use population .

Mocha Testing a Nested Model

Trying to write a test for a nested model but can't get it working:
Model:
const EmployeeSchema = new mongoose.Schema({
firstName: {type: String, required: true},
lastName: { type: String, required: true}
});
const CompanySchema = new mongoose.Schema({
name: { type: String, required: true },
streetAddress: { type: String, required: true },
country: { type: String, required: true },
employees:[EmployeeSchema]
}, { timestamps: true});
Controller:
function create(req, res, next) {
const company = new Company({
name: req.body.name,
streetAddress: req.body.streetAddress,
country: req.body.country
});
company.employees.push(req.employees);
company.save()
.then(savedCompany => res.json(savedCompany))
.catch(e => next(e));
}
Test:
describe('## Company APIs', () => {
let company = {
name: "Test Company",
streetAddress: "123 Fake Street",
country: "A Country"
};
company.employees.push({firstName: "Jane", lastName: "Doe"});
describe('# POST /api/company', () => {
it('should create a new company', (done) => {
request(app)
.post('/api/company')
.send(company)
.expect(httpStatus.OK)
.then((res) => {
expect(res.body.name).to.equal(company.name);
expect(res.body.streetAddress).to.equal(company.streetAddress);
expect(res.body.country).to.equal(company.country);
company = res.body;
done();
})
.catch(done);
});
});
The above gives: TypeError: Cannot read property 'push' of undefined
I've tried a few other things but this is the most promising result, for some reason I just can't seem to populate the embedded model as part of setting up the unit test.
I ended up resolving this, hopefully this helps someone in the future.
Test:
it('should associate an employee with the company', (done) => {
var employee = new Employee();
company.employees.push(employee);
request(app)
.put(`/api/company/${company._id}`)
.send(company)
.expect(httpStatus.OK)
.then((res) => {
expect(res.body.employees).to.be.an('array')
expect(res.body.employees).to.contain(employee.id)
done();
})
.catch(done);
});
Controller:
Adding this to handle multiple additions:
if (req.body.employees != null) {
req.body.employees.forEach(function(employee) {
company.employees.push(employee);
}, this);
}

Sequelize Association Error Not Associated

I am trying to associate my User model with my Organization model, but I'm running into an error that says, Error: user is not associated to organization! despite the fact that I am following the process to associate the User to my Organization. Is it possible that the type of association method that I am using is causing the problem?
User Model (user.js):
var bcrypt = require('bcrypt-nodejs');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('user', {
user_id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'first_name'
},
lastName: {
type: DataTypes.STRING,
field: 'last_name'
},
email: {
type: DataTypes.STRING,
isEmail: true,
unique: true
},
password: DataTypes.STRING,
organizationId: {
type: DataTypes.INTEGER,
field: 'organization_id',
allowNull: true
}
}, {
freezeTableName: true,
classMethods: {
generateHash: function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
},
associate: function(db) {
User.belongsTo(db.Organization, {foreignKey: 'organizationId'});
},
},
instanceMethods: {
validPassword: function(password) {
return bcrypt.compareSync(password, this.password);
},
},
});
return User;
}
Organization model (organization.js):
module.exports = function(sequelize, DataTypes) {
var Organization = sequelize.define('organization', {
organizationId: {
type: DataTypes.INTEGER,
field: 'organization_id',
autoIncrement: true,
primaryKey: true
},
organizationName: {
type: DataTypes.STRING,
field: 'organization_name'
},
admin: DataTypes.STRING,
members: DataTypes.STRING
},{
freezeTableName: true
});
return Organization;
}
index for tables to connect (db-index.js):
var Sequelize = require('sequelize');
var path = require('path');
var config = require(path.resolve(__dirname, '..', '..','./config/config.js'));
var sequelize = new Sequelize(config.database, config.username, config.password, {
host:'localhost',
port:'3306',
dialect: 'mysql'
});
sequelize.authenticate().then(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
});
var db = {}
db.Organization = sequelize.import(__dirname + "/organization");
db.User = sequelize.import(__dirname + "/user");
db.Records = sequelize.import(__dirname + "/records");
db.User.associate(db);
db.Records.associate(db);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
sequelize.sync();
module.exports = db;
Are of a route call that triggers this error:
appRoutes.route('/sign-up/organization')
.get(function(req, res){
models.User.find({
where: {
user_id: req.user.email
}, attributes: [ 'user_id', 'email'
]
}).then(function(user){
res.render('pages/sign-up-organization.hbs',{
user: req.user
});
})
})
.post(function(req, res, user){
models.Organization.create({
organizationName: req.body.organizationName,
admin: req.body.admin,
user: {
organizationId: req.body.organizationId
}
}, { include: [models.User] }).then(function(){
console.log(user.user_id);
res.redirect('/app');
}).catch(function(error){
res.send(error);
console.log('Error at Post');
})
});
You need to set up the reverse of the association, Organization hasMany Users