diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..5171c54083337f0b87926da2e8f52abefe19d70f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..57a123473780458b523e29b006d60602a8e201f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +config.js +logs/ +*.swp diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..e3b21c3c4534e0dd1f265b7ecc56d1c7f083415a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM node:boron + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY package.json /usr/src/app/ +RUN npm install + +COPY . /usr/src/app + +EXPOSE 8080 +CMD [ "npm", "start" ] \ No newline at end of file diff --git a/config.js.example b/config.js.example new file mode 100644 index 0000000000000000000000000000000000000000..b2deb06c586c934a283170344e7321bf42f22b2e --- /dev/null +++ b/config.js.example @@ -0,0 +1,40 @@ +var config = module.exports = {}; + +config.db_config = { + user: 'user', + password: 'password', + database: 'dbname', + host: 'localhost', + port: 5432 +}; + +config.mail = { + port: 25 + , host: 'localhost' + , ignoreTLS: true + , secure: false + , from: 'noreply@simmc.c3sl.ufpr.br' +}; + +config.report_config = { + imagesPath: './reports/reports/images/' + , outputPath: './tmp/reports' +}; + +config.alert_config = { + alertsPath: '/home/simmc/simmc/scripts/alerts/' +}; + +config.fqdn = 'simmc.c3sl.ufpr.br'; + +config.agentVersion = 1.0; + +config.secret = '123mudar'; + +// Uncomment to enable memcached +// +// config.memcached = { +// server: 'localhost:11211', +// options: { retries: 1, timeout: 1000, poolSize: 1 }, +// lifetime: 3600 // 1 hour in seconds +// }; diff --git a/lib/agentbuilder.js b/lib/agentbuilder.js new file mode 100644 index 0000000000000000000000000000000000000000..24cb61e90f345951f3d2b660620fd9034952648a --- /dev/null +++ b/lib/agentbuilder.js @@ -0,0 +1,35 @@ +var exec = require('child_process').exec; + +exports.build = function(id_point, os, proxy, callback) { + var buildScript, + proxyParams = ""; + + if (isNaN(id_point)) { + return callback({error: 'invalid_id_point'}); + } + + if (os === 'windows') + buildScript = __dirname + '/../scripts/build-windows-installer.sh'; + else + buildScript = __dirname + '/../scripts/build-linux-installer.sh'; + + if (proxy) { + // the replace method removes whitespaces that are not allowed in this fields + var host = (proxy.host || '').replace(/ /g, ''), + port = (proxy.port || '').replace(/ /g, ''), + user = (proxy.user || '').replace(/ /g, ''), + pass = (proxy.pass || '').replace(/ /g, ''); + + // check if the port number is actually a number or an empty string + if ( (port !== '') && (isNaN(parseInt(port),10)) ) { + return callback({error: 'invalid_proxy_port'}); + } + + proxyParams = '"'+host+'" "'+port+'" "'+user+'" "'+pass+'"'; + } + + var cmdline = buildScript + ' ' + id_point + ' ' + proxyParams; + exec(cmdline, function (err, stdout, stderr) { + callback(err, stdout); + }); +}; \ No newline at end of file diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 0000000000000000000000000000000000000000..cfd4c5b0405e67c847723329a5be32b0cf421711 --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2012 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of simmc + * + * simmc is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + + +var os = require('os'); +var cluster = require('cluster'); +var bunyan = require('bunyan'); +var cuid = require('cuid'); +var fs = require('fs'); + +// Serialize a request (remove unuseful information from requests, +// log only the necessary). +function requestSerializer(req) { + if ((typeof(req) !== 'object') || (req === null)) { + return req; + } + + var headers = req.headers || {}; + + return { + method: req.method, + url: req.url, + headers: { // selective choice of headers (no cookies) + "host": headers["host"], + "connection": headers["connection"], + "cache-control": headers["cache-control"], + "accept": headers["accept"], + "user-agent": headers["user-agent"], + "referer": headers["referer"], + "accept-encoding": headers["accept-encoding"], + "accept-language": headers["accept-language"] + }, + remoteAddress: req.ips[0] || req.ip || null + }; +} + +// Serialize a reponse (remove unuseful information from responses +// and calculate the reponse time). +function responseSerializer(res) { + if ((typeof(res) !== 'object') || (res === null)) { + return res; + } + + // Calculate the response time + var responseTime; + if (res.start) { + responseTime = (new Date() - res.start).toString() + " ms"; + } + + return { + statusCode: res.statusCode, + responseTime: responseTime + } +} + +// Make sure the logs dir exist +try { + fs.mkdirSync('logs'); +} +catch (e) { + if ( e.code != 'EEXIST' ) + throw e; +} + +// Create the default logger +var defaultLogger = bunyan.createLogger({ + name: 'default', + streams: [{ + level: "info", + type: 'file', + path: 'logs/default.log', + }, + { + level: "debug", + type: 'file', + path: 'logs/debug.log', + }], + serializers: { + req: requestSerializer, + res: responseSerializer + } +}); +if (!cluster.isMaster) { + defaultLogger = defaultLogger.child({ worker: cluster.worker.id }); +} + +// Export the default logger +exports.default = defaultLogger; + +// Export the access logger (log express requests) +exports.expressAccess = function (req, res, next) { + // insert the current time into the response + // (for later calculation of reponse time). + res.start = new Date(); + + // Insert a log object into the request. + // The routes can use this object to log messages and all + // of them can be traced to the request (by req_id). + req.log = defaultLogger.child({ req_id: cuid.slug() }); + + // Log the request + req.log.debug({req: req}, 'request'); + + // Continue to the next handler + next(); + + // Log the response + req.log.debug({res: res}, 'response'); +} + +// Export the express error logger (log errors during request processing) +exports.expressError = function (err, req, res, next) { + if (err) { + defaultLogger.error({err: err}, 'Error while processing request'); + } + + next(); +} diff --git a/lib/mail.js b/lib/mail.js new file mode 100644 index 0000000000000000000000000000000000000000..602c5cd3513833eba09ec440ec80d4f8bff91d15 --- /dev/null +++ b/lib/mail.js @@ -0,0 +1,37 @@ +var nodemailer = require('nodemailer'); +var smtpTransport = require('nodemailer-smtp-transport'); +var htmlToText = require('nodemailer-html-to-text').htmlToText; + +module.exports = function(config) { + + var options = smtpTransport({ + port: config.port + , host: config.host + , ignoreTLS: config.ignoreTLS + , secure: config.secure + }); + + // create reusable transporter object using SMTP transport + var transporter = nodemailer.createTransport(options); + + // set transporter to compile html do text automagically + transporter.use('compile', htmlToText()); + + // NB! No need to recreate the transporter object. You can use + // the same transporter object for all e-mails + + // setup e-mail data with unicode symbols + var mail = { + from: config.from // sender address + }; + + return { + send: function(to, subject, html, callback) { + // send mail with defined transport object + mail.to = to; + mail.subject = subject; + mail.html = html; + transporter.sendMail(mail, callback); + } + }; +}; diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..59659ae08a646bbcee61be69624b68bb635c22d6 --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of simmc + * + * simmc is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +var crypto = require('crypto'); + +// Returns a filename starting with prefix (if not null) plus a md5-hash +// representing the obj given as argument, with "ext" as extension. +exports.hashFilename = function(prefix, obj, ext) { + var txt = ""; + for (i in obj) { + txt += i + obj[i] + } + var hash = crypto.createHash('md5').update(txt).digest('hex'); + return (prefix? prefix + '_' + hash : hash) + '.' + ext; +}; + +// returns a filename in the format: type project_date(day+month+year+'_'+hours+minutes).ext +exports.reportFilename = function(prefix, ext) { + var date = formatDateReport(new Date()); + return prefix+ '_'+ date + '.' + ext; +}; + +// returns the date in the format day+month+year_hours+minutes +function formatDateReport(date) { + var day = date.getUTCDate(), + month = date.getUTCMonth() + 1, //Months are zero based + year = date.getUTCFullYear(), + hours = date.getHours(), + minutes = date.getMinutes(); + + if (day < 10) day = '0' + day; + if (month < 10) month = '0' + month; + if (hours < 10) hours = '0' + hours; + if (minutes < 10) minutes = '0' + minutes; + + return day + month + year + '_' + hours + minutes; +} + + +// returns the sum of every element in a array or object +exports.sum = function(x) { + var total = 0; + if (x.constructor == Array) { + for (var i=0; i<x.length; i++) { + total += x[i]; + } + } else { + for (var i in x) { + total += x[i]; + } + } + return total; +} + +exports.checkEmail = function(email) { + if (email.length < 4) { + return "Email deve conter pelo menos 4 caracteres."; + } + + if (email.length > 255) { + return "Email deve conter no máximo 255 caracteres."; + } + + if (!email.match(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/)) { + return "Email não está em um formato válido."; + } + + return false; +} diff --git a/middleware/cache.js b/middleware/cache.js new file mode 100644 index 0000000000000000000000000000000000000000..e8809908bdef74f85be346443811411dee8ec1d9 --- /dev/null +++ b/middleware/cache.js @@ -0,0 +1,37 @@ +module.exports = function (config) { + var memcached = null; + if (config) { // require memcached module only if configured + var Memcached = require('memcached'); + memcached = new Memcached(config.server || 'localhost:11211', config.options || {}); + } + + return { + try: function (req, res, next) { + if (!memcached) { // memcached not configured + next(); + return; + } + + memcached.get(req.url, function (err, data) { + if (err) { + console.log('Memcached error:\n'); + console.log(err); + next(); + } + else if (data) { + if (config.debug) console.log('cached response to '+req.url); + res.status(200).send(data); + } + else { + // provide a method for the route to cache its response + res.cache = function (data, cb) { + if (config.debug) console.log('caching '+req.url); + memcached.set(req.url, data, config.lifetime || 3600, cb || function (err) {}); + } + + next(); + } + }); + } + }; +}; diff --git a/middleware/db.js b/middleware/db.js new file mode 100644 index 0000000000000000000000000000000000000000..5f70a2707bd68ba8dc036bc043f5d9c9858d8bd3 --- /dev/null +++ b/middleware/db.js @@ -0,0 +1,168 @@ +var pg = require('pg'), + copyFrom = require('pg-copy-streams').from, + fs = require('fs'), + _ = require('lodash'); + +var tokenPattern = /\$[a-zA-Z]([a-zA-Z0-9_]*)\b/g; + +function numericFromNamed(sql, parameters) { + var fillableTokens = Object.keys(parameters); + + var matchedTokens = _.uniq(_.map(sql.match(tokenPattern), function (token) { + return token.substring(1); // Remove leading dollar sign + })); + + var fillTokens = _.intersection(fillableTokens, matchedTokens).sort(); + var fillValues = _.map(fillTokens, function (token) { + return parameters[token]; + }); + + var unmatchedTokens = _.difference(matchedTokens, fillableTokens); + + if (unmatchedTokens.length) { + var missing = unmatchedTokens.join(", "); + throw new Error("Missing Parameters: " + missing); + } + + var interpolatedSql = _.reduce(fillTokens, function (partiallyInterpolated, token, index) { + var replaceAllPattern = new RegExp('\\$' + fillTokens[index] + '\\b', "g"); + return partiallyInterpolated.replace(replaceAllPattern, '$' + (index+1)); + }, sql); + + var out = {}; + out.sql = interpolatedSql; + out.values = fillValues; + + return out; +} + +function namedPatch(client) { + var originalQuery = client.query; + + if (originalQuery.patched) return client; + + originalQuery = originalQuery.bind(client); + + var patchedQuery = function(config, values, callback) { + if (arguments.length === 1) { + return originalQuery(config); + } + else if (arguments.length === 2 && _.isFunction(values)) { + return originalQuery(config, values); + } + else if (_.isArray(values)) { + return originalQuery(config, values, callback); + } else { + var reparameterized = numericFromNamed(config, values); + return originalQuery(reparameterized.sql, reparameterized.values, callback); + } + }; + + client.query = patchedQuery; + client.query.patched = true; + + return client; +} + +exports.pool = function (config) { + return function (req, res, next) { + req.db = { + connect: function (callback) { + pg.on('error', function(err) { + return; + }); + pg.connect(config, function (err, client, done) { + if (err) { + setTimeout(req.db.connect, 5000, callback); + return; + } + + namedPatch(client); + callback(null, new Connection(client), done); + }); + } + }; + + next(); + }; +}; + +function Connection(client) { + this.query = function (query, params, callback) { + return client.query(query, params, callback); + }; + + this.execute = function (query, params) { + var $this = this; + + return function (callback) { + $this.query(query, params, function (err) { + callback(err); + }); + }; + }; + + this.queryFromFile = function(file, params, callback) { + var queries_dir = __dirname + "/../queries/"; + + fs.readFile(queries_dir + file, 'utf8', function (err, data) { + if (err) { + return callback(err); + } + + if (typeof params === 'undefined') { + params = []; + } + + client.query(data, params, callback); + }); + }; + + this.executeFromFile = function(file, params) { + var $this = this; + + return function (callback) { + $this.queryFromFile(file, params, function (err) { + callback(err); + }); + }; + }; + + this.copyFrom = function (query, callback) { + var stream = client.query(copyFrom(query)); + stream.on('end', callback); + stream.on('error', callback); + return stream; + }; + + this.transaction = function (callback) { + client.query('BEGIN;', function (err) { + callback(err); + }); + }; + + this.commit = function (callback) { + client.query('COMMIT;', function (err) { + callback(err); + }); + }; + + this.rollback = function (callback) { + client.query('ROLLBACK;', function (err) { + callback(err); + }); + }; + + this.auth = function (user, ip, action, comment) { + return function (callback) { + if (!(user && user.id)) + return callback('not_logged_in'); + + client.query('SELECT auth.user_action($1, $2, $3, $4);', + [user.id, ip, action, comment], + function (err) { + callback(err); + }); + }; + }; +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..cacdd20788a057d68cb3d94fc52698dae4fe108a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,480 @@ +{ + "name": "webservice-pinsis", + "version": "0.0.0", + "lockfileVersion": 1, + "dependencies": { + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=" + }, + "ap": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ap/-/ap-0.2.0.tgz", + "integrity": "sha1-rglCYAspkS8NKxTsYMRejzMLYRA=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true + }, + "body-parser": { + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", + "integrity": "sha1-+IkqvI+eYn1Crtr7yma/WrmRBO4=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "optional": true + }, + "browser-fingerprint": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/browser-fingerprint/-/browser-fingerprint-0.0.1.tgz", + "integrity": "sha1-jfPNyiW/fVs1QtYVRdcwBT/OYEo=" + }, + "buffer-writer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", + "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" + }, + "bunyan": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.10.tgz", + "integrity": "sha1-IB/t0mxwgLYy9BYHL1OpC5pSmBw=" + }, + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "cuid": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/cuid/-/cuid-1.3.8.tgz", + "integrity": "sha1-S4deCWm612T37AcGz0T1+wgx9rc=" + }, + "debug": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=" + }, + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "dtrace-provider": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.3.tgz", + "integrity": "sha1-uhv8ZJMoXM/PxqtpzVxh10wqQ78=", + "optional": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", + "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=" + }, + "express": { + "version": "4.15.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", + "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=" + }, + "finalhandler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", + "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=" + }, + "forwarded": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=" + }, + "fresh": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", + "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=" + }, + "generic-pool": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz", + "integrity": "sha1-eAw29p360FpaBF3Te+etyhGk9v8=" + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "optional": true + }, + "http-errors": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", + "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=" + }, + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", + "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "optional": true + } + } + }, + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", + "optional": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "optional": true + }, + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=", + "optional": true + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "optional": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "node-fingerprint": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/node-fingerprint/-/node-fingerprint-0.0.2.tgz", + "integrity": "sha1-Mcur63GmeufdWn3AQuUcPHWGhQE=" + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "pg": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-6.4.0.tgz", + "integrity": "sha1-y3a6Lnwuq4n8ZL96n+ZIztckNtw=" + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" + }, + "pg-copy-streams": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pg-copy-streams/-/pg-copy-streams-1.2.0.tgz", + "integrity": "sha1-ez+d7gtsX8IGj1nED6IY4MHXQkk=" + }, + "pg-pool": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz", + "integrity": "sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=" + }, + "pg-types": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.0.tgz", + "integrity": "sha1-itO3uJfj/UY+Yt4kGtX8ZAtKZvA=" + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=" + }, + "postgres-array": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz", + "integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=" + }, + "postgres-interval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.0.tgz", + "integrity": "sha1-EDHnusNFZBMoYq3J62xtLzqnW7Q=" + }, + "proxy-addr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", + "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM=" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "integrity": "sha1-mUl2z2pQlqQRYoQEkvC9xdbn+5Y=" + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "optional": true + }, + "safe-json-stringify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz", + "integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=", + "optional": true + }, + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + }, + "send": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", + "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk=" + }, + "serve-static": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", + "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI=" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + }, + "split": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.0.tgz", + "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + }, + "vary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", + "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000000000000000000000000000000000..38d2e9f5cfdfbac4453bf90536576dc1c0cb907c --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "webservice-pinsis", + "version": "0.0.0", + "description": "Webservice para receber dados do agente PInSIS", + "author": "Davisson Paulino <dhpaulino@gmail.com>", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.13.3", + "async": "^2.1.2", + "body-parser": "^1.14.1", + "pg": "^6.1.0", + "pg-copy-streams": "^1.2.0", + "minimist": "1.2.0", + "cuid": "^1.2.4", + "bunyan": "^1.0.1" + } +} diff --git a/routes/agent.js b/routes/agent.js new file mode 100644 index 0000000000000000000000000000000000000000..9b2560cf2c5623058403e8b927b64f0287854f82 --- /dev/null +++ b/routes/agent.js @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2012-2017 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of simmc + * + * simmc is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +var async = require('async'); + +function isSubSet (array1, array2) { + return array1.every(function(item1) { + return array2.some(function(item2) { + return item1 == item2; + }); + }); +} + +function dateFormat (date) { + + if (!date) { + return null; + } + + return date.getFullYear() + '-' + + ("0" + (date.getMonth() + 1)).slice(-2) + '-' + + ("0" + date.getDate()).slice(-2); +} + +function timeFormat (date) { + + if (!date) { + return null; + } + + return ("0" + date.getHours()).slice(-2) + ':' + + ("0" + date.getMinutes()).slice(-2) + ':' + + ("0" + date.getSeconds()).slice(-2); +} + +var routes = { + /*"net_usage": { + validation: function(body) { + if(!body) { + return false; + } + else { + var keys = [ + 'id_point', + 'mac_address', + 'bytes_recived', + 'bytes_transmited', + 'collect_time', + 'packets_recived', + 'packets_transmited', + ]; + return isSubSet(Object.keys(body), keys); + } + }, + parser: function(body) { + return [ + dateFormat(new Date()), + body.id_point, + body.mac_address, + dateFormat(body.collect_time), + timeFormat(body.collect_time), + body.bytes_recived, + body.packets_recived, + body.bytes_transmited, + body.packets_transmited, + ]; + }, + query: 'collect/net_usage.sql' + }*/ +}; + +module.exports = function(agentVersion) { + return { + collect: function(req, res) { + var route = routes[req.params.type]; + if(!route) { + return res.status(400).json({error: 'invalid_parameter'}); + } + if(route.validation(req.body)) { + var data = route.parser(req.body); + req.db.connect(function(err, conn, done) { + if (err) { + req.log.error(err); + res.status(500).json({error: 'db_connection_failed'}); + return; + } + async.waterfall([ + conn.transaction, + function(callback) { + conn.queryFromFile(route.query, data, callback); + }, + conn.commit + ], function (err, result) { + if(err) { + req.log.error(err); + res.staus(500).json({error: 'db_query_failed'}); + conn.rollback(done); + return; + } + res.status(200).json({}); + done(); + }); + }); + } + else { + return res.status(400).json({error: 'invalid_body'}); + } + }, + version : function (req, res) { + return res.status(200).json({version: agentVersion}); + } + }; +}; diff --git a/routes/ping.js b/routes/ping.js new file mode 100644 index 0000000000000000000000000000000000000000..4bbeec42f4d3961d2214d40da10b5f3dfaad60e8 --- /dev/null +++ b/routes/ping.js @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of simmc + * + * simmc is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +exports.get = function (req, res) { + req.db.connect(function (err, conn, done) { + done(err); + if (err) { + res.status(200).json({ message: 'db_connection_failed' }); + return; + } + res.status(200).json({ message: 'Pong' }); + return; + }); +}; diff --git a/server.js b/server.js new file mode 100644 index 0000000000000000000000000000000000000000..a0cb67db8f602d6fd7bd13579779f413422457de --- /dev/null +++ b/server.js @@ -0,0 +1,203 @@ +#!/usr/bin/env node +/* + * Copyright (C) 2012 Centro de Computacao Cientifica e Software Livre + * Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + * + * This file is part of simmc + * + * simmc is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +// +// Libraries +// +var os = require('os'); +var fs = require('fs'); +var cluster = require('cluster'); +var bodyParser = require('body-parser'); +var express = require('express'); +var minimist = require('minimist'); +var path = require('path'); +var exec = require('child_process').execFile; + +// +// Parse command line arguments +// +var argv = minimist(process.argv.slice(2)); +if (argv.help || argv.h) { + console.log('Usage: server.js [OPTION]...'); + console.log(''); + console.log('Where OPTION can be:'); + console.log(' -c, --config alternative configuration file (default: config.js)'); + console.log(' -p, --port port where the server will listen to'); + console.log(' --insecure allows session cookies to be passed around in'); + console.log(' in insecure connections'); + console.log(' --dev force development mode'); + console.log(' -n, --num-workers number of worker processes to spawn'); + console.log(' -d, --daemon start the server as a daemon'); + console.log(' --pid-file path for the pid file when running as a daemon'); + console.log(' -h, --help show this help and exit'); + return 0; +} + +var configFile = argv.config || argv.c || 'config.js'; +var config; +try { + config = require(path.resolve('.', configFile)); +} +catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + console.error('Missing configuration file ('+configFile+')!'); + console.error('Perhaps you need to create it using:'); + console.error(' $ cp config.example.js '+configFile); + console.error(''); + return 1; + } + else { + console.error('Error while parsing configuration file ('+configFile+')!'); + console.error(''); + console.error(e.stack); + return 2; + } +} + +var devMode = argv.dev || (process.env.NODE_ENV && (process.env.NODE_ENV.slice(0,3) === 'dev')); +var port = parseInt(argv.port || argv.p || process.env.PORT) || 3000; +var secureCookies = !argv.insecure; +var numWorkers = parseInt(argv['num-workers'] || argv.n) || (os.cpus().length * 2); +var daemon = argv.daemon || argv.d || false; +var pidfile = argv['pid-file'] || config.pid_file || process.env.PID_FILE || path.resolve('.', 'simmc.pid'); + +if (devMode) { + secureCookies = false; + + // Limit to only 1 worker in dev mode because sessions stored + // in memory are not shared between processes. + // In dev mode memcached is probably not configure therefore + // session storage falls back to memory resulting in sessions + // not persisting. + numWorkers = 1; +} + +// +// Setup logger +// +var logger = require('./lib/logger.js'); +var log = logger.default; + + +// +// Fork process +// +if (cluster.isMaster) { + // daemonize the process (useful for init.d scripts and similar) + if (argv.daemon) { + require('daemon')(); + fs.writeFileSync(pidfile, process.pid+"\n"); + } + + log.info('Starting server in '+ (devMode ? 'development' : 'production') + + ' mode, spawning ' + numWorkers + ' workers'); + + for (var i = 0; i < numWorkers; i++) { + cluster.fork(); + } + + + cluster.on('exit', function(worker, code, signal) { + if (code || signal) { + log.error('Worker %d has ended (%s,%s).', worker.id, code, signal); + } else { + log.fatal('Worker %d has died. Restarting it...', worker.id); + cluster.fork(); + } + }); + + function exit() { + log.info('Server exiting...'); + + process.exit(0); + } + + process.on('SIGTERM', exit); + process.on('SIGHUP', exit); + process.on('SIGINT', exit); +} +else { + // + // Middlewares + // + + var db = require('./middleware/db.js'); + var utils = require('./lib/utils.js'); + + // + // Routes + // + + var ping = require('./routes/ping.js'); + var agent = require('./routes/agent.js')(config.agentVersion); + + + // + // Setup express app + // + var app = express(); + app.use(logger.expressAccess); + app.use(logger.expressError); + app.use(bodyParser.json()); + app.use(bodyParser.urlencoded({extended: true})); + + + + app.use(db.pool(config.db_config)); + + + + // acquire user id and ip address + app.use(function (req, res, next) { + req.ip = req.ips[0] || req.ip || null; + next(); + }); + + + + + + // + // Setup routes + // + + app.get('/api/ping', ping.get); + + app.post('/api/agent/collect/:type(inventory|net_usage)', agent.collect); + app.get('/api/agent/version', agent.version); + + // + // Listen for incoming connections + // + if (!module.parent) { + // Only enter the listen loop if the script is executed directly + // (like: node server.js, not imported by another script). This check + // is useful for running automated tests which don't work if this + // module is "stuck" on listen loop. + + log.info('Ready'); + console.log('Worker '+cluster.worker.id+' listening...'); + + app.listen(port); + } +}