diff --git a/migrations/20200203160355-create-permissions.js b/migrations/20200203160355-create-permissions.js new file mode 100644 index 00000000..f51d2dad --- /dev/null +++ b/migrations/20200203160355-create-permissions.js @@ -0,0 +1,44 @@ +module.exports = { + up: (queryInterface, Sequelize) => queryInterface.createTable('permissions', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + scope: { + type: Sequelize.STRING, + allowNull: false + }, + action: { + type: Sequelize.STRING, + allowNull: false + }, + object: { + type: Sequelize.STRING, + allowNull: false + }, + combined: { + type: Sequelize.STRING, + allowNull: false + }, + description: { + type: Sequelize.TEXT, + allowNull: false + }, + filters: { + type: Sequelize.ARRAY(Sequelize.STRING), + allowNull: false, + defaultValue: [] + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }), + down: (queryInterface) => queryInterface.dropTable('permissions') +}; diff --git a/migrations/20200203171809-create-circle-permissions.js b/migrations/20200203171809-create-circle-permissions.js new file mode 100644 index 00000000..5c97ae49 --- /dev/null +++ b/migrations/20200203171809-create-circle-permissions.js @@ -0,0 +1,35 @@ +module.exports = { + up: (queryInterface, Sequelize) => queryInterface.createTable('circle_permissions', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + circle_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'circles', + key: 'id' + } + }, + permission_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'permissions', + key: 'id' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }), + down: (queryInterface) => queryInterface.dropTable('circle_permissions') +}; diff --git a/models/CirclePermission.js b/models/CirclePermission.js new file mode 100644 index 00000000..15ae7f29 --- /dev/null +++ b/models/CirclePermission.js @@ -0,0 +1,10 @@ +const { sequelize } = require('../lib/sequelize'); + +const CirclePermission = sequelize.define('circle_permission', {}, { + underscored: true, + tableName: 'circle_permissions', + createdAt: 'created_at', + updatedAt: 'updated_at', +}); + +module.exports = CirclePermission; diff --git a/models/Permission.js b/models/Permission.js new file mode 100644 index 00000000..7512cda3 --- /dev/null +++ b/models/Permission.js @@ -0,0 +1,63 @@ +const { Sequelize, sequelize } = require('../lib/sequelize'); + +const Permission = sequelize.define('permission', { + scope: { + type: Sequelize.ENUM('global', 'global'), + allowNull: false, + defaultValue: '', + validate: { + isIn: { + args: [['global', 'local']], + msg: 'Permission scope should be one of these: "global", "local".' + } + } + }, + action: { + type: Sequelize.STRING, + allowNull: false, + defaultValue: '', + validate: { + notEmpty: { msg: 'Action should be set.' }, + }, + }, + object: { + type: Sequelize.STRING, + allowNull: false, + defaultValue: '', + validate: { + notEmpty: { msg: 'Object should be set.' }, + }, + }, + combined: { + type: Sequelize.STRING, + allowNull: true + }, + description: { + type: Sequelize.STRING, + allowNull: false, + defaultValue: '', + validate: { + notEmpty: { msg: 'Description should be set.' }, + }, + }, + filters: { + type: Sequelize.ARRAY(Sequelize.STRING), + allowNull: false, + defaultValue: [] + } +}, { + underscored: true, + tableName: 'permissions', + createdAt: 'created_at', + updatedAt: 'updated_at', +}); + +Permission.afterValidate((permission) => { + permission.combined = [ + permission.scope, + permission.action, + permission.object + ].join(':'); +}); + +module.exports = Permission; diff --git a/models/index.js b/models/index.js index dd9b74a4..dd1318e8 100644 --- a/models/index.js +++ b/models/index.js @@ -5,6 +5,8 @@ const AccessToken = require('./AccessToken'); const RefreshToken = require('./RefreshToken'); const Body = require('./Body'); const Circle = require('./Circle'); +const Permission = require('./Permission'); +const CirclePermission = require('./CirclePermission'); Campaign.hasMany(User, { foreignKey: 'campaign_id' }); User.belongsTo(Campaign, { foreignKey: 'campaign_id' }); @@ -24,6 +26,9 @@ Circle.belongsTo(Body, { foreignKey: 'body_id' }); Circle.hasMany(Circle, { foreignKey: 'parent_circle_id', as: 'child_circles' }); Circle.belongsTo(Circle, { foreignKey: 'parent_circle_id', as: 'parent_circle' }); +Circle.belongsToMany(Permission, { through: CirclePermission, foreignKey: 'circle_id', as: 'permissions' }); +Permission.belongsToMany(Circle, { through: CirclePermission, foreignKey: 'permission_id', as: 'circles' }); + module.exports = { User, Campaign, @@ -31,5 +36,6 @@ module.exports = { AccessToken, RefreshToken, Body, - Circle + Circle, + Permission };