sequelize return result from .then - node.js

I have the following code :
var ORM = require('../helpers/mysql_orm');
var log = require('../helpers/logger');
function UserModel() {
this.User = ORM.define('User', {
}, {
tableName: 'User',
timestamps: false,
});
}
UserModel.prototype.findOneByCredinitals = function (creditinals) {
this.User.findOne({
attributes:['username','id'],
where:
{
username:creditinals.principal,
password:creditinals.creditinal}
})
.then(function(user) {
console.log("inside then function"+user);
return user;
})
// console.log(result);
},
UserModel.prototype.findAllByLimit = function(req,res) {
}
module.exports= new UserModel;
//app.js
var result = User.findOneByCredinitals({principal: 'admin',creditinal:'danieladenew'});
console.log("returned "+result);
This the result from app.js
------------------------------------------------
returned undefined
inside then function User Sequelize Instance i.e Useriffound and displayed.
How do i return user object from then to app.js code please ?

You need to return the promise in order for the data to appear.
UserModel.prototype.findOneByCredential = function (credentials) {
return this.User.findOne({
attributes: ['username', 'id'],
where: {
username: credential.principal,
password: credential.credential
}
}).then(function(user) {
console.log("inside then function"+user);
return user;
}
});
},
Also, it might be a good idea to add a catch block. If the query fails, you will have no idea otherwise

Related

function returning before await function

im trying to write a function that updates shopping cart which given products info and give user the updated shopping cart, however when I call this function, database is updating but response is not.
Code
export const addToCart: Hapi.Lifecycle.Method = async (request, h, err) => {
const payload: ProductIdPayload = <ProductIdPayload>request.payload;
const userId: string = <string>request.auth.credentials._id;
try {
const [shoppingCart, product] = await Promise.all([
ShoppingCartModel.findOne({ userId: userId }),
ProductModel.findById(payload.productId),
]);
if (product) {
console.log(product);
if (shoppingCart) {
await shoppingCart.updateOne({
$push: { productIds: payload.productId },
$inc: { totalValue: product.price },
});
//above line updates database but below command returns non-updated shopping cart
return h.response({
shoppingCart: shoppingCart,
});
} else {
const newShoppingCart = new ShoppingCartModel({
userId: userId,
productIds: [payload.productId],
totalValue: product.price,
});
console.log(newShoppingCart)
await newShoppingCart.save();
return h.response({ shoppingCart: newShoppingCart });
}
} else {
const error = Boom.notFound("Product Not Found");
return error;
}
} catch (error) {
throw new Error();
}
};
Any idea why is this happening?
Try using:
const updatedShoppingCart = await shoppingCart.updateOne({
$push: { productIds: payload.productId },
$inc: { totalValue: product.price },
});
return h.response({
shoppingCart: updatedShoppingCart,
});
If the above solution doesn't work for you use findOneAndUpdate function on the Model and pass {new: true} in the options.

Mongoose Schema.method() is not working, and showing an error message

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.

Sequelize changed function not working - like Mongoose's isModified

In a hook I want to confirm whether a password has changed before executing encryption process.
Mongoose has a function "isModified" and I believe Sequelize's "changed" function servers the same purpose.
I cannot get the "changed" function to work. I am looking for an example of how it is used.
*******Snippet of code
{
hooks: {
beforeCreate: async (user) => {
if (changed([user.password]) === false) return next();
const salt = await bcrypt.genSalt(12);
user.password = await bcrypt.hash(user.password, salt);
user.passwordConfirmed = undefined;
},
},
instanceMethods: {
validPassword: function (password) {
return bcrypt.compare(password, this.password);
},
},
}
You must to use hook beforeUpdate with previous function. Try something like that:
let { Sequelize, DataTypes } = require('sequelize');
let sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'database.sqlite',
});
(async () => {
try {
await sequelize.authenticate();
console.log('connected');
let Person = sequelize.define('Person', { name: DataTypes.STRING, age: DataTypes.INTEGER });
Person.addHook('beforeUpdate', (person) => {
if (person.previous('name') != person.name) {
console.log('name changed', person.previous('name'), person.name);
}
});
await Person.sync({ force: true });
await Person.create({ name: 'John', age: 30 });
let [person] = await Person.findAll();
person.name = 'Paul';
await person.save();
} catch (error) {
console.error('Unable to connect to the database:', error);
}
})();

how to change username password using passport local mongoose

i'm trying to change the password of username using local mongoose
i tried to use setPassword function but it does not seem to work
router.put('/admin/users/:username', function(req,res){
User.findByUsername.then(function(sanitizedUser){
if (sanitizedUser){
sanitizedUser.setPassword(req.body.password, function(){
sanitizedUser.save();
res.redirect("back");
});
} else {
res.redirect("back");
}
},function(err){
console.error(err);
})
});
is there any other solution other than setpassword
what exactly i did wrong?
I have posted what I tend to do to reset password (part of it includes hashing it but the rest is the same). Except I am using async/await
const { password } = req.body;
let restP = new User();
try {
const newP = await restP.generateHash(password.password);
const resetP = await User.findByIdAndUpdate(
req.params.id,
{ $set: { passwordHash: newP } },
{
fields: { passwordHash: 0 },
new: true
}
)
// return image user object
res.send(resetP);
} catch (error) {
console.log(error);
return res.status(400).send(error);
}

adding functions to a knex/bookshelf model in node/express

I have a model like this:
const User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true
});
module.exports = User;
With this I can do things like
const User = require("../models/user");
User.fetchAll({columns:['id','email']}).then((data) => {
res.json(data);
}).catch(err => {
res.json(err);
});
What if I want to add costume functions to my model such as:
var connection = require('./dbconnection.js');
var User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true
});
User.getUsers = (callback) => {
if (connection) {
const newLocal = "select * FROM users";
connection.query(newLocal, (err,rows,fields) => {
if (err) {
return res.sendStatus(500);
} else {
callback(null,rows);
}
});
}
};
module.exports = User;
And then do something like:
const User = require("../models/user");
User.getUsers((err,data) => {
res.status(200).json(data);
});
Is this posible? Or should I just conform with the bookshelf functions?
Right now the error I get is connection.query is not a function
And models/dbconnection.js is:
const mysql = require('mysql');
port = process.env.PORT || 3333;
if (port == 3333) {
var connection = mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
insecureAuth: true
});
} else {
console.log("Error");
}
connection.connect();
module.exports.connection = connection;
Yes, you can add your custom functions to bookshelf models in two different ways.
Instance methods
For example, you want to return user's full name, your User model will look something like this
const User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true,
//be careful here, if you use arrow function `this` context will change
//and your function won't work as expected
returnFullName: function() {
return this.get('firstname') + this.get('lastname');
}
});
module.exports = User;
then you will call this function like this
User.forge().where({id: SOME_ID}).fetch()
.then(function(user) {
var fullName = user.returnFullName();
});
Class methods
For example, you want to return user's email based on username, your User model will look something like this
const User = db.Model.extend({
tableName: 'users',
hasSecurePassword: true
}, {
getUserEmail: function(SOME_USERNAME) {
return User.forge().where({username: SOME_USERNAME}).fetch()
.then(function (user) {
if(user) {
return Promise.resolve(user.get('email'));
} else {
return Promise.resolve(null);
}
});
}
});
module.exports = User;
then you can call this function like
User.getUserEmail(SOME_USERNAME)
.then(function(email) {
console.log(email);
});

Resources