'use strict'; const fs = require('fs'); const path = require('path'); const { Sequelize, Utils } = require('sequelize'); const process = require('process'); const basename = path.basename(__filename); const env = process.env.NODE_ENV || 'development'; const config = require(__dirname + '/config/config.js'); const db = {}; let sequelize; // Connect sequelize models to LDAP models const ldapModels = require('../ldap'); function getFieldWithLdap(attributes){ let out = []; for (const [attribute, options] of Object.entries(attributes)) { if(options.ldapModel) out.push(attribute) } return out; } const sequilze_conf = { define: { hooks: { async afterValidate(instance) { let hasError = false; function itemError(key, validator, message){ let error = new Sequelize.ValidationErrorItem(message); error.type = 'Validation error'; error.path = key; error.origin = 'FUNCTION'; error.instance = instance; error.validatorKey = 'validator'; error.validatorName = 'validator'; error.validatorArgs = []; error.original = []; throw new Sequelize.ValidationError(null, [error]); } for(let attribute of getFieldWithLdap(this.getAttributes())){ let externalModel = ldapModels[this.getAttributes()[attribute].ldapModel]; if(!externalModel) itemError(attribute, 'modelExists', `LDAP model ${this.getAttributes()[attribute].ldapModel} not found.`); if(!hasError && !(await externalModel.exists(instance[attribute])) ) itemError(attribute, 'foreignKey', `LDAP model has no object ${instance[attribute]}`); } } } } } class _Model extends Sequelize.Model{ constructor(...args){ super(...args) let hasLdap = getFieldWithLdap(this.constructor.getAttributes()) for(let attribute of hasLdap){ let externalModelName = this.constructor.getAttributes()[attribute].ldapModel; this[`get${externalModelName}`] = async function(){ return await ldapModels[externalModelName].get(this[attribute]); } } } // Backward compatible with my LDAP and Redis models. // I will update the LDAP and Redis stuff to have method interfaces inline with sequilze static async get(token){ return await this.findByPk(token); } } if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config); } else { sequelize = new Sequelize(config.database, config.username, config.password, {...config, ...sequilze_conf}); } fs .readdirSync(__dirname) .filter(file => { return ( file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' && file.indexOf('.test.js') === -1 ); }) .forEach(file => { const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes, _Model); db[model.name] = model; }); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); db.sequelize = sequelize; db.Sequelize = Sequelize; module.exports = db;