UNPKG

@aarconada/urserver

Version:

Basic Server definitions to develope REST API with a node + express Server

833 lines (788 loc) 80 kB
/** * Created by ubuntu on 12/09/18. */ 'use strict'; const server = require('./server')(); const _ = require('lodash'); const definitionoptions = {}; const definitions = {}; var Sequelize = null; var model = null; const SqlWhereParser = require('sql-where-parser'); const parser = new SqlWhereParser(); if(server.configuration.sequelize.enabled) { Sequelize = require('sequelize-views-support'); model = new Sequelize( server.configuration.sequelize.database.name, server.configuration.sequelize.database.login, server.configuration.sequelize.database.password, server.configuration.sequelize.connection); model .authenticate() .then(() => { server.debug('MySQL Connection has been established succesfully.') }) .catch((err) => { server.debug('Unable to connect to the database', err); }); if(server.configuration.sequelize.mustSync) { model.sync(server.configuration.sequelize.sync); } } module.exports.model = model; module.exports.api = Sequelize; module.exports.options = definitionoptions; module.exports.define = function(options) { if(model === null || !options || !options.modelname || !options.schema) { return null; } options.configuration = !_.isUndefined(options.configuration) ? options.configuration : {}; options.configuration.icon = !_.isUndefined(options.configuration.icon) ? options.configuration.icon : 'photo'; options.configuration.treatAsView = !_.isUndefined(options.configuration.treatAsView) ? options.configuration.treatAsView : false; options.configuration.viewDefinition = !_.isUndefined(options.configuration.viewDefinition) ? options.configuration.viewDefinition : ''; options.configuration.timestamps = !_.isUndefined(options.configuration.timestamps) ? options.configuration.timestamps : !options.configuration.treatAsView; options.configuration.version = !_.isUndefined(options.configuration.version) ? options.configuration.version : !options.configuration.treatAsView; options.configuration.paranoid = !_.isUndefined(options.configuration.paranoid) ? options.configuration.paranoid : !options.configuration.treatAsView; options.GET = !_.isUndefined(options.GET) ? options.GET : {}; options.GET.all = !_.isUndefined(options.GET.all) ? options.GET.all : {}; options.GET.all.enabled = !_.isUndefined(options.GET.all.enabled) ? options.GET.all.enabled : true; options.GET.all.token = !_.isUndefined(options.GET.all.token) ? options.GET.all.token : {}; options.GET.all.token.required = !_.isUndefined(options.GET.all.token.required) ? options.GET.all.token.required : true; options.GET.all.token.ignoreExpiration = !_.isUndefined(options.GET.all.token.ignoreExpiration) ? options.GET.all.token.ignoreExpiration : false; options.GET.all.help = !_.isUndefined(options.GET.all.help) ? options.GET.all.help : {}; options.GET.all.help.enabled = !_.isUndefined(options.GET.all.help.enabled) ? options.GET.all.help.enabled : true; options.GET.all.help.route = !_.isUndefined(options.GET.all.help.route) ? options.GET.all.help.route : '/help'; options.GET.all.session = !_.isUndefined(options.GET.all.session) ? options.GET.all.session : {}; options.GET.all.session.required = !_.isUndefined(options.GET.all.session.required) ? options.GET.all.session.required : true; options.GET.all.session.ignoreExpiration = !_.isUndefined(options.GET.all.session.allowedRoles) ? options.GET.all.session.allowedRoles : {}; options.GET.all.include = !_.isUndefined(options.GET.all.include) ? options.GET.all.include : {all: true}; options.GET.all.where = !_.isUndefined(options.GET.all.where) ? options.GET.all.where : {}; options.GET = !_.isUndefined(options.GET) ? options.GET : {}; options.GET.single = !_.isUndefined(options.GET.single) ? options.GET.single : {}; options.GET.single.enabled = !_.isUndefined(options.GET.single.enabled) ? options.GET.single.enabled : !options.configuration.treatAsView; options.GET.single.token = !_.isUndefined(options.GET.single.token) ? options.GET.single.token : {}; options.GET.single.token.required = !_.isUndefined(options.GET.single.token.required) ? options.GET.single.token.required : true; options.GET.single.token.ignoreExpiration = !_.isUndefined(options.GET.single.token.ignoreExpiration) ? options.GET.single.token.ignoreExpiration : false; options.GET.single.help = !_.isUndefined(options.GET.single.help) ? options.GET.single.help : {}; options.GET.single.help.enabled = !_.isUndefined(options.GET.single.help.enabled) ? options.GET.single.help.enabled : true; options.GET.single.help.route = !_.isUndefined(options.GET.single.help.route) ? options.GET.single.help.route : '/help'; options.GET.single.session = !_.isUndefined(options.GET.single.session) ? options.GET.single.session : {}; options.GET.single.session.required = !_.isUndefined(options.GET.single.session.required) ? options.GET.single.session.required : true; options.GET.single.session.ignoreExpiration = !_.isUndefined(options.GET.single.session.allowedRoles) ? options.GET.single.session.allowedRoles : {}; options.GET.single.include = !_.isUndefined(options.GET.single.include) ? options.GET.single.include : {all: true}; options.GET.single.where = !_.isUndefined(options.GET.single.where) ? options.GET.single.where : {}; options.POST = !_.isUndefined(options.POST) ? options.POST : {}; options.POST.single = !_.isUndefined(options.POST.single) ? options.POST.single : {}; options.POST.single.enabled = !_.isUndefined(options.POST.single.enabled) ? options.POST.single.enabled : !options.configuration.treatAsView; options.POST.single.token = !_.isUndefined(options.POST.single.token) ? options.POST.single.token : {}; options.POST.single.token.required = !_.isUndefined(options.POST.single.token.required) ? options.POST.single.token.required : true; options.POST.single.token.ignoreExpiration = !_.isUndefined(options.POST.single.token.ignoreExpiration) ? options.POST.single.token.ignoreExpiration : false; options.POST.single.help = !_.isUndefined(options.POST.single.help) ? options.POST.single.help : {}; options.POST.single.help.enabled = !_.isUndefined(options.POST.single.help.enabled) ? options.POST.single.help.enabled : true; options.POST.single.help.route = !_.isUndefined(options.POST.single.help.route) ? options.POST.single.help.route : '/help'; options.POST.single.session = !_.isUndefined(options.POST.single.session) ? options.POST.single.session : {}; options.POST.single.session.required = !_.isUndefined(options.POST.single.session.required) ? options.POST.single.session.required : true; options.POST.single.session.ignoreExpiration = !_.isUndefined(options.POST.single.session.allowedRoles) ? options.POST.single.session.allowedRoles : {}; options.PUT = !_.isUndefined(options.PUT) ? options.PUT : {}; options.PUT.single = !_.isUndefined(options.PUT.single) ? options.PUT.single : {}; options.PUT.single.enabled = !_.isUndefined(options.PUT.single.enabled) ? options.PUT.single.enabled : !options.configuration.treatAsView; options.PUT.single.token = !_.isUndefined(options.PUT.single.token) ? options.PUT.single.token : {}; options.PUT.single.token.required = !_.isUndefined(options.PUT.single.token.required) ? options.PUT.single.token.required : true; options.PUT.single.token.ignoreExpiration = !_.isUndefined(options.PUT.single.token.ignoreExpiration) ? options.PUT.single.token.ignoreExpiration : false; options.PUT.single.help = !_.isUndefined(options.PUT.single.help) ? options.PUT.single.help : {}; options.PUT.single.help.enabled = !_.isUndefined(options.PUT.single.help.enabled) ? options.PUT.single.help.enabled : true; options.PUT.single.help.route = !_.isUndefined(options.PUT.single.help.route) ? options.PUT.single.help.route : '/help'; options.PUT.single.session = !_.isUndefined(options.PUT.single.session) ? options.PUT.single.session : {}; options.PUT.single.session.required = !_.isUndefined(options.PUT.single.session.required) ? options.PUT.single.session.required : true; options.PUT.single.session.ignoreExpiration = !_.isUndefined(options.PUT.single.session.allowedRoles) ? options.PUT.single.session.allowedRoles : {}; options.PUT = !_.isUndefined(options.PUT) ? options.PUT : {}; options.PUT.all = !_.isUndefined(options.PUT.all) ? options.PUT.all : {}; options.PUT.all.enabled = !_.isUndefined(options.PUT.all.enabled) ? options.PUT.all.enabled : !options.configuration.treatAsView; options.PUT.all.token = !_.isUndefined(options.PUT.all.token) ? options.PUT.all.token : {}; options.PUT.all.token.required = !_.isUndefined(options.PUT.all.token.required) ? options.PUT.all.token.required : true; options.PUT.all.token.ignoreExpiration = !_.isUndefined(options.PUT.all.token.ignoreExpiration) ? options.PUT.all.token.ignoreExpiration : false; options.PUT.all.help = !_.isUndefined(options.PUT.all.help) ? options.PUT.all.help : {}; options.PUT.all.help.enabled = !_.isUndefined(options.PUT.all.help.enabled) ? options.PUT.all.help.enabled : true; options.PUT.all.help.route = !_.isUndefined(options.PUT.all.help.route) ? options.PUT.all.help.route : '/help'; options.PUT.all.session = !_.isUndefined(options.PUT.all.session) ? options.PUT.all.session : {}; options.PUT.all.session.required = !_.isUndefined(options.PUT.all.session.required) ? options.PUT.all.session.required : true; options.PUT.all.session.ignoreExpiration = !_.isUndefined(options.PUT.all.session.allowedRoles) ? options.PUT.all.session.allowedRoles : {}; options.DELETE = !_.isUndefined(options.DELETE) ? options.DELETE : {}; options.DELETE.single = !_.isUndefined(options.DELETE.single) ? options.DELETE.single : {}; options.DELETE.single.enabled = !_.isUndefined(options.DELETE.single.enabled) ? options.DELETE.single.enabled : !options.configuration.treatAsView; options.DELETE.single.token = !_.isUndefined(options.DELETE.single.token) ? options.DELETE.single.token : {}; options.DELETE.single.token.required = !_.isUndefined(options.DELETE.single.token.required) ? options.DELETE.single.token.required : true; options.DELETE.single.token.ignoreExpiration = !_.isUndefined(options.DELETE.single.token.ignoreExpiration) ? options.DELETE.single.token.ignoreExpiration : false; options.DELETE.single.help = !_.isUndefined(options.DELETE.single.help) ? options.DELETE.single.help : {}; options.DELETE.single.help.enabled = !_.isUndefined(options.DELETE.single.help.enabled) ? options.DELETE.single.help.enabled : true; options.DELETE.single.help.route = !_.isUndefined(options.DELETE.single.help.route) ? options.DELETE.single.help.route : '/help'; options.DELETE.single.session = !_.isUndefined(options.DELETE.single.session) ? options.DELETE.single.session : {}; options.DELETE.single.session.required = !_.isUndefined(options.DELETE.single.session.required) ? options.DELETE.single.session.required : true; options.DELETE.single.session.ignoreExpiration = !_.isUndefined(options.DELETE.single.session.allowedRoles) ? options.DELETE.single.session.allowedRoles : {}; options.DELETE = !_.isUndefined(options.DELETE) ? options.DELETE : {}; options.DELETE.all = !_.isUndefined(options.DELETE.all) ? options.DELETE.all : {}; options.DELETE.all.enabled = !_.isUndefined(options.DELETE.all.enabled) ? options.DELETE.all.enabled : !options.configuration.treatAsView; options.DELETE.all.token = !_.isUndefined(options.DELETE.all.token) ? options.DELETE.all.token : {}; options.DELETE.all.token.required = !_.isUndefined(options.DELETE.all.token.required) ? options.DELETE.all.token.required : true; options.DELETE.all.token.ignoreExpiration = !_.isUndefined(options.DELETE.all.token.ignoreExpiration) ? options.DELETE.all.token.ignoreExpiration : false; options.DELETE.all.help = !_.isUndefined(options.DELETE.all.help) ? options.DELETE.all.help : {}; options.DELETE.all.help.enabled = !_.isUndefined(options.DELETE.all.help.enabled) ? options.DELETE.all.help.enabled : true; options.DELETE.all.help.route = !_.isUndefined(options.DELETE.all.help.route) ? options.DELETE.all.help.route : '/help'; options.DELETE.all.session = !_.isUndefined(options.DELETE.all.session) ? options.DELETE.all.session : {}; options.DELETE.all.session.required = !_.isUndefined(options.DELETE.all.session.required) ? options.DELETE.all.session.required : true; options.DELETE.all.session.ignoreExpiration = !_.isUndefined(options.DELETE.all.session.allowedRoles) ? options.DELETE.all.session.allowedRoles : {}; const newModelDefinition = model.define( options.modelname, options.schema, options.configuration); definitionoptions[options.modelname] = options; definitions[options.modelname] = newModelDefinition; module.exports[options.modelname] = newModelDefinition; return newModelDefinition; }; module.exports.generateEndpoints = function() { server.debug('Starting generation of endpoints for the model'); for(var currentOptions in definitionoptions) { var currentDefinitionOptions = definitionoptions[currentOptions]; var currentDefinition = definitions[currentOptions]; const pluralName = currentDefinition.tableName; const singularName = currentDefinition.name; server.debug('Generating endpoints to model', currentDefinitionOptions.modelname); if(currentDefinitionOptions.GET.all.enabled) { generateGetAllEndpoint(currentDefinition, currentDefinitionOptions.GET.all, pluralName); } if(currentDefinitionOptions.GET.single.enabled) { generateGetSingleEndpoint(currentDefinition, currentDefinitionOptions.GET.single, pluralName, singularName); } if(currentDefinitionOptions.POST.single.enabled) { generatePostSingleEndpoint(currentDefinition, currentDefinitionOptions.POST.single, pluralName, singularName); } if(currentDefinitionOptions.PUT.all.enabled) { generatePutAllEndpoint(currentDefinition, currentDefinitionOptions.PUT.all, pluralName, singularName); } if(currentDefinitionOptions.PUT.single.enabled) { generatePutSingleEndpoint(currentDefinition, currentDefinitionOptions.PUT.single, pluralName, singularName); } if(currentDefinitionOptions.DELETE.all.enabled) { generateDeleteAllEndpoint(currentDefinition, currentDefinitionOptions.DELETE.all, pluralName, singularName); } if(currentDefinitionOptions.DELETE.single.enabled) { generateDeleteSingleEndpoint(currentDefinition, currentDefinitionOptions.DELETE.single, pluralName, singularName); } } }; function generateGetAllEndpoint(currentDefinition, options, plural){ try { const attributeList = []; const filterList = []; const parameters = [ { name : 'sort', dataType : server.utils.dataType.STRING, parameterType : server.utils.parameterType.QUERY, required : false, description : 'Allows sort the response (?sort=-f1,+f2 = Sort by f1 Descending and f2 Ascending)' }, { name : 'fields', dataType : server.utils.dataType.STRING, parameterType : server.utils.parameterType.QUERY, required : false, description : 'Allows to specify the fields that will appear in the response (?fields=f1,f2 = Returns only f1 and f2)' }, { name : 'offset', dataType : server.utils.dataType.STRING, parameterType : server.utils.parameterType.QUERY, required : false, description : 'Allows to specify first record to return' }, { name : 'limit', dataType : server.utils.dataType.STRING, parameterType : server.utils.parameterType.QUERY, required : false, description : 'Allows to specify the number of records to return' }, { name : 'filter', dataType : server.utils.dataType.STRING, parameterType : server.utils.parameterType.QUERY, required : false, description : 'Allows to specify the where clause to filter result' } ]; if(!currentDefinition['options'].treatAsView) { parameters.push({ name : 'RelatedEntityNamefilter', dataType : server.utils.dataType.STRING, parameterType : server.utils.parameterType.QUERY, required : false, description : 'Allows to specify the where clause to filter the related entity with the specified name' }); } var singleResponse = {}; const attributes = Object.keys(currentDefinition['attributes']).sort(function(a, b) {return a.toLowerCase().localeCompare(b.toLowerCase())}); attributes.forEach(currentAttributeName => { var currentAttribute = currentDefinition['attributes'][currentAttributeName]; var currentAttributeName = currentAttribute.fieldName; var currentAttributeType = '' + currentAttribute.type; var currentAttributeIsFilter= currentAttribute.isFilter ? currentAttribute.isFilter : false; if(currentAttributeType === 'INTEGER') { singleResponse[currentAttributeName] = 123; } else if(currentAttributeType === 'DATETIME') { singleResponse[currentAttributeName] = '1978-06-16T14:35:16.000Z'; } else if(currentAttributeType === 'DATE') { singleResponse[currentAttributeName] = '1978-06-16'; } else if(currentAttributeType === 'TIME') { singleResponse[currentAttributeName] = '14:35:16.000'; } else if(currentAttributeType === 'BOOLEAN') { singleResponse[currentAttributeName] = true; } else { singleResponse[currentAttributeName] = 'abc...'; } attributeList.push(currentAttributeName); }); var definitionInclude = options.include; if(!_.isUndefined(definitionInclude.all) && definitionInclude.all === true) { definitionInclude = []; Object.keys(currentDefinition.associations).forEach(currentAttribute => { server.debug(currentDefinition.associations[currentAttribute].as); if (currentDefinition.associations[currentAttribute].associationType === 'HasMany') { server.debug('AS', currentDefinition.associations[currentAttribute].as); definitionInclude.push({model: currentDefinition.associations[currentAttribute].target, as: currentDefinition.associations[currentAttribute].as}); } else { definitionInclude.push({model: currentDefinition.associations[currentAttribute].target, as: currentDefinition.associations[currentAttribute].as}); } }); } const endpointConfiguration = { name: 'Get ' + (currentDefinition['options'].treatAsView ? currentDefinition.name : plural.toLowerCase()), description: (currentDefinition['options'].treatAsView ? 'This endpoint returns the execution of view ' + currentDefinition.name : 'This endpoint returns a list of ' + plural), route: '/' + (currentDefinition['options'].treatAsView ? currentDefinition.name : plural.toLowerCase()), method: server.utils.method.GET, callback: options.callback ? options.callback : function (req, res, next, allowedResponses) { var attributes = attributeList; var include = definitionInclude; var limit = null; var offset = null; var order = []; var findWhere = []; filterList.forEach(currentAttribute => { if(!server.utils.valueInList(req.currentSession.filters, currentAttribute)) { server.utils.throwError(allowedResponses.unauthorized); } }); attributeList.forEach(currentAttribute => { if(server.utils.valueInList(req.currentSession.filters, currentAttribute)) { server.debug('Auto filtering ' + currentAttribute + ' from Filters'); var filterObject = {}; filterObject[currentAttribute] = req.currentSession.filters[currentAttribute]; findWhere.push(filterObject); } }); Object.keys(req.query).forEach(currentParameter => { if(currentParameter === 'fields') { attributes = req.query.fields.split(','); include = []; } else if(currentParameter === 'limit') { limit = +req.query.limit; }else if(currentParameter === 'offset') { offset = +req.query.offset; }else if(currentParameter === 'sort') { req.query.sort.split(',').forEach(currentSortValue => { currentSortValue = currentSortValue.trim(); var sortType = 'ASC'; var fieldName = ''; if (currentSortValue[0] === '-') { sortType = 'DESC'; fieldName = currentSortValue.substring(1); } else if (currentSortValue[0] === '+') { fieldName = currentSortValue.substring(1); } else { fieldName = currentSortValue; } order.push([fieldName, sortType]); }); } else if(currentParameter === 'filter') { findWhere.push(getFilterWhere(currentDefinition.name, req.query.filter)); } else if(currentParameter.endsWith('filter')) { const relatedEntityName = currentParameter.replace('filter', ''); var validFilter = false; include.forEach(currentInclude => { if(currentInclude.model.name.toUpperCase() === relatedEntityName.toUpperCase()) { validFilter = true; currentInclude.where = getFilterWhere(currentInclude.model.name, req.query[currentParameter]); } }); if(!validFilter) { server.utils.throwError(server.defaultResponses.invalid_parameter); } } else { server.utils.throwError(server.defaultResponses.invalid_parameter); } }); server.debug('Getting list of', plural); return currentDefinition.findAll({ subQuery : true, attributes : attributes, include : include, where : findWhere, limit : limit, offset : offset, order : order }).then(elements => { return elements; }).catch(err => { server.debug(err); server.utils.throwError(allowedResponses.entity_unable_get_list, err); }); }, token: options.token, help: options.help, session: options.session, parameters: parameters, responses: { entity_unable_get_list : server.defaultResponses.entity_unable_get_list, unauthorized : server.defaultResponses.unauthorized }, success: [singleResponse], transactional: false, }; server.endpointmanager.addEndpoint(endpointConfiguration); } catch(err) { server.debug(err); throw err; } } function getFilterWhere (entityName, filterString) { const tableFieldParser = RegExp(/\w+\.\w+/i); const parsed = parser.parse(filterString, (operatorValue, operands) => { var includeCurrentParsedElement = true; if (!_.isNull(tableFieldParser.exec(operands[0])) || !_.isNull(tableFieldParser.exec(operands[1]))) { if (!_.isNull(tableFieldParser.exec(operands[0]))) { const whereParts = operands[0].split('.'); if (entityName.toUpperCase() !== whereParts[0].toUpperCase()) { server.utils.throwError(server.defaultResponses.invalid_filter); } else { operands[0] = whereParts[1]; } } if (!_.isNull(tableFieldParser.exec(operands[1]))) { const whereParts = operands[1].split('.'); if (currentDefinition.name.toUpperCase() !== whereParts[0].toUpperCase()) { server.utils.throwError(server.defaultResponses.invalid_filter); } else { operands[1] = whereParts[1]; } } } switch (operatorValue) { case 'AND': if (!_.isUndefined(operands[0]) && !_.isUndefined(operands[1])) { return { [server.sequelize.api.Op.and]: operands }; } else if (!_.isUndefined(operands[0])) { return operands[0]; } else if (!_.isUndefined(operands[1])) { return operands[1]; } case 'OR': return { [server.sequelize.api.Op.or]: operands }; case '!=': return { [operands[0]]: { [server.sequelize.api.Op.ne]: operands[1] } }; case '<=': return { [operands[0]]: { [server.sequelize.api.Op.lte]: operands[1] } }; case '>=': return { [operands[0]]: { [server.sequelize.api.Op.gte]: operands[1] } }; case '=': return { [operands[0]]: operands[1] }; case '>': return { [operands[0]]: { [server.sequelize.api.Op.gt]: operands[1] } }; case '<': return { [operands[0]]: { [server.sequelize.api.Op.lt]: operands[1] } }; default: server.utils.throwError(server.defaultResponses.invalid_filter); } }); return parsed; } function generateGetSingleEndpoint(currentDefinition, options, plural, singular){ try { const filterList = []; const attributeList = []; var singleResponse = {}; const attributes = Object.keys(currentDefinition['attributes']).sort(function(a, b) {return a.toLowerCase().localeCompare(b.toLowerCase())}); attributes.forEach(currentAttributeName => { var currentAttribute = currentDefinition['attributes'][currentAttributeName]; var currentAttributeName = currentAttribute.fieldName; var currentAttributeType = '' + currentAttribute.type; var currentAttributeIsFilter= currentAttribute.isFilter ? currentAttribute.isFilter : false; if(currentAttributeType === 'INTEGER') { singleResponse[currentAttributeName] = 123; } else if(currentAttributeType === 'DATETIME') { singleResponse[currentAttributeName] = '1978-06-16T14:35:16.000Z'; } else if(currentAttributeType === 'DATE') { singleResponse[currentAttributeName] = '1978-06-16'; } else if(currentAttributeType === 'TIME') { singleResponse[currentAttributeName] = '14:35:16.000'; } else if(currentAttributeType === 'BOOLEAN') { singleResponse[currentAttributeName] = true; } else { singleResponse[currentAttributeName] = 'abc...'; } attributeList.push(currentAttributeName); }); const endpointConfiguration = { name: 'Get ' + singular, description: 'This endpoint returns the ' + singular.toLowerCase() + ' associated with the :id received', route: '/' + plural.toLowerCase() + '/:id', method: server.utils.method.GET, callback: options.callback ? options.callback : function (req, res, next, allowedResponses) { server.debug('Getting', singular.toLowerCase()); filterList.forEach(currentAttribute => { if(!server.utils.valueInList(req.currentSession.filters, currentAttribute)) { throw allowedResponses.unauthorized; } }); var findWhere = [ {id: req.params.id} ]; attributeList.forEach(currentAttribute => { if (req.body[currentAttribute]) { assignations[currentAttribute] = req.body[currentAttribute]; } if(server.utils.valueInList(req.currentSession.filters, currentAttribute)) { server.debug('Auto filtering ' + currentAttribute + ' from Filters'); var filterObject = {}; filterObject[currentAttribute] = req.currentSession.filters[currentAttribute]; findWhere.push(filterObject); } }); return currentDefinition.findAll({ subQuery : false, attributes : attributeList, where : {[server.sequelize.api.Op.and]: findWhere}, include : options.include }).then(element => { if(element === null) server.utils.throwError(allowedResponses.entity_element_not_found); return element[0]; }).catch(err => { server.debug(err); server.utils.throwError(allowedResponses.entity_unable_get_element, err); }); }, token: options.token, help: options.help, session: options.session, parameters: [ { name: 'id', dataType: server.utils.dataType.INTEGER, parameterType: server.utils.parameterType.PARAM, required: true, description: 'The id of the finded ' + singular.toLowerCase() } ], responses: { entity_element_not_found: server.defaultResponses.entity_element_not_found, entity_unable_get_element: server.defaultResponses.entity_unable_get_element }, success: singleResponse, transactional: false, }; server.endpointmanager.addEndpoint(endpointConfiguration); Object.keys(currentDefinition.associations).forEach(currentAttribute => { var singleResponse = {}; var singleFilters = []; const currentTarget = currentDefinition.associations[currentAttribute].target; const attributes = Object.keys(currentTarget.attributes).sort(function(a, b) {return a.toLowerCase().localeCompare(b.toLowerCase())}); attributes.forEach(currentAttributeName => { var currentAttribute = currentTarget.attributes[currentAttributeName]; var currentAttributeName = currentAttribute.fieldName; var currentAttributeType = '' + currentAttribute.type; var currentAttributeIsFilter= currentAttribute.isFilter ? currentAttribute.isFilter : false; /* if(currentAttributeIsFilter) { if(currentAttributeName === 'id') { filterList.push(singular + 'Id'); } else { filterList.push(currentAttributeName); } } */ if(currentAttributeType === 'INTEGER') { singleResponse[currentAttributeName] = 123; } else if(currentAttributeType === 'DATETIME') { singleResponse[currentAttributeName] = '1978-06-16T14:35:16.000Z'; } else if(currentAttributeType === 'DATE') { singleResponse[currentAttributeName] = '1978-06-16'; } else if(currentAttributeType === 'TIME') { singleResponse[currentAttributeName] = '14:35:16.000'; } else if(currentAttributeType === 'BOOLEAN') { singleResponse[currentAttributeName] = true; } else { singleResponse[currentAttributeName] = 'abc...'; } }); if(currentDefinition.associations[currentAttribute].isMultiAssociation) { singleResponse = [singleResponse]; } const endpointConfiguration = { name: 'Get ' + singular + ' ' + currentAttribute, description: 'This endpoint returns the ' + currentAttribute + ' of the ' + singular.toLowerCase() + ' associated with the :id received', route: '/' + plural.toLowerCase() + '/:id/' + currentAttribute, method: server.utils.method.GET, callback: options.callback ? options.callback : function (req, res, next, allowedResponses) { server.debug('Getting list of', plural); singleFilters.forEach(currentAttribute => { if(!server.utils.valueInList(req.currentSession.filters, currentAttribute)) { throw allowedResponses.unauthorized; } }); var findWhere = [ {id: req.params.id} ] attributeList.forEach(currentAttribute => { if (req.body[currentAttribute]) { assignations[currentAttribute] = req.body[currentAttribute]; } if(server.utils.valueInList(req.currentSession.filters, currentAttribute)) { server.debug('Auto filtering ' + currentAttribute + ' from Filters'); var filterObject = {}; filterObject[currentAttribute] = req.currentSession.filters[currentAttribute]; findWhere.push(filterObject); } }); return currentDefinition.findOne({ subQuery : false, where : {[server.sequelize.api.Op.and]: findWhere}, include : options.include }).then(element => { if(element === null) server.utils.throwError(allowedResponses.entity_element_not_found); const relationGetterCallback = element['get' + currentAttribute](); return relationGetterCallback.then(relatedEntities => { return relatedEntities; }).catch(err => { server.debug(err); server.utils.throwError(allowedResponses.entity_unable_get_element, err); }) }).catch(err => { server.debug(err); server.utils.throwError(allowedResponses.entity_unable_get_element, err); }); }, token: options.token, help: options.help, session: options.session, parameters: [ { name: 'id', dataType: server.utils.dataType.INTEGER, parameterType: server.utils.parameterType.PARAM, required: true, description: 'The id of the finded ' + singular.toLowerCase() } ], responses: { entity_element_not_found: server.defaultResponses.entity_element_not_found, entity_unable_get_element: server.defaultResponses.entity_unable_get_element, unauthorized: server.defaultResponses.unauthorized }, success: singleResponse, transactional: false, }; server.endpointmanager.addEndpoint(endpointConfiguration); }); } catch(err) { server.debug(err); throw err; } } function generatePostSingleEndpoint(currentDefinition, options, plural, singular){ try { const parameters = []; const attributeList = []; const fileList = []; const filterList = []; var singleResponse = {}; const attributes = Object.keys(currentDefinition['attributes']).sort(function(a, b) {return a.toLowerCase().localeCompare(b.toLowerCase())}); attributes.forEach(currentAttributeName => { var currentAttribute = currentDefinition['attributes'][currentAttributeName]; var currentAttributeName = currentAttribute.fieldName; var currentAttributeType = '' + currentAttribute.type; var dataType = server.utils.dataType.STRING; var description = ''; var currentAttributeIsFilter= currentAttribute.isFilter ? currentAttribute.isFilter : false; if(!currentAttribute._autoGenerated) { if(!_.isUndefined(currentAttribute.resource)) { parameters.push({ name: currentAttributeName, parameterType: server.utils.parameterType.FILE, required: !currentAttribute.allowNull, description: description }); fileList.push(currentAttribute); } else { if (currentAttributeType === 'INTEGER') { dataType = server.utils.dataType.INTEGER; } else if (currentAttributeType === 'FLOAT' || currentAttributeType === 'REAL' || currentAttributeType === 'DOUBLE' || currentAttributeType === 'DECIMAL') { dataType = server.utils.dataType.FLOAT; } else if (currentAttributeType === 'DATETIME' || currentAttributeType === 'DATE' || currentAttributeType === 'TIME' || currentAttributeType === 'DATEONLY') { dataType = server.utils.dataType.DATE; } else if (currentAttributeType === 'BOOLEAN') { dataType = server.utils.dataType.BOOLEAN; } if (currentAttribute.unique) { description += '(UNIQUE)'; } if (currentAttribute.references) { const referenceValue = currentAttribute.references; description += 'Key of the related ' + referenceValue.model + ' of the ' + singular; } parameters.push({ name: currentAttributeName, dataType: dataType, parameterType: server.utils.parameterType.BODY, required: !currentAttribute.allowNull, description: description }); attributeList.push(currentAttributeName); } } }); const endpointConfiguration = { name : !_.isUndefined(options.name) ? options.name : 'Create ' + singular, description : !_.isUndefined(options.description) ? options.description : 'This endpoint creates a ' + singular.toLowerCase() + ' in the database', route : '/' + plural.toLowerCase(), method : server.utils.method.POST, callback : !_.isUndefined(options.callback) ? options.callback : function (req, res, next, allowedResponses, transaction) { server.debug('Trying to create ' + singular.toLowerCase()); filterList.forEach(currentAttribute => { if(!server.utils.valueInList(req.currentSession.filters, currentAttribute)) { throw allowedResponses.unauthorized; } }); var assignations = {}; attributeList.forEach(currentAttribute => { if (req.body[currentAttribute]) { assignations[currentAttribute] = req.body[currentAttribute]; } if(server.utils.valueInList(req.currentSession.filters, currentAttribute)) { server.debug('AutoAssigning ' + currentAttribute + ' from Filters'); assignations[currentAttribute] = req.currentSession.filters[currentAttribute]; } }); fileList.forEach(currentFile => { var fieldName = currentFile.fieldName; if(!_.isUndefined(req.files) && req.files !== null && req.files[fieldName]) { var resourcePath = !_.isUndefined(currentFile.resource.path) ? currentFile.resource.path : ''; var fileName = +(new Date()); var fileNameParts = req.files[fieldName].name.split('.'); if (fileNameParts.length === 2) fileName += '.' + fileNameParts[1]; if (!_.isUndefined(currentFile.resource.saveInCloudStorage) && currentFile.resource.saveInCloudStorage === true && server.configuration.google.storage.enabled) { server.googlestorage.saveFile(resourcePath + '/' + fileName, req.files[fieldName].data, req.files[fieldName].mimetype); assignations[fieldName] = resourcePath + '/' + fileName; } else { assignations[fieldName] = server.fileSystem.saveResource(resourcePath, req.files[fieldName], fileName); } } }); return currentDefinition.create( assignations, { transaction: transaction }) .then(newElement => { server.socket.Emit(singular.toUpperCase() + server.socket.Events.EntityCreated, newElement); return { id: newElement.id }; }) .catch(err => { server.debug(err); throw allowedResponses.entity_unable_post_element; }); }, token : options.token, help : options.help, session : options.session, parameters : !_.isUndefined(options.parameters) ? options.parameters : parameters, responses : { missing_parameter : server.defaultResponses.missing_parameter, entity_unable_post_element : server.defaultResponses.entity_unable_post_element, invalid_parameter_data_type : server.defaultResponses.invalid_parameter_data_type, unauthorized : server.defaultResponses.unauthorized }, success : {id: 123}, transactional : true, }; server.endpointmanager.addEndpoint(endpointConfiguration); } catch(err) { server.debug(err); throw err; } } function generatePutSingleEndpoint(currentDefinition, options, plural, singular){ try { const parameters = [ { name: 'id', dataType: server.utils.dataType.INTEGER, parameterType: server.utils.parameterType.PARAM, required: true, description: 'The id of the finded ' + singular.toLowerCase() } ]; const attributeList = []; const filterList = []; const fileList = []; //var singleResponse = {}; const attributes = Object.keys(currentDefinition['attributes']).sort(function(a, b) {return a.toLowerCase().localeCompare(b.toLowerCase())}); attributes.forEach(currentAttributeName => { var currentAttribute = currentDefinition['attributes'][currentAttributeName]; var currentAttributeName = currentAttribute.fieldName; var currentAttributeType = '' + currentAttribute.type; var dataType = server.utils.dataType.STRING; var description = ''; var currentAttributeIsFilter= currentAttribute.isFilter ? currentAttribute.isFilter : false; if(!currentAttribute._autoGenerated) { if(!_.isUndefined(currentAttribute.resource)) { parameters.push({ name: currentAttributeName, parameterType: server.utils.parameterType.FILE, required: false, description: description }); fileList.push(currentAttribute); } else { if (currentAttributeType === 'INTEGER') { dataType = server.utils.dataType.INTEGER; } else if (currentAttributeType === 'FLOAT' || currentAttributeType === 'REAL' || currentAttributeType === 'DOUBLE' || currentAttributeType === 'DECIMAL') { dataType = server.utils.dataType.FLOAT; } else if (cu