I'm new in this sequelize things. I try to associate model between Users and Permissions through UserPermissions using belongsToMany, and this is my code.
-- users.js
const bcrypt = require('bcrypt');
const config = require('../config/general');
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isLowercase: true,
notEmpty: true,
isEmail: true
}
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isLowercase: true,
notEmpty: true,
min: 3
}
},
salt: {
type: DataTypes.STRING,
allowNull: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
}, {
underscored: true,
classMethods: {
associate: (models) => {
User.belongsToMany(models.Permission, {
through: 'UserPermissions',
foreignKey: 'user_id'
});
},
validPassword: (password, passwd, done) => {
const tmppass = password + config.secret;
bcryptpare(tmppass, passwd, (err, isMatch) => {
if (err) return done(err);
return done(null, isMatch);
});
}
}
});
User.beforeCreate( (user, option, done) => {
bcrypt.genSalt(SALT_WORK_FACTOR, (err, salt) => {
if (err) return done(err);
const tmppass = user.password + config.secret;
bcrypt.hash(tmppass, salt, (err, hash) => {
if (err) return done(err);
user.salt = salt;
user.password = hash;
return done(null, user);
});
});
});
return User;
};
-- permissions.js
module.exports = (sequelize, DataTypes) => {
const Permission = sequelize.define('Permission', {
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
slug: {
type: DataTypes.STRING,
validate: {
isLowercase: true
}
},
description: {
type: DataTypes.TEXT
}
}, {
underscored: true,
classMethods: {
associate: (models) => {
Permission.belongsToMany(models.User, {
through: 'UserPermissions',
foreignKey: 'permission_id'
});
}
}
});
return Permission;
};
According to sequelize docs about belongsToMany in here, belongsToMany will create a new model that link to whatever model that you join, right.
This will create a new model called UserProject with the equivalent foreign keys projectId and userId. Whether the attributes are camelcase or not depends on the two models joined by the table (in this case User and Project). Sequelize Belongs-To-Many
But when I try that and migrate it using sequelize-cli
, I didn't see any join table that had been created. The Users Table is created, The Permissions Table is created, but UserPermissions Table is not created. Did I miss some thing in here? or there is something wrong with my code?
I'm using postgres
dialect, "pg": "^6.4.0"
and "sequelize": "^4.3.1"
Oh ya, I'm really sorry about my english, I'm not really good in english.
I'm new in this sequelize things. I try to associate model between Users and Permissions through UserPermissions using belongsToMany, and this is my code.
-- users.js
const bcrypt = require('bcrypt');
const config = require('../config/general');
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isLowercase: true,
notEmpty: true,
isEmail: true
}
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isLowercase: true,
notEmpty: true,
min: 3
}
},
salt: {
type: DataTypes.STRING,
allowNull: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
}, {
underscored: true,
classMethods: {
associate: (models) => {
User.belongsToMany(models.Permission, {
through: 'UserPermissions',
foreignKey: 'user_id'
});
},
validPassword: (password, passwd, done) => {
const tmppass = password + config.secret;
bcrypt.pare(tmppass, passwd, (err, isMatch) => {
if (err) return done(err);
return done(null, isMatch);
});
}
}
});
User.beforeCreate( (user, option, done) => {
bcrypt.genSalt(SALT_WORK_FACTOR, (err, salt) => {
if (err) return done(err);
const tmppass = user.password + config.secret;
bcrypt.hash(tmppass, salt, (err, hash) => {
if (err) return done(err);
user.salt = salt;
user.password = hash;
return done(null, user);
});
});
});
return User;
};
-- permissions.js
module.exports = (sequelize, DataTypes) => {
const Permission = sequelize.define('Permission', {
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
slug: {
type: DataTypes.STRING,
validate: {
isLowercase: true
}
},
description: {
type: DataTypes.TEXT
}
}, {
underscored: true,
classMethods: {
associate: (models) => {
Permission.belongsToMany(models.User, {
through: 'UserPermissions',
foreignKey: 'permission_id'
});
}
}
});
return Permission;
};
According to sequelize docs about belongsToMany in here, belongsToMany will create a new model that link to whatever model that you join, right.
This will create a new model called UserProject with the equivalent foreign keys projectId and userId. Whether the attributes are camelcase or not depends on the two models joined by the table (in this case User and Project). Sequelize Belongs-To-Many
But when I try that and migrate it using sequelize-cli
, I didn't see any join table that had been created. The Users Table is created, The Permissions Table is created, but UserPermissions Table is not created. Did I miss some thing in here? or there is something wrong with my code?
I'm using postgres
dialect, "pg": "^6.4.0"
and "sequelize": "^4.3.1"
Oh ya, I'm really sorry about my english, I'm not really good in english.
Share Improve this question asked Jul 12, 2017 at 7:09 Lukman WahyudiLukman Wahyudi 711 silver badge2 bronze badges 3- You will need to write your own migration for the through table – mcranston18 Commented Jul 13, 2017 at 1:10
- Ah I see, so that's mean this belongsToMany didn't create is own join table if we use migration? – Lukman Wahyudi Commented Jul 13, 2017 at 2:10
-
Correct. If you create a
belongsToMany
relationship, you will need to manually create a migration file and run your migrations. – mcranston18 Commented Jul 13, 2017 at 13:45
1 Answer
Reset to default 8To answer your question (many years later):
You were likely told by the documentation to do this to create a join table:
In your User associations:
User.belongsToMany(models.Permission, {
through: 'UserPermissions',
foreignKey: 'user_id'
});
In your Permission associations:
Permission.belongsToMany(models.User, {
through: 'UserPermissions',
foreignKey: 'permission_id'
});
The portion of the process not mentioned in the documentation is how to actually create this table that you use in the database. To create the table used by these functions in the database, create a migration with the following code:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('UserPermissions', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
permission_id: {
type: Sequelize.INTEGER,
references: {
model: 'Permissions',
key: 'id',
as: 'permission_id'
}
},
user_id: {
type: Sequelize.INTEGER,
references: {
model: 'Users',
key: 'id',
as: 'user_id'
}
},
createdAd: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('UserPermissions')
}
}
Using the Sequelize CLI will generate most of this code for you. Note that the model
object property under references
is the table name in postgres (well, this is what worked for me).
EDIT:
Also note that the through
property should be a model, so:
through: models.UserPermission
and create the relevant model.