Instance Methods is not working in Sequelize - node.js

I can't seem to set the User model properly. I've implemented some instance methods that don't seem to be working
var UserDetails = mysequelize.sequelize.define('user_tb', {
id: {
autoIncrement: true,
type: mysequelize.sequelize.Sequelize.INTEGER,
allowNull: false,
},
username: {
type: mysequelize.sequelize.Sequelize.STRING,
primaryKey: true,
unique: true,
},
hierarchyid: {
type: mysequelize.sequelize.Sequelize.STRING
},
password: {
type: mysequelize.sequelize.Sequelize.STRING,
validate: {
len: {
args: [6, 15],
msg: "Please enter a password with at least 6 chars but no more than 15"
}
},
allowNull: false
},
customerid: {
type: mysequelize.sequelize.Sequelize.INTEGER
},
statususer: {
type: mysequelize.sequelize.Sequelize.STRING,
allowNull: false
},
userid: {
unique: true,
type: mysequelize.sequelize.Sequelize.STRING,
allowNull: false
},
authtoken: {
unique: true,
type: mysequelize.sequelize.Sequelize.STRING,
allowNull: false
}
},
{
tableName: 'user_tb',
timestamps: false,
freezeTableName: true
});
UserDetails.prototype.toJSON = function(){
var user = this;
var userObject = user.toObject();
return _.pick(userObject,['userid','password']);
};
UserDetails.prototype.findByCredentials = function(userid, password)
{
console.log('Sunddep');
var User = this;
// return User.fin
User.findOne({userid}).then((user)=> {
if(!user)
{
return Promise.reject();
}
return new Promise((resolve,reject) => {
bcrypt.compare(password,user.password,(err,res) => {
if(res)
{
resolve(user);
}
else{
reject();
}
})
})
});
}
UserDetails.prototype.generateAuthToken = function()
{
var user = this;
var access = 'authtoken';
var token = jwt.sign({userid:
user.userid.toHexString(),access},process.env.JWT_SECRET).toString();
user.build({
access: token
});
user.save().then(() =>{
return token;
});
}
module.exports = {UserDetails}
server.js
app.post('/user/login', (req, res) => {
console.log(req.body);
var body = _.pick(req.body, ['userId', 'password']);
user.findByCredentials(body.userId, body.password).then(() => {
res.send('Sundeep');
},
(e) => {
sendData: ({
wsState: '0',
messageCode: 'WS000001',
message: 'No user find with this Id',
userData: []
});
res.status(400).send(sendData)
});
});
Hi, I am getting error while calling instance method from other class. Can any one tell me how can i achieve it
UserDetails.prototype.findByCredentials = function(userid, password) {.....}
But while run the server.js file i getting error like UserDetails.findByCredentials is not a function while calling from other class
Thanks for help in advance.

Related

Sequelize Associations in Node/express JS

I am new to sequelize SQL ORM nodejs. I am facing problem with associations.When I try to make a join query. It throws an association error. here is my code snippet.
server.js
app.get("/", (req, res) => {
db_conn.syncModels(req, res);
});
db_connection.js
require("dotenv").config();
const { Sequelize, DataTypes } = require("sequelize");
const crypto = require("crypto");
class DbConnection {
constructor() {
this.db = {};
this.sequelizeObj = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASS,
{
host: process.env.DB_URI,
dialect: "mysql",
logging: true,
}
);
this.userRoles = [
{
role_name: "SuperAdmin",
},
{
role_name: "Admin Assistant",
},
{
role_name: "HR Manager",
},
{
role_name: "Department Head",
},
{
role_name: "Assistant Manager",
},
{
role_name: "Employee",
},
];
this.defaultUser = {
user_name: "SuperAdmin",
user_email: "superadmin#" + process.env.BASE_URL,
user_password: crypto
.createHash("md5")
.update("SuperAdmin")
.digest("hex"),
role_id: 100000,
};
}
sequelize() {
return this.sequelizeObj;
}
connect() {
this.sequelizeObj
.authenticate()
.then(() => {
console.log("Connection has been established successfully.");
})
.catch((error) => {
if (error.message.includes("Unknown database")) {
this.createdb();
} else {
console.error("Unable to connect to the database: ", error);
}
});
}
async createdb() {
try {
const sequelize = new Sequelize(
"",
process.env.DB_USER,
process.env.DB_PASS,
{
host: process.env.DB_URI,
dialect: "mysql",
logging: true,
}
);
const createdb = await sequelize.query(
`CREATE DATABASE IF NOT EXISTS ${process.env.DB_NAME};`
);
console.log("Database Created")
} catch (err) {
console.log(err);
}
}
disconnect() {
this.sequelizeObj
.close()
.then(() => {
console.log("Connection has been closed successfully.");
})
.catch((error) => {
console.error("Unable to disconnect: ", error);
});
}
syncModels(payload, cb) {
this.db.Sequelize = Sequelize;
this.db.sequelize = this.sequelizeObj;
this.db.sequelize
.sync({ force: true })
.then((res) => {
console.log("Environment Configured");
})
.then(async () => {
await this.db.user_roles.bulkCreate(this.userRoles);
})
.then(() => {
console.log("User Roles Created");
})
.then(() => {
cb.status(200).send("Environment Configured");
})
.catch((err) => {
cb.status(400).send("Environment Configuration Error " + err);
});
// specifying models
this.db.users = require("../Auth/models/auth.model")(
this.sequelizeObj,
DataTypes
);
this.db.user_roles = require("../Auth/models/roles.model")(
this.sequelizeObj,
DataTypes
);
// Method 01
// Relation of user and user-roles
this.db.users.hasOne(this.db.user_roles, {
foreignKey: "role_id",
as: "role",
});
this.db.user_roles.belongsTo(this.db.users, {
foreignKey: "role_id",
as: "role",
});
}
random_password(length) {
var result = "";
var characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
}
module.exports = DbConnection;
Users.model.js
module.exports = (sequelize, DataTypes) => {
const Users = sequelize.define(
"users",
{
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
unique: true,
},
user_name: {
type: DataTypes.STRING,
allowNull: false,
},
user_email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
user_password: {
type: DataTypes.STRING,
allowNull: false,
},
role_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
initialAutoIncrement: 1900000,
}
);
// Method 02
Users.associate = (models) => {
Users.hasOne(models.UserRoles, { foreignKey: "role_id" });
};
return Users;
};
UserRoles.model.js
module.exports = (sequelize, DataTypes) => {
const UserRoles = sequelize.define(
"user_roles",
{
role_id: {
type: DataTypes.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
unique: true,
},
role_name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
initialAutoIncrement: 100000,
}
);
// Method 02
UserRoles.associate = (models) => {
UserRoles.hasMany(models.Users, { as: "users", foreignKey: "user_id" });
};
return UserRoles;
};
My query is as follows:
findUser(body, callback) {
let jwt = new JsonWebToken();
let encrypted = crypto
.createHash("md5")
.update(body.password)
.digest("hex");
this.Users.findOne({
includes: [
model: 'user_roles'
]
where: {
user_email: body.email,
user_password: encrypted,
},
})
.then((res) => {
console.log(res)
})
.catch((err) => {
callback.status(302).send("Error Found" + err);
});
}
The error is throws as follows:
Error FoundSequelizeEagerLoadingError: user_roles is not associated to users!
Any help would be appreciated.
Thanks

sequelize returns empty array at querying

doesn't matter if I try findOne() or findAll()
I get : []
empty array.
the query being called for findAll() is:
SELECT "id", "password", "firstName", "lastName", "email", "phone", "roleId", "userId", "createdAt", "updatedAt" FROM "Users" AS "Users";
while when I manually use in pgadmin cli this query: select * from Users;
I get all the rows of the table.
could you please advise?
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = require('../db/database')
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
//console.log(sequelize);
const User = sequelize.define("Users", {
password: {
type: Sequelize.STRING,
allowNull: false,
validate:{
len: [8,40],
trim: true
}
},
firstName: {
type: Sequelize.STRING,
allowNull: false,
validate:{
len: [0,20],
trim: true,
lowercase: true
}
},
lastName: {
type: Sequelize.STRING,
allowNull: false,
validate:{
len: [0,20],
trim: true,
lowercase: true
}
},
email: {
type: Sequelize.STRING,
unique: true,
allowNull: false,
validate:{
len: [0,20],
trim: true,
lowercase: true,
isEmail: true
}
},
phone: {
type: Sequelize.STRING,
validate:{
len: [10,10],
trim: true,
}
},
roleId: {
type: Sequelize.INTEGER,
allowNull: false,
validate:{
trim: true
/* must convert roleId from string to integer
toInt(value){
return parseInt(value);
}*/
}
},
userId: {
type: Sequelize.INTEGER,
allowNull: false
}
},
{
timestamps: true,
versionKey: false,
hooks:{
beforeSave: async function(user,options){
if (user.isModified('password')) {
user.password = await bcrypt.hash(user.password, 8)
}
}
}
}
);
User.prototype.toJSON = function () {
const user = this;
const userObject = user.toObject();
delete userObject.password;
delete userObject.tokens;
return userObject;
};
User.prototype.generateAuthToken = async function () {
const user = this;
const payload = { user };
const token = jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET, {
expiresIn: 360000
});
return token;
};
const findByCredentials = async (email, password) => {
const users= await User.findAll();
const user = await User.findOne({where: {email}});
if (!user) {
throw Error('invalid email');
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
throw Error('invalid password');
}
return user;
}
User.sync();
module.exports = {
User,
findByCredentials
}

Routing in NodeJs

I am working on an eCommerce application, and I am trying to save users in my database but when I hit the API in the postmen then instead of :
res.json({
name: user.name,
email: user.email,
id: user._id
});
});
**instead of this code following code is running
user.save((err, user) => {
if (err) {
return res.status(400).json({
err: "NOT able to save user in DB"
});
}
//the complete code of my "auth.js" file is as following:
const User = require("../models/user");
exports.signup = (req, res) => {
const user = new User(req.body);
user.save((err, user) => {
if (err) {
return res.status(400).json({
err: "NOT able to save user in DB"
});
}
res.json({
name: user.name,
email: user.email,
id: user._id
});
});
};
exports.signout = (req, res) => {
res.json({
message: "User signout"
});
};
///and the complete code of my user model file is as following:
var mongoose = require("mongoose");
const crypto = require("crypto");
const uuidv1 = require("uuid/v1");
var 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
},
userinfo: {
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(function(password) {
this._password = password;
this.salt = uuidv1();
this.encry_password = this.securePassword(password);
})
.get(function() {
return this._password;
});
userSchema.methods = {
autheticate: function(plainpassword) {
return this.securePassword(plainpassword) === this.encry_password;
},
securePassword: function(plainpassword) {
if (!plainpassword) return "";
try {
return crypto
.createHmac("sha256", this.salt)
.update(plainpassword)
.digest("hex");
} catch (err) {
return "";
}
}
};
module.exports = mongoose.model("User", userSchema);
SO please anyone tell me how to solve this problem while hiting this code to api mongo shell is also opend and mean while i also keep ROBO3T connected.

The classMethods findMyMobile() when called from contoller is giving error

I have created number of function in the user model which are both instance and class methods. But when i am calling class method findMyMobile() from a controller it is giving 'not a function' error. I tried display it inside the controller but it seems it is undefined there.
model/user.js
const { Sequelize, sequelize } = require('../db/sequelize');
const jwt = require('jsonwebtoken');
const Model = Sequelize.Model;
class User extends Model {}
User.init({
id:{
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
allowNull: false
},
mobile_number:{
field:'mobile_number',
type: Sequelize.BIGINT(10),
unique:true,
allowNull: false,
is:/^[1-9]\d{9}$/g,
},
type:{
type: Sequelize.ENUM('0','1','2'),
allowNull: false,
defaultValue: '1',
},
otp:{
type: Sequelize.STRING,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW
}
},{ sequelize,
modelName:'user',
classMethods:{
findByMobile: function(){
var User = this;
return User.findOne({'mobile_number':data['mobile_number']}).then(user => {
return new Promise((resolve,reject)=>{
if(user)
resolve(user);
else
reject(new Error('No user found'));
});
}).catch(err=>{
return Promise.reject(new Error('Database error'));
})
}
}
})
User.sync();
module.exports = {
User
}
controller/login.js
const { User } = require('../model/user');
const _ = require('lodash');
exports.login = (req, res) => {
const mobile = _.pick(req.body, ['mobile_number']);
console.log(typeof User.findByMobile);
User.findByMobile(mobile).then((user) => {
console.log(user);
}).catch(err => {
var response = {
status: 'failure',
message: err.message
}
res.send(response);
});
};
ERROR:
TypeError: User.findByMobile is not a function
Since sequelize v4 classMethods and instanceMethod are removed from the configuration options : https://sequelize.org/v4/manual/tutorial/upgrade-to-v4.html#config-options
You have two ways to define them
class User extends Model {
//Class Method
static findByMobile() {}
//Instance Method
findByMobile() {}
}
OR
class User extends Model { }
//Class Method
User.findByMobile = function() {}
//Instance Method
User.prototype.findByMobile = function() {}
I think you have the export wrong. See this example for reference.
module.exports = {
getName: () => {
return 'Jim';
},
getLocation: () => {
return 'Munich';
},
dob: '12.01.1982',
};
Then on the import file:
const { getName, dob } = require('./user');
console.log(
`${getName()} was born on ${dob}.`
);
What I do suggest is export the function itself. See link below for ref:
What is the purpose of Node.js module.exports and how do you use it?

How to display details in one to many relationship

In my case, one maincategory has many subcategories.
maincategory model defined:
const MainCategorySchema = mongoose.Schema({
mainCategoryName: {
type: String,
unique: true,
required: true,
},
});
subcategory model defined
const SubCategorySchema = mongoose.Schema({
subCategoryName: {
type: String,
unique: true,
required: true,
},
main_category: {
type: mongoose.Schema.Types.ObjectId,
ref: "MainCategory",
},
});
module.exports.getAllSubCategories = function (callback) {
SubCategory.find(callback);
};
route
router.get( "/subCategories",
passport.authenticate("jwt", { session: false }),
(req, res) => {
SubCategory.getAllSubCategories((err, subCategory) => {
if (err) {
let message = "No category";
return res.json({
success: false,
message,
});
} else {
return res.send(subCategory);
}
});
}
);
How can I display mainCategoryName along with subCategoryName?
You need to populate main_category like this:
router.get("/subCategories",
passport.authenticate("jwt", { session: false }), (req, res) => {
SubCategory.find()
.populate("main_category")
.exec((err, subCategory) => {
if (err) {
let message = "No category";
return res.json({
success: false,
message
});
} else {
return res.send(subCategory);
}
});
}
);

Resources