Removing ng-di on the server.
This commit is contained in:
parent
ddb2f47a9d
commit
8697d79ba5
|
@ -33,7 +33,6 @@
|
|||
"lodash": "^4.17.11",
|
||||
"moment": "^2.22.2",
|
||||
"ng-admin": "^1.0.13",
|
||||
"ng-di": "^0.2.1",
|
||||
"node-cron": "^2.0.1",
|
||||
"nodemailer": "^4.6.8",
|
||||
"nodemailer-html-to-text": "^3.0.0",
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('app', function (fs, config, _) {
|
||||
var express = require('express');
|
||||
var auth = require('http-auth');
|
||||
var bodyParser = require('body-parser');
|
||||
var compress = require('compression');
|
||||
const _ = require('lodash')
|
||||
const auth = require('http-auth');
|
||||
const bodyParser = require('body-parser');
|
||||
const compress = require('compression');
|
||||
const express = require('express');
|
||||
const fs = require('graceful-fs')
|
||||
|
||||
var app = express();
|
||||
var router = express.Router();
|
||||
const config = require('./config').config
|
||||
|
||||
const app = express();
|
||||
|
||||
module.exports = (() => {
|
||||
const router = express.Router();
|
||||
|
||||
// urls beneath /internal are protected
|
||||
var internalAuth = auth.basic(
|
||||
const internalAuth = auth.basic(
|
||||
{
|
||||
realm: 'Knotenformular - Intern'
|
||||
},
|
||||
|
@ -27,11 +32,11 @@ angular.module('ffffng').factory('app', function (fs, config, _) {
|
|||
router.use(bodyParser.json());
|
||||
router.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
var adminDir = __dirname + '/../admin';
|
||||
var clientDir = __dirname + '/../client';
|
||||
var templateDir = __dirname + '/templates';
|
||||
const adminDir = __dirname + '/../admin';
|
||||
const clientDir = __dirname + '/../client';
|
||||
const templateDir = __dirname + '/templates';
|
||||
|
||||
var jsTemplateFiles = [
|
||||
const jsTemplateFiles = [
|
||||
'/config.js'
|
||||
];
|
||||
|
||||
|
@ -63,4 +68,4 @@ angular.module('ffffng').factory('app', function (fs, config, _) {
|
|||
app.use(config.server.rootPath, router);
|
||||
|
||||
return app;
|
||||
});
|
||||
})()
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
var commandLineArgs = require('command-line-args');
|
||||
var commandLineUsage = require('command-line-usage');
|
||||
module.exports = (() => {
|
||||
const commandLineArgs = require('command-line-args');
|
||||
const commandLineUsage = require('command-line-usage');
|
||||
|
||||
var commandLineDefs = [
|
||||
const commandLineDefs = [
|
||||
{ name: 'help', alias: 'h', type: Boolean, description: 'Show this help' },
|
||||
{ name: 'config', alias: 'c', type: String, description: 'Location of config.json' },
|
||||
{ name: 'version', alias: 'v', type: Boolean, description: 'Show ffffng version' }
|
||||
];
|
||||
|
||||
var commandLineOptions;
|
||||
let commandLineOptions;
|
||||
try {
|
||||
commandLineOptions = commandLineArgs(commandLineDefs);
|
||||
} catch (e) {
|
||||
|
@ -18,10 +19,10 @@ try {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
var fs = require('graceful-fs');
|
||||
const fs = require('graceful-fs');
|
||||
|
||||
var packageJsonFile = __dirname + '/../package.json';
|
||||
var version = 'unknown';
|
||||
const packageJsonFile = __dirname + '/../package.json';
|
||||
let version = 'unknown';
|
||||
if (fs.existsSync(packageJsonFile)) {
|
||||
version = JSON.parse(fs.readFileSync(packageJsonFile, 'utf8')).version;
|
||||
}
|
||||
|
@ -50,9 +51,9 @@ if (!commandLineOptions.config) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
var deepExtend = require('deep-extend');
|
||||
const deepExtend = require('deep-extend');
|
||||
|
||||
var defaultConfig = {
|
||||
const defaultConfig = {
|
||||
server: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
port: 8080,
|
||||
|
@ -122,8 +123,8 @@ var defaultConfig = {
|
|||
}
|
||||
};
|
||||
|
||||
var configJSONFile = commandLineOptions.config;
|
||||
var configJSON = {};
|
||||
const configJSONFile = commandLineOptions.config;
|
||||
let configJSON = {};
|
||||
|
||||
if (fs.existsSync(configJSONFile)) {
|
||||
configJSON = JSON.parse(fs.readFileSync(configJSONFile, 'utf8'));
|
||||
|
@ -132,25 +133,26 @@ if (fs.existsSync(configJSONFile)) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
var _ = require('lodash');
|
||||
const _ = require('lodash');
|
||||
|
||||
function stripTrailingSlash (obj, field) {
|
||||
var url = obj[field];
|
||||
const url = obj[field];
|
||||
if (_.isString(url) && _.last(url) === '/') {
|
||||
obj[field] = url.substr(0, url.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
var config = deepExtend({}, defaultConfig, configJSON);
|
||||
const config = deepExtend({}, defaultConfig, configJSON);
|
||||
|
||||
stripTrailingSlash(config.server, 'baseUrl');
|
||||
stripTrailingSlash(config.client.map, 'mapUrl');
|
||||
|
||||
var url = require('url');
|
||||
const url = require('url');
|
||||
config.server.rootPath = url.parse(config.server.baseUrl).pathname;
|
||||
config.client.rootPath = config.server.rootPath;
|
||||
|
||||
module.exports = config;
|
||||
|
||||
angular.module('ffffng').constant('config', config);
|
||||
angular.module('ffffng').constant('version', version);
|
||||
return {
|
||||
config,
|
||||
version
|
||||
}
|
||||
})()
|
||||
|
|
|
@ -5,7 +5,7 @@ const fs = require('graceful-fs');
|
|||
const glob = util.promisify(require('glob'));
|
||||
const path = require('path');
|
||||
|
||||
const config = require('../config');
|
||||
const config = require('../config').config;
|
||||
const Logger = require('../logger');
|
||||
|
||||
async function applyPatch(db, file) {
|
||||
|
@ -72,10 +72,7 @@ async function init() {
|
|||
throw error;
|
||||
}
|
||||
|
||||
// WARNING: We have to use funtion() syntax here, to satisfy ng-di. m(
|
||||
return angular.module('ffffng').factory('Database', function () {
|
||||
return db;
|
||||
});
|
||||
module.exports.db = db;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
18
server/jobs/FixNodeFilenamesJob.js
Normal file
18
server/jobs/FixNodeFilenamesJob.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const Logger = require('../logger')
|
||||
const NodeService = require('../services/nodeService')
|
||||
|
||||
module.exports = {
|
||||
description: 'Makes sure node files (holding fastd key, name, etc.) are correctly named.',
|
||||
|
||||
run: function (callback) {
|
||||
NodeService.fixNodeFilenames(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('nodes', 'fix-filenames').error('Error fixing filenames:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
18
server/jobs/MailQueueJob.js
Normal file
18
server/jobs/MailQueueJob.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const Logger = require('../logger')
|
||||
const MailService = require('../services/mailService')
|
||||
|
||||
module.exports = {
|
||||
description: 'Send pending emails (up to 5 attempts in case of failures).',
|
||||
|
||||
run: function (callback) {
|
||||
MailService.sendPendingMails(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('mail', 'queue').error('Error sending pending mails:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
18
server/jobs/MonitoringMailsSendingJob.js
Normal file
18
server/jobs/MonitoringMailsSendingJob.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const Logger = require('../logger')
|
||||
const MonitoringService = require('../services/monitoringService')
|
||||
|
||||
module.exports = {
|
||||
description: 'Sends monitoring emails depending on the monitoring state of nodes retrieved by the NodeInformationRetrievalJob.',
|
||||
|
||||
run: function (callback) {
|
||||
MonitoringService.sendMonitoringMails(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('monitoring', 'mail-sending').error('Error sending monitoring mails:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
18
server/jobs/NodeInformationRetrievalJob.js
Normal file
18
server/jobs/NodeInformationRetrievalJob.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const Logger = require('../logger')
|
||||
const MonitoringService = require('../services/monitoringService')
|
||||
|
||||
module.exports = {
|
||||
description: 'Fetches the nodes.json and calculates and stores the monitoring / online status for registered nodes.',
|
||||
|
||||
run: function (callback) {
|
||||
MonitoringService.retrieveNodeInformation(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('monitoring', 'information-retrieval').error('Error retrieving node data:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
18
server/jobs/OfflineNodesDeletionJob.js
Normal file
18
server/jobs/OfflineNodesDeletionJob.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const Logger = require('../logger')
|
||||
const MonitoringService = require('../services/monitoringService')
|
||||
|
||||
module.exports = {
|
||||
description: 'Delete nodes that are offline for more than 100 days.',
|
||||
|
||||
run: function (callback) {
|
||||
MonitoringService.deleteOfflineNodes(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('nodes', 'delete-offline').error('Error deleting offline nodes:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('FixNodeFilenamesJob', function (NodeService, Logger) {
|
||||
return {
|
||||
description: 'Makes sure node files (holding fastd key, name, etc.) are correctly named.',
|
||||
|
||||
run: function (callback) {
|
||||
NodeService.fixNodeFilenames(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('nodes', 'fix-filenames').error('Error fixing filenames:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('MailQueueJob', function (MailService, Logger) {
|
||||
return {
|
||||
description: 'Send pending emails (up to 5 attempts in case of failures).',
|
||||
|
||||
run: function (callback) {
|
||||
MailService.sendPendingMails(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('mail', 'queue').error('Error sending pending mails:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('MonitoringMailsSendingJob', function (MonitoringService, Logger) {
|
||||
return {
|
||||
description: 'Sends monitoring emails depending on the monitoring state of nodes retrieved by the NodeInformationRetrievalJob.',
|
||||
|
||||
run: function (callback) {
|
||||
MonitoringService.sendMonitoringMails(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('monitoring', 'mail-sending').error('Error sending monitoring mails:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('NodeInformationRetrievalJob', function (MonitoringService, Logger) {
|
||||
return {
|
||||
description: 'Fetches the nodes.json and calculates and stores the monitoring / online status for registered nodes.',
|
||||
|
||||
run: function (callback) {
|
||||
MonitoringService.retrieveNodeInformation(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('monitoring', 'information-retrieval').error('Error retrieving node data:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('OfflineNodesDeletionJob', function (MonitoringService, Logger) {
|
||||
return {
|
||||
description: 'Delete nodes that are offline for more than 100 days.',
|
||||
|
||||
run: function (callback) {
|
||||
MonitoringService.deleteOfflineNodes(function (err) {
|
||||
if (err) {
|
||||
Logger.tag('nodes', 'delete-offline').error('Error deleting offline nodes:', err);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,21 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
var glob = require('glob');
|
||||
var _ = require('lodash');
|
||||
const _ = require('lodash');
|
||||
const cron = require('node-cron');
|
||||
const glob = require('glob');
|
||||
const moment = require('moment');
|
||||
|
||||
var jobFiles = glob.sync(__dirname + '/*Job.js');
|
||||
const config = require('../config').config
|
||||
const Logger = require('../logger')
|
||||
|
||||
const jobFiles = glob.sync(__dirname + '/*Job.js');
|
||||
_.each(jobFiles, function (jobFile) {
|
||||
require(jobFile);
|
||||
});
|
||||
|
||||
angular.module('ffffng').factory('Scheduler', function ($injector, Logger, config, moment) {
|
||||
var cron = require('node-cron');
|
||||
const tasks = {};
|
||||
|
||||
var tasks = {};
|
||||
|
||||
var taskId = 1;
|
||||
let taskId = 1;
|
||||
function nextTaskId() {
|
||||
var id = taskId;
|
||||
const id = taskId;
|
||||
taskId += 1;
|
||||
return id;
|
||||
}
|
||||
|
@ -23,7 +25,7 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi
|
|||
function schedule(expr, jobName) {
|
||||
Logger.tag('jobs').info('Scheduling job: %s %s', expr, jobName);
|
||||
|
||||
var job = $injector.get(jobName);
|
||||
var job = require(`../jobs/${jobName}`);
|
||||
|
||||
if (!_.isFunction(job.run)) {
|
||||
throw new Error('The job ' + jobName + ' does not provide a "run" function.');
|
||||
|
@ -69,7 +71,7 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi
|
|||
tasks['' + id] = task;
|
||||
}
|
||||
|
||||
return {
|
||||
module.exports = {
|
||||
init: function () {
|
||||
Logger.tag('jobs').info('Scheduling background jobs...');
|
||||
|
||||
|
@ -94,5 +96,4 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi
|
|||
getTasks: function () {
|
||||
return tasks;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
(function () {
|
||||
var module = angular.module('ffffng');
|
||||
|
||||
function lib(name, nodeModule) {
|
||||
if (!nodeModule) {
|
||||
nodeModule = name;
|
||||
}
|
||||
|
||||
module.factory(name, function () {
|
||||
return require(nodeModule);
|
||||
});
|
||||
}
|
||||
|
||||
lib('_', 'lodash');
|
||||
lib('async');
|
||||
lib('crypto');
|
||||
lib('deepExtend', 'deep-extend');
|
||||
lib('fs', 'graceful-fs');
|
||||
lib('glob');
|
||||
lib('moment');
|
||||
lib('request');
|
||||
})();
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
const app = require('./app');
|
||||
const config = require('./config').config;
|
||||
|
||||
// Hack to allow proper logging of Error.
|
||||
Object.defineProperty(Error.prototype, 'message', {
|
||||
|
@ -14,7 +14,7 @@ Object.defineProperty(Error.prototype, 'stack', {
|
|||
});
|
||||
|
||||
|
||||
var scribe = require('scribe-js')({
|
||||
const scribe = require('scribe-js')({
|
||||
rootPath: config.server.logging.directory,
|
||||
});
|
||||
|
||||
|
@ -33,12 +33,11 @@ function addLogger(name, color, active) {
|
|||
addLogger('debug', 'grey', config.server.logging.debug);
|
||||
addLogger('profile', 'blue', config.server.logging.profile);
|
||||
|
||||
angular.module('ffffng').factory('Logger', function (app) {
|
||||
if (config.server.logging.logRequests) {
|
||||
app.use(scribe.express.logger());
|
||||
}
|
||||
if (config.server.internal.active) {
|
||||
var prefix = config.server.rootPath === '/' ? '' : config.server.rootPath;
|
||||
const prefix = config.server.rootPath === '/' ? '' : config.server.rootPath;
|
||||
app.use(prefix + '/internal/logs', scribe.webPanel());
|
||||
}
|
||||
|
||||
|
@ -47,8 +46,8 @@ angular.module('ffffng').factory('Logger', function (app) {
|
|||
Object.defineProperty(Error.prototype, 'toJSON', {
|
||||
configurable: true,
|
||||
value: function () {
|
||||
var alt = {};
|
||||
var storeKey = function (key) {
|
||||
const alt = {};
|
||||
const storeKey = function (key) {
|
||||
alt[key] = this[key];
|
||||
};
|
||||
Object.getOwnPropertyNames(this).forEach(storeKey, this);
|
||||
|
@ -56,7 +55,4 @@ angular.module('ffffng').factory('Logger', function (app) {
|
|||
}
|
||||
});
|
||||
|
||||
return process.console;
|
||||
});
|
||||
|
||||
module.exports = process.console;
|
||||
|
|
|
@ -2,11 +2,6 @@
|
|||
/*jslint node: true */
|
||||
'use strict';
|
||||
|
||||
// Dirty hack to allow usage of angular modules.
|
||||
global.angular = require('ng-di');
|
||||
|
||||
angular.module('ffffng', []);
|
||||
|
||||
(function () {
|
||||
// Use graceful-fs instead of fs also in all libraries to have more robust fs handling.
|
||||
const realFs = require('fs');
|
||||
|
@ -14,52 +9,24 @@ angular.module('ffffng', []);
|
|||
gracefulFs.gracefulify(realFs);
|
||||
})();
|
||||
|
||||
require('./config');
|
||||
const config = require('./config').config;
|
||||
|
||||
require('./logger').tag('main', 'startup').info('Server starting up...');
|
||||
const Logger = require('./logger')
|
||||
Logger.tag('main', 'startup').info('Server starting up...');
|
||||
|
||||
require('./app');
|
||||
require('./router');
|
||||
require('./libs');
|
||||
|
||||
require('./utils/databaseUtil');
|
||||
require('./utils/errorTypes');
|
||||
require('./utils/resources');
|
||||
require('./utils/strings');
|
||||
require('./utils/urlBuilder');
|
||||
|
||||
require('./resources/versionResource');
|
||||
require('./resources/statisticsResource');
|
||||
require('./resources/frontendResource');
|
||||
require('./resources/taskResource');
|
||||
require('./resources/mailResource');
|
||||
require('./resources/nodeResource');
|
||||
require('./resources/monitoringResource');
|
||||
|
||||
require('./services/mailService');
|
||||
require('./services/mailTemplateService');
|
||||
require('./services/nodeService');
|
||||
require('./services/monitoringService');
|
||||
|
||||
require('../shared/validation/constraints');
|
||||
require('./validation/validator');
|
||||
|
||||
require('./jobs/scheduler');
|
||||
|
||||
const db = require('./db/database');
|
||||
|
||||
db.init().then(() => {
|
||||
// WARNING: We have to use funtion() syntax here, to satisfy ng-di. m(
|
||||
angular.injector(['ffffng']).invoke(function (config, app, Logger, Scheduler, Router) {
|
||||
require('./db/database').init()
|
||||
.then(() => {
|
||||
Logger.tag('main').info('Initializing...');
|
||||
|
||||
Scheduler.init();
|
||||
Router.init();
|
||||
const app = require('./app');
|
||||
|
||||
require('./jobs/scheduler').init();
|
||||
require('./router').init();
|
||||
|
||||
app.listen(config.server.port, '::');
|
||||
module.exports = app;
|
||||
});
|
||||
}).catch(error => {
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Could not init database: ', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('FrontendResource', function (
|
||||
Logger,
|
||||
Resources,
|
||||
ErrorTypes,
|
||||
fs
|
||||
) {
|
||||
var indexHtml = __dirname + '/../../client/index.html';
|
||||
const fs = require('graceful-fs')
|
||||
|
||||
return {
|
||||
render: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const Resources = require('../utils/resources')
|
||||
|
||||
const indexHtml = __dirname + '/../../client/index.html';
|
||||
|
||||
module.exports = {
|
||||
render (req, res) {
|
||||
const data = Resources.getData(req);
|
||||
|
||||
fs.readFile(indexHtml, 'utf8', function (err, body) {
|
||||
if (err) {
|
||||
|
@ -27,5 +27,4 @@ angular.module('ffffng').factory('FrontendResource', function (
|
|||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('MailResource', function (
|
||||
Constraints,
|
||||
Validator,
|
||||
MailService,
|
||||
Resources,
|
||||
Logger,
|
||||
ErrorTypes,
|
||||
Strings
|
||||
) {
|
||||
var isValidId = Validator.forConstraint(Constraints.id);
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const MailService = require('../services/mailService')
|
||||
const Resources = require('../utils/resources')
|
||||
const Strings = require('../utils/strings')
|
||||
const Validator = require('../validation/validator')
|
||||
|
||||
const isValidId = Validator.forConstraint(Constraints.id);
|
||||
|
||||
function withValidMailId(req, res, callback) {
|
||||
var id = Strings.normalizeString(Resources.getData(req).id);
|
||||
const id = Strings.normalizeString(Resources.getData(req).id);
|
||||
|
||||
if (!isValidId(id)) {
|
||||
return callback({data: 'Invalid mail id.', type: ErrorTypes.badRequest});
|
||||
|
@ -21,8 +20,8 @@ angular.module('ffffng').factory('MailResource', function (
|
|||
callback(null, id);
|
||||
}
|
||||
|
||||
return {
|
||||
get: function (req, res) {
|
||||
module.exports = {
|
||||
get (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
|
@ -43,7 +42,7 @@ angular.module('ffffng').factory('MailResource', function (
|
|||
});
|
||||
},
|
||||
|
||||
getAll: function (req, res) {
|
||||
getAll (req, res) {
|
||||
Resources.getValidRestParams('list', null, req, function (err, restParams) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
|
@ -64,7 +63,7 @@ angular.module('ffffng').factory('MailResource', function (
|
|||
});
|
||||
},
|
||||
|
||||
delete: function (req, res) {
|
||||
delete (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
|
@ -81,7 +80,7 @@ angular.module('ffffng').factory('MailResource', function (
|
|||
});
|
||||
},
|
||||
|
||||
resetFailures: function (req, res) {
|
||||
resetFailures (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
|
@ -97,5 +96,4 @@ angular.module('ffffng').factory('MailResource', function (
|
|||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('MonitoringResource', function (
|
||||
Constraints,
|
||||
Validator,
|
||||
MonitoringService,
|
||||
Logger,
|
||||
_,
|
||||
Strings,
|
||||
Resources,
|
||||
ErrorTypes
|
||||
) {
|
||||
var isValidToken = Validator.forConstraint(Constraints.token);
|
||||
const _ = require('lodash')
|
||||
|
||||
return {
|
||||
getAll: function (req, res) {
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const MonitoringService = require('../services/monitoringService')
|
||||
const Resources = require('../utils/resources')
|
||||
const Strings = require('../utils/strings')
|
||||
const Validator = require('../validation/validator')
|
||||
|
||||
const isValidToken = Validator.forConstraint(Constraints.token);
|
||||
|
||||
module.exports = {
|
||||
getAll (req, res) {
|
||||
Resources.getValidRestParams('list', null, req, function (err, restParams) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
|
@ -37,10 +37,10 @@ angular.module('ffffng').factory('MonitoringResource', function (
|
|||
});
|
||||
},
|
||||
|
||||
confirm: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
confirm (req, res) {
|
||||
const data = Resources.getData(req);
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
const token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -59,10 +59,10 @@ angular.module('ffffng').factory('MonitoringResource', function (
|
|||
});
|
||||
},
|
||||
|
||||
disable: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
disable (req, res) {
|
||||
const data = Resources.getData(req);
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
const token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -79,5 +79,4 @@ angular.module('ffffng').factory('MonitoringResource', function (
|
|||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('NodeResource', function (
|
||||
Constraints,
|
||||
Validator,
|
||||
Logger,
|
||||
MonitoringService,
|
||||
NodeService,
|
||||
_,
|
||||
deepExtend,
|
||||
Strings,
|
||||
Resources,
|
||||
ErrorTypes
|
||||
) {
|
||||
var nodeFields = ['hostname', 'key', 'email', 'nickname', 'mac', 'coords', 'monitoring'];
|
||||
const _ = require('lodash')
|
||||
const deepExtend = require('deep-extend')
|
||||
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const MonitoringService = require('../services/monitoringService')
|
||||
const NodeService = require('../services/nodeService')
|
||||
const Strings = require('../utils/strings')
|
||||
const Validator = require('../validation/validator')
|
||||
const Resources = require('../utils/resources')
|
||||
|
||||
const nodeFields = ['hostname', 'key', 'email', 'nickname', 'mac', 'coords', 'monitoring'];
|
||||
|
||||
function getNormalizedNodeData(reqData) {
|
||||
var node = {};
|
||||
const node = {};
|
||||
_.each(nodeFields, function (field) {
|
||||
var value = Strings.normalizeString(reqData[field]);
|
||||
let value = Strings.normalizeString(reqData[field]);
|
||||
if (field === 'mac') {
|
||||
value = Strings.normalizeMac(value);
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
return node;
|
||||
}
|
||||
|
||||
var isValidNode = Validator.forConstraints(Constraints.node);
|
||||
var isValidToken = Validator.forConstraint(Constraints.token);
|
||||
const isValidNode = Validator.forConstraints(Constraints.node);
|
||||
const isValidToken = Validator.forConstraint(Constraints.token);
|
||||
|
||||
return {
|
||||
module.exports = {
|
||||
create: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
const data = Resources.getData(req);
|
||||
|
||||
var node = getNormalizedNodeData(data);
|
||||
const node = getNormalizedNodeData(data);
|
||||
if (!isValidNode(node)) {
|
||||
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
},
|
||||
|
||||
update: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
const data = Resources.getData(req);
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
const token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
var node = getNormalizedNodeData(data);
|
||||
const node = getNormalizedNodeData(data);
|
||||
if (!isValidNode(node)) {
|
||||
return Resources.error(res, {data: 'Invalid node data.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -68,9 +68,9 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
},
|
||||
|
||||
delete: function (req, res) {
|
||||
var data = Resources.getData(req);
|
||||
const data = Resources.getData(req);
|
||||
|
||||
var token = Strings.normalizeString(data.token);
|
||||
const token = Strings.normalizeString(data.token);
|
||||
if (!isValidToken(token)) {
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
},
|
||||
|
||||
get: function (req, res) {
|
||||
var token = Strings.normalizeString(Resources.getData(req).token);
|
||||
const token = Strings.normalizeString(Resources.getData(req).token);
|
||||
if (!isValidToken(token)) {
|
||||
return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -108,12 +108,12 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
var realNodes = _.filter(nodes, function (node) {
|
||||
const realNodes = _.filter(nodes, function (node) {
|
||||
// We ignore nodes without tokens as those are only manually added ones like gateways.
|
||||
return node.token;
|
||||
});
|
||||
|
||||
var macs = _.map(realNodes, function (node) {
|
||||
const macs = _.map(realNodes, function (node) {
|
||||
return node.mac;
|
||||
});
|
||||
|
||||
|
@ -123,8 +123,8 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
var enhancedNodes = _.map(realNodes, function (node) {
|
||||
var nodeState = nodeStateByMac[node.mac];
|
||||
const enhancedNodes = _.map(realNodes, function (node) {
|
||||
const nodeState = nodeStateByMac[node.mac];
|
||||
if (nodeState) {
|
||||
return deepExtend({}, node, {
|
||||
site: nodeState.site,
|
||||
|
@ -136,7 +136,7 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
return node;
|
||||
});
|
||||
|
||||
var filteredNodes = Resources.filter(
|
||||
const filteredNodes = Resources.filter(
|
||||
enhancedNodes,
|
||||
[
|
||||
'hostname',
|
||||
|
@ -151,9 +151,9 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
],
|
||||
restParams
|
||||
);
|
||||
var total = filteredNodes.length;
|
||||
const total = filteredNodes.length;
|
||||
|
||||
var sortedNodes = Resources.sort(
|
||||
const sortedNodes = Resources.sort(
|
||||
filteredNodes,
|
||||
[
|
||||
'hostname',
|
||||
|
@ -170,7 +170,7 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
],
|
||||
restParams
|
||||
);
|
||||
var pageNodes = Resources.getPageEntities(sortedNodes, restParams);
|
||||
const pageNodes = Resources.getPageEntities(sortedNodes, restParams);
|
||||
|
||||
res.set('X-Total-Count', total);
|
||||
return Resources.success(res, pageNodes);
|
||||
|
@ -178,5 +178,4 @@ angular.module('ffffng').factory('NodeResource', function (
|
|||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('StatisticsResource', function (
|
||||
Logger,
|
||||
NodeService,
|
||||
Resources,
|
||||
ErrorTypes
|
||||
) {
|
||||
return {
|
||||
get: function (req, res) {
|
||||
NodeService.getNodeStatistics(function (err, nodeStatistics) {
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const NodeService = require('../services/nodeService')
|
||||
const Resources = require('../utils/resources')
|
||||
|
||||
module.exports = {
|
||||
get (req, res) {
|
||||
NodeService.getNodeStatistics((err, nodeStatistics) => {
|
||||
if (err) {
|
||||
Logger.tag('statistics').error('Error getting statistics:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
|
@ -22,5 +21,4 @@ angular.module('ffffng').factory('StatisticsResource', function (
|
|||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('TaskResource', function (
|
||||
Constraints,
|
||||
Validator,
|
||||
_,
|
||||
Strings,
|
||||
Resources,
|
||||
ErrorTypes,
|
||||
Scheduler
|
||||
) {
|
||||
var isValidId = Validator.forConstraint(Constraints.id);
|
||||
const _ = require('lodash')
|
||||
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Resources = require('../utils/resources')
|
||||
const Scheduler = require('../jobs/scheduler')
|
||||
const Strings = require('../utils/strings')
|
||||
const Validator = require('../validation/validator')
|
||||
|
||||
const isValidId = Validator.forConstraint(Constraints.id);
|
||||
|
||||
function toExternalTask(task) {
|
||||
return {
|
||||
|
@ -26,7 +26,7 @@ angular.module('ffffng').factory('TaskResource', function (
|
|||
}
|
||||
|
||||
function withValidTaskId(req, res, callback) {
|
||||
var id = Strings.normalizeString(Resources.getData(req).id);
|
||||
const id = Strings.normalizeString(Resources.getData(req).id);
|
||||
|
||||
if (!isValidId(id)) {
|
||||
return callback({data: 'Invalid task id.', type: ErrorTypes.badRequest});
|
||||
|
@ -36,8 +36,8 @@ angular.module('ffffng').factory('TaskResource', function (
|
|||
}
|
||||
|
||||
function getTask(id, callback) {
|
||||
var tasks = Scheduler.getTasks();
|
||||
var task = tasks[id];
|
||||
const tasks = Scheduler.getTasks();
|
||||
const task = tasks[id];
|
||||
|
||||
if (!task) {
|
||||
return callback({data: 'Task not found.', type: ErrorTypes.notFound});
|
||||
|
@ -74,33 +74,33 @@ angular.module('ffffng').factory('TaskResource', function (
|
|||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getAll: function (req, res) {
|
||||
module.exports = {
|
||||
getAll (req, res) {
|
||||
Resources.getValidRestParams('list', null, req, function (err, restParams) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
var tasks = Resources.sort(
|
||||
const tasks = Resources.sort(
|
||||
_.values(Scheduler.getTasks()),
|
||||
['id', 'name', 'schedule', 'state', 'runningSince', 'lastRunStarted'],
|
||||
restParams
|
||||
);
|
||||
var filteredTasks = Resources.filter(
|
||||
const filteredTasks = Resources.filter(
|
||||
tasks,
|
||||
['id', 'name', 'schedule', 'state'],
|
||||
restParams
|
||||
);
|
||||
var total = filteredTasks.length;
|
||||
const total = filteredTasks.length;
|
||||
|
||||
var pageTasks = Resources.getPageEntities(filteredTasks, restParams);
|
||||
const pageTasks = Resources.getPageEntities(filteredTasks, restParams);
|
||||
|
||||
res.set('X-Total-Count', total);
|
||||
return Resources.success(res, _.map(pageTasks, toExternalTask));
|
||||
});
|
||||
},
|
||||
|
||||
run: function (req, res) {
|
||||
run (req, res) {
|
||||
withTask(req, res, function (err, task) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
|
@ -116,12 +116,11 @@ angular.module('ffffng').factory('TaskResource', function (
|
|||
});
|
||||
},
|
||||
|
||||
enable: function (req, res) {
|
||||
enable (req, res) {
|
||||
setTaskEnabled(req, res, true);
|
||||
},
|
||||
|
||||
disable: function (req, res) {
|
||||
disable (req, res) {
|
||||
setTaskEnabled(req, res, false);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('VersionResource', function (
|
||||
version,
|
||||
Resources
|
||||
) {
|
||||
return {
|
||||
get: function (req, res) {
|
||||
const Resources = require('../utils/resources')
|
||||
const version = require('../config').version
|
||||
|
||||
module.exports = {
|
||||
get (req, res) {
|
||||
return Resources.success(
|
||||
res,
|
||||
{
|
||||
version: version
|
||||
version
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Router', function (
|
||||
app,
|
||||
VersionResource,
|
||||
StatisticsResource,
|
||||
FrontendResource,
|
||||
NodeResource,
|
||||
MonitoringResource,
|
||||
TaskResource,
|
||||
MailResource,
|
||||
config
|
||||
) {
|
||||
return {
|
||||
init: function () {
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
const express = require('express');
|
||||
|
||||
const app = require('./app')
|
||||
const config = require('./config').config
|
||||
const VersionResource = require('./resources/versionResource')
|
||||
const StatisticsResource = require('./resources/statisticsResource')
|
||||
const FrontendResource = require('./resources/frontendResource')
|
||||
const NodeResource = require('./resources/nodeResource')
|
||||
const MonitoringResource = require('./resources/monitoringResource')
|
||||
const TaskResource = require('./resources/taskResource')
|
||||
const MailResource = require('./resources/mailResource')
|
||||
|
||||
module.exports = {
|
||||
init () {
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/', FrontendResource.render);
|
||||
|
||||
|
@ -49,5 +49,4 @@ angular.module('ffffng').factory('Router', function (
|
|||
|
||||
app.use(config.server.rootPath, router);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng')
|
||||
.service('MailService', function (
|
||||
Database,
|
||||
MailTemplateService,
|
||||
config,
|
||||
_,
|
||||
async,
|
||||
deepExtend,
|
||||
fs,
|
||||
moment,
|
||||
Logger,
|
||||
Resources
|
||||
) {
|
||||
var MAIL_QUEUE_DB_BATCH_SIZE = 50;
|
||||
var MAIL_QUEUE_MAX_PARALLEL_SENDING = 3;
|
||||
const _ = require('lodash')
|
||||
const async = require('async')
|
||||
const deepExtend = require('deep-extend')
|
||||
const moment = require('moment')
|
||||
|
||||
var transporter = require('nodemailer').createTransport(deepExtend(
|
||||
const config = require('../config').config
|
||||
const Database = require('../db/database').db
|
||||
const Logger = require('../logger')
|
||||
const MailTemplateService = require('./mailTemplateService')
|
||||
const Resources = require('../utils/resources')
|
||||
|
||||
const MAIL_QUEUE_DB_BATCH_SIZE = 50;
|
||||
const MAIL_QUEUE_MAX_PARALLEL_SENDING = 3;
|
||||
|
||||
const transporter = require('nodemailer').createTransport(deepExtend(
|
||||
{},
|
||||
config.server.email.smtp,
|
||||
{
|
||||
|
@ -41,7 +39,7 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var mailOptions = {
|
||||
const mailOptions = {
|
||||
from: options.sender,
|
||||
to: options.recipient,
|
||||
subject: renderedTemplate.subject,
|
||||
|
@ -70,7 +68,7 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var pendingMails;
|
||||
let pendingMails;
|
||||
try {
|
||||
pendingMails = _.map(rows, function (row) {
|
||||
return deepExtend(
|
||||
|
@ -96,7 +94,7 @@ angular.module('ffffng')
|
|||
}
|
||||
|
||||
function incrementFailureCounterForPendingEmail(id, callback) {
|
||||
var now = moment();
|
||||
const now = moment();
|
||||
Database.run(
|
||||
'UPDATE email_queue SET failures = failures + 1, modified_at = ? WHERE id = ?',
|
||||
[now.unix(), id],
|
||||
|
@ -126,8 +124,8 @@ angular.module('ffffng')
|
|||
Database.get('SELECT * FROM email_queue WHERE id = ?', [id], callback);
|
||||
}
|
||||
|
||||
return {
|
||||
enqueue: function (sender, recipient, email, data, callback) {
|
||||
module.exports = {
|
||||
enqueue (sender, recipient, email, data, callback) {
|
||||
if (!_.isPlainObject(data)) {
|
||||
return callback(new Error('Unexpected data: ' + data));
|
||||
}
|
||||
|
@ -142,11 +140,11 @@ angular.module('ffffng')
|
|||
);
|
||||
},
|
||||
|
||||
getMail: function (id, callback) {
|
||||
getMail (id, callback) {
|
||||
doGetMail(id, callback);
|
||||
},
|
||||
|
||||
getPendingMails: function (restParams, callback) {
|
||||
getPendingMails (restParams, callback) {
|
||||
Database.get(
|
||||
'SELECT count(*) AS total FROM email_queue',
|
||||
[],
|
||||
|
@ -155,9 +153,9 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var total = row.total;
|
||||
const total = row.total;
|
||||
|
||||
var filter = Resources.filterClause(
|
||||
const filter = Resources.filterClause(
|
||||
restParams,
|
||||
'id',
|
||||
['id', 'failures', 'sender', 'recipient', 'email', 'created_at', 'modified_at'],
|
||||
|
@ -179,11 +177,11 @@ angular.module('ffffng')
|
|||
);
|
||||
},
|
||||
|
||||
deleteMail: function (id, callback) {
|
||||
deleteMail (id, callback) {
|
||||
removePendingMailFromQueue(id, callback);
|
||||
},
|
||||
|
||||
resetFailures: function (id, callback) {
|
||||
resetFailures (id, callback) {
|
||||
Database.run(
|
||||
'UPDATE email_queue SET failures = 0, modified_at = ? WHERE id = ?',
|
||||
[moment().unix(), id],
|
||||
|
@ -201,12 +199,12 @@ angular.module('ffffng')
|
|||
);
|
||||
},
|
||||
|
||||
sendPendingMails: function (callback) {
|
||||
sendPendingMails (callback) {
|
||||
Logger.tag('mail', 'queue').debug('Start sending pending mails...');
|
||||
|
||||
var startTime = moment();
|
||||
const startTime = moment();
|
||||
|
||||
var sendNextBatch = function (err) {
|
||||
const sendNextBatch = function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
@ -234,5 +232,4 @@ angular.module('ffffng')
|
|||
|
||||
sendNextBatch(null);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng')
|
||||
.service('MailTemplateService', function (
|
||||
UrlBuilder,
|
||||
config,
|
||||
_,
|
||||
async,
|
||||
deepExtend,
|
||||
fs,
|
||||
moment,
|
||||
Logger
|
||||
) {
|
||||
var templateBasePath = __dirname + '/../mailTemplates';
|
||||
var snippetsBasePath = templateBasePath + '/snippets';
|
||||
const _ = require('lodash')
|
||||
const async = require('async')
|
||||
const deepExtend = require('deep-extend')
|
||||
const fs = require('graceful-fs')
|
||||
const moment = require('moment')
|
||||
|
||||
var templateFunctions = {};
|
||||
const config = require('../config').config
|
||||
const Logger = require('../logger')
|
||||
const UrlBuilder = require('../utils/urlBuilder')
|
||||
|
||||
const templateBasePath = __dirname + '/../mailTemplates';
|
||||
const snippetsBasePath = templateBasePath + '/snippets';
|
||||
|
||||
const templateFunctions = {};
|
||||
|
||||
function renderSnippet(name, data) {
|
||||
var snippetFile = snippetsBasePath + '/' + name + '.html';
|
||||
const snippetFile = snippetsBasePath + '/' + name + '.html';
|
||||
|
||||
return _.template(fs.readFileSync(snippetFile).toString())(deepExtend(
|
||||
{},
|
||||
|
@ -69,16 +68,16 @@ angular.module('ffffng')
|
|||
templateFunctions.formatDateTime = formatDateTime;
|
||||
templateFunctions.formatFromNow = formatFromNow;
|
||||
|
||||
return {
|
||||
configureTransporter: function (transporter) {
|
||||
var htmlToText = require('nodemailer-html-to-text').htmlToText;
|
||||
module.exports = {
|
||||
configureTransporter (transporter) {
|
||||
const htmlToText = require('nodemailer-html-to-text').htmlToText;
|
||||
transporter.use('compile', htmlToText({
|
||||
tables: ['.table']
|
||||
}));
|
||||
},
|
||||
|
||||
render: function (mailOptions, callback) {
|
||||
var templatePathPrefix = templateBasePath + '/' + mailOptions.email;
|
||||
render (mailOptions, callback) {
|
||||
const templatePathPrefix = templateBasePath + '/' + mailOptions.email;
|
||||
|
||||
async.parallel({
|
||||
subject: _.partial(fs.readFile, templatePathPrefix + '.subject.txt'),
|
||||
|
@ -89,7 +88,7 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var data = deepExtend(
|
||||
const data = deepExtend(
|
||||
{},
|
||||
mailOptions.data,
|
||||
{
|
||||
|
@ -103,14 +102,13 @@ angular.module('ffffng')
|
|||
return _.template(templates[field].toString())(data);
|
||||
}
|
||||
|
||||
var renderedTemplate;
|
||||
let renderedTemplate;
|
||||
try {
|
||||
renderedTemplate = {
|
||||
subject: _.trim(render('subject')),
|
||||
body: render('body')
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
Logger
|
||||
.tag('mail', 'template')
|
||||
.error('Error rendering template for mail[' + mailOptions.id + ']:', error);
|
||||
|
@ -121,5 +119,4 @@ angular.module('ffffng')
|
|||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng')
|
||||
.service('MonitoringService', function (
|
||||
_,
|
||||
async,
|
||||
config,
|
||||
deepExtend,
|
||||
Database,
|
||||
DatabaseUtil,
|
||||
ErrorTypes,
|
||||
Logger,
|
||||
moment,
|
||||
MailService,
|
||||
NodeService,
|
||||
request,
|
||||
Strings,
|
||||
UrlBuilder,
|
||||
Validator,
|
||||
Constraints,
|
||||
Resources
|
||||
) {
|
||||
var MONITORING_STATE_MACS_CHUNK_SIZE = 100;
|
||||
var MONITORING_MAILS_DB_BATCH_SIZE = 50;
|
||||
const _ = require('lodash')
|
||||
const async = require('async')
|
||||
const moment = require('moment')
|
||||
const request = require('request')
|
||||
|
||||
const config = require('../config').config
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const Database = require('../db/database').db
|
||||
const DatabaseUtil = require('../utils/databaseUtil')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const MailService = require('../services/mailService')
|
||||
const NodeService = require('../services/nodeService')
|
||||
const Resources = require('../utils/resources')
|
||||
const Strings = require('../utils/strings')
|
||||
const UrlBuilder = require('../utils/urlBuilder')
|
||||
const Validator = require('../validation/validator')
|
||||
|
||||
const MONITORING_STATE_MACS_CHUNK_SIZE = 100;
|
||||
const MONITORING_MAILS_DB_BATCH_SIZE = 50;
|
||||
/**
|
||||
* Defines the intervals emails are sent if a node is offline
|
||||
*/
|
||||
var MONITORING_OFFLINE_MAILS_SCHEDULE = {
|
||||
const MONITORING_OFFLINE_MAILS_SCHEDULE = {
|
||||
1: { amount: 3, unit: 'hours' },
|
||||
2: { amount: 1, unit: 'days' },
|
||||
3: { amount: 7, unit: 'days' }
|
||||
};
|
||||
var DELETE_OFFLINE_NODES_AFTER_DURATION = {
|
||||
const DELETE_OFFLINE_NODES_AFTER_DURATION = {
|
||||
amount: 100,
|
||||
unit: 'days'
|
||||
};
|
||||
|
||||
var previousImportTimestamp = null;
|
||||
let previousImportTimestamp = null;
|
||||
|
||||
function insertNodeInformation(nodeData, node, callback) {
|
||||
Logger
|
||||
|
@ -117,7 +115,7 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var nodeDataForStoring;
|
||||
let nodeDataForStoring;
|
||||
if (nodeData === 'missing') {
|
||||
nodeDataForStoring = {
|
||||
mac: node.mac,
|
||||
|
@ -141,7 +139,7 @@ angular.module('ffffng')
|
|||
});
|
||||
}
|
||||
|
||||
var isValidMac = Validator.forConstraint(Constraints.node.mac);
|
||||
const isValidMac = Validator.forConstraint(Constraints.node.mac);
|
||||
|
||||
function parseTimestamp (timestamp) {
|
||||
if (!_.isString(timestamp)) {
|
||||
|
@ -173,7 +171,7 @@ angular.module('ffffng')
|
|||
'Node ' + nodeId + ': Invalid MAC: ' + nodeData.nodeinfo.network.mac
|
||||
);
|
||||
}
|
||||
var mac = Strings.normalizeMac(nodeData.nodeinfo.network.mac);
|
||||
const mac = Strings.normalizeMac(nodeData.nodeinfo.network.mac);
|
||||
|
||||
if (!_.isPlainObject(nodeData.flags)) {
|
||||
throw new Error(
|
||||
|
@ -185,23 +183,23 @@ angular.module('ffffng')
|
|||
'Node ' + nodeId + ': Unexpected flags.online type: ' + (typeof nodeData.flags.online)
|
||||
);
|
||||
}
|
||||
var isOnline = nodeData.flags.online;
|
||||
const isOnline = nodeData.flags.online;
|
||||
|
||||
var lastSeen = parseTimestamp(nodeData.lastseen);
|
||||
const lastSeen = parseTimestamp(nodeData.lastseen);
|
||||
if (!lastSeen.isValid()) {
|
||||
throw new Error(
|
||||
'Node ' + nodeId + ': Invalid lastseen timestamp: ' + nodeData.lastseen
|
||||
);
|
||||
}
|
||||
|
||||
var site = null;
|
||||
let site = null;
|
||||
// jshint -W106
|
||||
if (_.isPlainObject(nodeData.nodeinfo.system) && _.isString(nodeData.nodeinfo.system.site_code)) {
|
||||
site = nodeData.nodeinfo.system.site_code;
|
||||
}
|
||||
// jshint +W106
|
||||
|
||||
var domain = null;
|
||||
let domain = null;
|
||||
// jshint -W106
|
||||
if (_.isPlainObject(nodeData.nodeinfo.system) && _.isString(nodeData.nodeinfo.system.domain_code)) {
|
||||
domain = nodeData.nodeinfo.system.domain_code;
|
||||
|
@ -221,10 +219,10 @@ angular.module('ffffng')
|
|||
function parseNodesJson (body, callback) {
|
||||
Logger.tag('monitoring', 'information-retrieval').debug('Parsing nodes.json...');
|
||||
|
||||
var data = {};
|
||||
const data = {};
|
||||
|
||||
try {
|
||||
var json = JSON.parse(body);
|
||||
const json = JSON.parse(body);
|
||||
|
||||
if (json.version !== 1) {
|
||||
return callback(new Error('Unexpected nodes.json version: ' + json.version));
|
||||
|
@ -282,7 +280,7 @@ angular.module('ffffng')
|
|||
function sendMonitoringMailsBatched(name, mailType, findBatchFun, callback) {
|
||||
Logger.tag('monitoring', 'mail-sending').debug('Sending "%s" mails...', name);
|
||||
|
||||
var sendNextBatch = function (err) {
|
||||
const sendNextBatch = function (err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
@ -302,7 +300,7 @@ angular.module('ffffng')
|
|||
async.each(
|
||||
nodeStates,
|
||||
function (nodeState, mailCallback) {
|
||||
var mac = nodeState.mac;
|
||||
const mac = nodeState.mac;
|
||||
Logger.tag('monitoring', 'mail-sending').debug('Loading node data for: %s', mac);
|
||||
NodeService.getNodeDataByMac(mac, function (err, node, nodeSecrets) {
|
||||
if (err) {
|
||||
|
@ -349,7 +347,7 @@ angular.module('ffffng')
|
|||
.tag('monitoring', 'mail-sending')
|
||||
.debug('Updating node state: ', mac);
|
||||
|
||||
var now = moment().unix();
|
||||
const now = moment().unix();
|
||||
Database.run(
|
||||
'UPDATE node_state ' +
|
||||
'SET hostname = ?, monitoring_state = ?, modified_at = ?, last_status_mail_sent = ?, last_status_mail_type = ?' +
|
||||
|
@ -416,14 +414,14 @@ angular.module('ffffng')
|
|||
/**
|
||||
* descriptive string that stores, which was the last mail type, stored in the database as last_status_mail_type
|
||||
*/
|
||||
var previousType =
|
||||
const previousType =
|
||||
mailNumber === 1 ? 'monitoring-online-again' : ('monitoring-offline-' + (mailNumber - 1));
|
||||
|
||||
// the first time the first offline mail is send, there was no mail before
|
||||
var allowNull = mailNumber === 1 ? ' OR last_status_mail_type IS NULL' : '';
|
||||
const allowNull = mailNumber === 1 ? ' OR last_status_mail_type IS NULL' : '';
|
||||
|
||||
var schedule = MONITORING_OFFLINE_MAILS_SCHEDULE[mailNumber];
|
||||
var scheduledTimeBefore = moment().subtract(schedule.amount, schedule.unit);
|
||||
const schedule = MONITORING_OFFLINE_MAILS_SCHEDULE[mailNumber];
|
||||
const scheduledTimeBefore = moment().subtract(schedule.amount, schedule.unit);
|
||||
|
||||
Database.all(
|
||||
'SELECT * FROM node_state ' +
|
||||
|
@ -472,8 +470,8 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var maxTimestamp = datas[0].importTimestamp;
|
||||
var minTimestamp = maxTimestamp;
|
||||
let maxTimestamp = datas[0].importTimestamp;
|
||||
let minTimestamp = maxTimestamp;
|
||||
_.each(datas, function (data) {
|
||||
if (data.importTimestamp.isAfter(maxTimestamp)) {
|
||||
maxTimestamp = data.importTimestamp;
|
||||
|
@ -497,15 +495,15 @@ angular.module('ffffng')
|
|||
|
||||
// We do not parallelize here as the sqlite will start slowing down and blocking with too many
|
||||
// parallel queries. This has resulted in blocking other requests too and thus in a major slowdown.
|
||||
var allNodes = _.flatMap(datas, function (data) {
|
||||
const allNodes = _.flatMap(datas, function (data) {
|
||||
return data.nodes;
|
||||
});
|
||||
|
||||
// Get rid of duplicates from different nodes.json files. Always use the one with the newest
|
||||
var sortedNodes = _.orderBy(allNodes, [function (node) {
|
||||
const sortedNodes = _.orderBy(allNodes, [function (node) {
|
||||
return node.lastSeen.unix();
|
||||
}], ['desc']);
|
||||
var uniqueNodes = _.uniqBy(sortedNodes, function (node) {
|
||||
const uniqueNodes = _.uniqBy(sortedNodes, function (node) {
|
||||
return node.mac;
|
||||
});
|
||||
async.eachSeries(
|
||||
|
@ -569,9 +567,9 @@ angular.module('ffffng')
|
|||
});
|
||||
}
|
||||
|
||||
return {
|
||||
module.exports = {
|
||||
getAll: function (restParams, callback) {
|
||||
var sortFields = [
|
||||
const sortFields = [
|
||||
'id',
|
||||
'hostname',
|
||||
'mac',
|
||||
|
@ -586,7 +584,7 @@ angular.module('ffffng')
|
|||
'created_at',
|
||||
'modified_at'
|
||||
];
|
||||
var filterFields = [
|
||||
const filterFields = [
|
||||
'hostname',
|
||||
'mac',
|
||||
'monitoring_state',
|
||||
|
@ -594,7 +592,7 @@ angular.module('ffffng')
|
|||
'last_status_mail_type'
|
||||
];
|
||||
|
||||
var where = Resources.whereCondition(restParams, filterFields);
|
||||
const where = Resources.whereCondition(restParams, filterFields);
|
||||
|
||||
Database.get(
|
||||
'SELECT count(*) AS total FROM node_state WHERE ' + where.query,
|
||||
|
@ -604,9 +602,9 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var total = row.total;
|
||||
const total = row.total;
|
||||
|
||||
var filter = Resources.filterClause(
|
||||
const filter = Resources.filterClause(
|
||||
restParams,
|
||||
'id',
|
||||
sortFields,
|
||||
|
@ -636,7 +634,7 @@ angular.module('ffffng')
|
|||
async.map(
|
||||
_.chunk(macs, MONITORING_STATE_MACS_CHUNK_SIZE),
|
||||
function (subMacs, subCallback) {
|
||||
var inCondition = DatabaseUtil.inCondition('mac', subMacs);
|
||||
const inCondition = DatabaseUtil.inCondition('mac', subMacs);
|
||||
|
||||
Database.all(
|
||||
'SELECT * FROM node_state WHERE ' + inCondition.query,
|
||||
|
@ -649,7 +647,7 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var nodeStateByMac = {};
|
||||
const nodeStateByMac = {};
|
||||
_.each(_.flatten(rowsArrays), function (row) {
|
||||
nodeStateByMac[row.mac] = row;
|
||||
});
|
||||
|
@ -707,7 +705,7 @@ angular.module('ffffng')
|
|||
},
|
||||
|
||||
retrieveNodeInformation: function (callback) {
|
||||
var urls = config.server.map.nodesJsonUrl;
|
||||
let urls = config.server.map.nodesJsonUrl;
|
||||
if (_.isEmpty(urls)) {
|
||||
return callback(
|
||||
new Error('No nodes.json-URLs set. Please adjust config.json: server.map.nodesJsonUrl')
|
||||
|
@ -723,7 +721,7 @@ angular.module('ffffng')
|
|||
sendMonitoringMails: function (callback) {
|
||||
Logger.tag('monitoring', 'mail-sending').debug('Sending monitoring mails...');
|
||||
|
||||
var startTime = moment();
|
||||
const startTime = moment();
|
||||
|
||||
sendOnlineAgainMails(startTime, function (err) {
|
||||
if (err) {
|
||||
|
@ -786,7 +784,7 @@ angular.module('ffffng')
|
|||
async.eachSeries(
|
||||
rows,
|
||||
function (row, nodeCallback) {
|
||||
var mac = row.mac;
|
||||
const mac = row.mac;
|
||||
Logger.tag('nodes', 'delete-offline').info('Deleting node ' + mac);
|
||||
NodeService.getNodeDataByMac(mac, function (err, node) {
|
||||
if (err) {
|
||||
|
@ -825,5 +823,4 @@ angular.module('ffffng')
|
|||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng')
|
||||
.service('NodeService', function (
|
||||
config,
|
||||
_,
|
||||
async,
|
||||
crypto,
|
||||
fs,
|
||||
glob,
|
||||
Logger,
|
||||
MailService,
|
||||
Strings,
|
||||
ErrorTypes,
|
||||
UrlBuilder
|
||||
) {
|
||||
var MAX_PARALLEL_NODES_PARSING = 10;
|
||||
const _ = require('lodash')
|
||||
const async = require('async')
|
||||
const crypto = require('crypto')
|
||||
const fs = require('graceful-fs')
|
||||
const glob = require('glob')
|
||||
|
||||
var linePrefixes = {
|
||||
const config = require('../config').config
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const MailService = require('../services/mailService')
|
||||
const Strings = require('../utils/strings')
|
||||
const UrlBuilder = require('../utils/urlBuilder')
|
||||
|
||||
const MAX_PARALLEL_NODES_PARSING = 10;
|
||||
|
||||
const linePrefixes = {
|
||||
hostname: '# Knotenname: ',
|
||||
nickname: '# Ansprechpartner: ',
|
||||
email: '# Kontakt: ',
|
||||
|
@ -27,14 +26,14 @@ angular.module('ffffng')
|
|||
monitoringToken: '# Monitoring-Token: '
|
||||
};
|
||||
|
||||
var filenameParts = ['hostname', 'mac', 'key', 'token', 'monitoringToken'];
|
||||
const filenameParts = ['hostname', 'mac', 'key', 'token', 'monitoringToken'];
|
||||
|
||||
function generateToken() {
|
||||
return crypto.randomBytes(8).toString('hex');
|
||||
}
|
||||
|
||||
function toNodeFilesPattern(filter) {
|
||||
var pattern = _.join(
|
||||
const pattern = _.join(
|
||||
_.map(filenameParts, function (field) {
|
||||
return filter.hasOwnProperty(field) ? filter[field] : '*';
|
||||
}),
|
||||
|
@ -75,8 +74,8 @@ angular.module('ffffng')
|
|||
}
|
||||
|
||||
function parseNodeFilename(filename) {
|
||||
var parts = _.split(filename, '@', filenameParts.length);
|
||||
var parsed = {};
|
||||
const parts = _.split(filename, '@', filenameParts.length);
|
||||
const parsed = {};
|
||||
_.each(_.zip(filenameParts, parts), function (part) {
|
||||
parsed[part[0]] = part[1];
|
||||
});
|
||||
|
@ -84,7 +83,7 @@ angular.module('ffffng')
|
|||
}
|
||||
|
||||
function isDuplicate(filter, token) {
|
||||
var files = findNodeFilesSync(filter);
|
||||
const files = findNodeFilesSync(filter);
|
||||
if (files.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -130,10 +129,10 @@ angular.module('ffffng')
|
|||
}
|
||||
|
||||
function writeNodeFile(isUpdate, token, node, nodeSecrets, callback) {
|
||||
var filename = toNodeFilename(token, node, nodeSecrets);
|
||||
var data = '';
|
||||
const filename = toNodeFilename(token, node, nodeSecrets);
|
||||
let data = '';
|
||||
_.each(linePrefixes, function (prefix, key) {
|
||||
var value;
|
||||
let value;
|
||||
switch (key) {
|
||||
case 'monitoring':
|
||||
if (node.monitoring && node.monitoringConfirmed) {
|
||||
|
@ -164,10 +163,10 @@ angular.module('ffffng')
|
|||
|
||||
// since node.js is single threaded we don't need a lock
|
||||
|
||||
var error;
|
||||
let error;
|
||||
|
||||
if (isUpdate) {
|
||||
var files = findNodeFilesSync({ token: token });
|
||||
const files = findNodeFilesSync({ token: token });
|
||||
if (files.length !== 1) {
|
||||
return callback({data: 'Node not found.', type: ErrorTypes.notFound});
|
||||
}
|
||||
|
@ -177,7 +176,7 @@ angular.module('ffffng')
|
|||
return callback(error);
|
||||
}
|
||||
|
||||
var file = files[0];
|
||||
const file = files[0];
|
||||
try {
|
||||
fs.unlinkSync(file);
|
||||
}
|
||||
|
@ -232,17 +231,17 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var lines = contents.toString();
|
||||
const lines = contents.toString();
|
||||
|
||||
var node = {};
|
||||
var nodeSecrets = {};
|
||||
const node = {};
|
||||
const nodeSecrets = {};
|
||||
|
||||
_.each(lines.split('\n'), function (line) {
|
||||
var entries = {};
|
||||
const entries = {};
|
||||
|
||||
for (var key in linePrefixes) {
|
||||
for (const key in linePrefixes) {
|
||||
if (linePrefixes.hasOwnProperty(key)) {
|
||||
var prefix = linePrefixes[key];
|
||||
const prefix = linePrefixes[key];
|
||||
if (line.substring(0, prefix.length) === prefix) {
|
||||
entries[key] = Strings.normalizeString(line.substr(prefix.length));
|
||||
break;
|
||||
|
@ -259,8 +258,8 @@ angular.module('ffffng')
|
|||
node.mac = value;
|
||||
node.mapId = _.toLower(value).replace(/:/g, '');
|
||||
} else if (key === 'monitoring') {
|
||||
var active = value === 'aktiv';
|
||||
var pending = value === 'pending';
|
||||
const active = value === 'aktiv';
|
||||
const pending = value === 'pending';
|
||||
node.monitoring = active || pending;
|
||||
node.monitoringConfirmed = active;
|
||||
node.monitoringState = active ? 'active' : (pending ? 'pending' : 'disabled');
|
||||
|
@ -286,7 +285,7 @@ angular.module('ffffng')
|
|||
return callback(null);
|
||||
}
|
||||
|
||||
var file = files[0];
|
||||
const file = files[0];
|
||||
return parseNodeFile(file, callback);
|
||||
});
|
||||
}
|
||||
|
@ -306,8 +305,8 @@ angular.module('ffffng')
|
|||
}
|
||||
|
||||
function sendMonitoringConfirmationMail(node, nodeSecrets, callback) {
|
||||
var confirmUrl = UrlBuilder.monitoringConfirmUrl(nodeSecrets);
|
||||
var disableUrl = UrlBuilder.monitoringDisableUrl(nodeSecrets);
|
||||
const confirmUrl = UrlBuilder.monitoringConfirmUrl(nodeSecrets);
|
||||
const disableUrl = UrlBuilder.monitoringDisableUrl(nodeSecrets);
|
||||
|
||||
MailService.enqueue(
|
||||
config.server.email.from,
|
||||
|
@ -329,10 +328,10 @@ angular.module('ffffng')
|
|||
);
|
||||
}
|
||||
|
||||
return {
|
||||
module.exports = {
|
||||
createNode: function (node, callback) {
|
||||
var token = generateToken();
|
||||
var nodeSecrets = {};
|
||||
const token = generateToken();
|
||||
const nodeSecrets = {};
|
||||
|
||||
node.monitoringConfirmed = false;
|
||||
|
||||
|
@ -365,8 +364,8 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var monitoringConfirmed = false;
|
||||
var monitoringToken = '';
|
||||
let monitoringConfirmed = false;
|
||||
let monitoringToken = '';
|
||||
|
||||
if (node.monitoring) {
|
||||
if (!currentNode.monitoring) {
|
||||
|
@ -471,7 +470,7 @@ angular.module('ffffng')
|
|||
return fileCallback(err);
|
||||
}
|
||||
|
||||
var expectedFilename = toNodeFilename(node.token, node, nodeSecrets);
|
||||
const expectedFilename = toNodeFilename(node.token, node, nodeSecrets);
|
||||
if (file !== expectedFilename) {
|
||||
return fs.rename(file, expectedFilename, function (err) {
|
||||
if (err) {
|
||||
|
@ -498,7 +497,7 @@ angular.module('ffffng')
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
var nodeStatistics = {
|
||||
const nodeStatistics = {
|
||||
registered: _.size(nodes),
|
||||
withVPN: 0,
|
||||
withCoords: 0,
|
||||
|
@ -530,5 +529,4 @@ angular.module('ffffng')
|
|||
callback(null, nodeStatistics);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('DatabaseUtil', function (_) {
|
||||
return {
|
||||
inCondition: function (field, list) {
|
||||
const _ = require('lodash')
|
||||
|
||||
module.exports = {
|
||||
inCondition (field, list) {
|
||||
return {
|
||||
query: '(' + field + ' IN (' + _.join(_.times(list.length, _.constant('?')), ', ') + '))',
|
||||
params: list
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('ErrorTypes', function () {
|
||||
return {
|
||||
module.exports = {
|
||||
badRequest: {code: 400},
|
||||
notFound: {code: 404},
|
||||
conflict: {code: 409},
|
||||
internalError: {code: 500}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Resources', function (_, Constraints, Validator, ErrorTypes, Logger) {
|
||||
const _ = require('lodash')
|
||||
|
||||
const Constraints = require('../../shared/validation/constraints')
|
||||
const ErrorTypes = require('../utils/errorTypes')
|
||||
const Logger = require('../logger')
|
||||
const Validator = require('../validation/validator')
|
||||
|
||||
function respond(res, httpCode, data, type) {
|
||||
switch (type) {
|
||||
case 'html':
|
||||
|
@ -16,7 +22,7 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
}
|
||||
|
||||
function orderByClause(restParams, defaultSortField, allowedSortFields) {
|
||||
var sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
let sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
if (!sortField) {
|
||||
sortField = defaultSortField;
|
||||
}
|
||||
|
@ -28,8 +34,8 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
}
|
||||
|
||||
function limitOffsetClause(restParams) {
|
||||
var page = restParams._page;
|
||||
var perPage = restParams._perPage;
|
||||
const page = restParams._page;
|
||||
const perPage = restParams._perPage;
|
||||
|
||||
return {
|
||||
query: 'LIMIT ? OFFSET ?',
|
||||
|
@ -52,7 +58,7 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
};
|
||||
}
|
||||
|
||||
var query = _.join(
|
||||
let query = _.join(
|
||||
_.map(filterFields, function (field) {
|
||||
return 'LOWER(' + field + ') LIKE ?';
|
||||
}),
|
||||
|
@ -61,8 +67,8 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
|
||||
query += ' ESCAPE \'\\\'';
|
||||
|
||||
var search = '%' + (_.isString(restParams.q) ? escapeForLikePattern(_.toLower(restParams.q.trim())) : '') + '%';
|
||||
var params = _.times(filterFields.length, _.constant(search));
|
||||
const search = '%' + (_.isString(restParams.q) ? escapeForLikePattern(_.toLower(restParams.q.trim())) : '') + '%';
|
||||
const params = _.times(filterFields.length, _.constant(search));
|
||||
|
||||
return {
|
||||
query: query,
|
||||
|
@ -71,28 +77,28 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
}
|
||||
|
||||
function getConstrainedValues(data, constraints) {
|
||||
var values = {};
|
||||
const values = {};
|
||||
_.each(_.keys(constraints), function (key) {
|
||||
var value = data[key];
|
||||
const value = data[key];
|
||||
values[key] =
|
||||
_.isUndefined(value) && !_.isUndefined(constraints[key].default) ? constraints[key].default : value;
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
return {
|
||||
getData: function (req) {
|
||||
module.exports = {
|
||||
getData (req) {
|
||||
return _.extend({}, req.body, req.params, req.query);
|
||||
},
|
||||
|
||||
getValidRestParams: function(type, subtype, req, callback) {
|
||||
var constraints = Constraints.rest[type];
|
||||
getValidRestParams(type, subtype, req, callback) {
|
||||
const constraints = Constraints.rest[type];
|
||||
if (!_.isPlainObject(constraints)) {
|
||||
Logger.tag('validation', 'rest').error('Unknown REST resource type: {}', type);
|
||||
return callback({data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
var filterConstraints = {};
|
||||
let filterConstraints = {};
|
||||
if (subtype) {
|
||||
filterConstraints = Constraints[subtype + 'Filters'];
|
||||
if (!_.isPlainObject(filterConstraints)) {
|
||||
|
@ -101,13 +107,13 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
}
|
||||
}
|
||||
|
||||
var data = this.getData(req);
|
||||
const data = this.getData(req);
|
||||
|
||||
var restParams = getConstrainedValues(data, constraints);
|
||||
var filterParams = getConstrainedValues(data, filterConstraints);
|
||||
const restParams = getConstrainedValues(data, constraints);
|
||||
const filterParams = getConstrainedValues(data, filterConstraints);
|
||||
|
||||
var areValidParams = Validator.forConstraints(constraints);
|
||||
var areValidFilters = Validator.forConstraints(filterConstraints);
|
||||
const areValidParams = Validator.forConstraints(constraints);
|
||||
const areValidFilters = Validator.forConstraints(filterConstraints);
|
||||
if (!areValidParams(restParams) || !areValidFilters(filterParams)) {
|
||||
return callback({data: 'Invalid REST parameters.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
@ -117,8 +123,8 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
callback(null, restParams);
|
||||
},
|
||||
|
||||
filter: function (entities, allowedFilterFields, restParams) {
|
||||
var query = restParams.q;
|
||||
filter (entities, allowedFilterFields, restParams) {
|
||||
let query = restParams.q;
|
||||
if (query) {
|
||||
query = _.toLower(query.trim());
|
||||
}
|
||||
|
@ -128,7 +134,7 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
return true;
|
||||
}
|
||||
return _.some(allowedFilterFields, function (field) {
|
||||
var value = entity[field];
|
||||
let value = entity[field];
|
||||
if (_.isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
@ -146,7 +152,7 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
});
|
||||
}
|
||||
|
||||
var filters = restParams.filters;
|
||||
const filters = restParams.filters;
|
||||
|
||||
function filtersMatch(entity) {
|
||||
if (_.isEmpty(filters)) {
|
||||
|
@ -158,7 +164,7 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
return true;
|
||||
}
|
||||
if (_.startsWith(key, 'has')) {
|
||||
var entityKey = key.substr(3, 1).toLowerCase() + key.substr(4);
|
||||
const entityKey = key.substr(3, 1).toLowerCase() + key.substr(4);
|
||||
return _.isEmpty(entity[entityKey]).toString() !== value;
|
||||
}
|
||||
return entity[key] === value;
|
||||
|
@ -170,35 +176,35 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
});
|
||||
},
|
||||
|
||||
sort: function (entities, allowedSortFields, restParams) {
|
||||
var sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
sort (entities, allowedSortFields, restParams) {
|
||||
const sortField = _.includes(allowedSortFields, restParams._sortField) ? restParams._sortField : undefined;
|
||||
if (!sortField) {
|
||||
return entities;
|
||||
}
|
||||
|
||||
var sorted = _.sortBy(entities, [sortField]);
|
||||
const sorted = _.sortBy(entities, [sortField]);
|
||||
|
||||
return restParams._sortDir === 'ASC' ? sorted : _.reverse(sorted);
|
||||
},
|
||||
|
||||
getPageEntities: function (entities, restParams) {
|
||||
var page = restParams._page;
|
||||
var perPage = restParams._perPage;
|
||||
getPageEntities (entities, restParams) {
|
||||
const page = restParams._page;
|
||||
const perPage = restParams._perPage;
|
||||
|
||||
return entities.slice((page - 1) * perPage, page * perPage);
|
||||
},
|
||||
|
||||
whereCondition: filterCondition,
|
||||
|
||||
filterClause: function (restParams, defaultSortField, allowedSortFields, filterFields) {
|
||||
var orderBy = orderByClause(
|
||||
filterClause (restParams, defaultSortField, allowedSortFields, filterFields) {
|
||||
const orderBy = orderByClause(
|
||||
restParams,
|
||||
defaultSortField,
|
||||
allowedSortFields
|
||||
);
|
||||
var limitOffset = limitOffsetClause(restParams);
|
||||
const limitOffset = limitOffsetClause(restParams);
|
||||
|
||||
var filter = filterCondition(
|
||||
const filter = filterCondition(
|
||||
restParams,
|
||||
filterFields
|
||||
);
|
||||
|
@ -209,16 +215,15 @@ angular.module('ffffng').factory('Resources', function (_, Constraints, Validato
|
|||
};
|
||||
},
|
||||
|
||||
success: function (res, data) {
|
||||
success (res, data) {
|
||||
respond(res, 200, data, 'json');
|
||||
},
|
||||
|
||||
successHtml: function (res, html) {
|
||||
successHtml (res, html) {
|
||||
respond(res, 200, html, 'html');
|
||||
},
|
||||
|
||||
error: function (res, err) {
|
||||
error (res, err) {
|
||||
respond(res, err.type.code, err.data, 'json');
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Strings', function (_) {
|
||||
return {
|
||||
normalizeString: function (str) {
|
||||
const _ = require('lodash')
|
||||
|
||||
module.exports = {
|
||||
normalizeString (str) {
|
||||
return _.isString(str) ? str.trim().replace(/\s+/g, ' ') : str;
|
||||
},
|
||||
|
||||
normalizeMac: function (mac) {
|
||||
normalizeMac (mac) {
|
||||
// parts only contains values at odd indexes
|
||||
var parts = mac.toUpperCase().replace(/:/g, '').split(/([A-F0-9]{2})/);
|
||||
const parts = mac.toUpperCase().replace(/:/g, '').split(/([A-F0-9]{2})/);
|
||||
|
||||
var macParts = [];
|
||||
const macParts = [];
|
||||
|
||||
for (var i = 1; i < parts.length; i += 2) {
|
||||
for (let i = 1; i < parts.length; i += 2) {
|
||||
macParts.push(parts[i]);
|
||||
}
|
||||
|
||||
return macParts.join(':');
|
||||
},
|
||||
|
||||
parseInt: function (str) {
|
||||
var parsed = _.parseInt(str, 10);
|
||||
parseInt (str) {
|
||||
const parsed = _.parseInt(str, 10);
|
||||
return parsed.toString() === str ? parsed : undefined;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('UrlBuilder', function (_, config) {
|
||||
const _ = require('lodash')
|
||||
|
||||
const config = require('../config').config
|
||||
|
||||
function formUrl(route, queryParams) {
|
||||
var url = config.server.baseUrl;
|
||||
let url = config.server.baseUrl;
|
||||
if (route || queryParams) {
|
||||
url += '/#/';
|
||||
}
|
||||
|
@ -24,16 +27,15 @@ angular.module('ffffng').factory('UrlBuilder', function (_, config) {
|
|||
return url;
|
||||
}
|
||||
|
||||
return {
|
||||
editNodeUrl: function () {
|
||||
module.exports = {
|
||||
editNodeUrl () {
|
||||
return formUrl('update');
|
||||
},
|
||||
|
||||
monitoringConfirmUrl: function (nodeSecrets) {
|
||||
monitoringConfirmUrl (nodeSecrets) {
|
||||
return formUrl('monitoring/confirm', { token: nodeSecrets.monitoringToken });
|
||||
},
|
||||
monitoringDisableUrl: function (nodeSecrets) {
|
||||
monitoringDisableUrl (nodeSecrets) {
|
||||
return formUrl('monitoring/disable', { token: nodeSecrets.monitoringToken });
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').factory('Validator', function (_, Strings, Logger) {
|
||||
const _ = require('lodash')
|
||||
|
||||
const Strings = require('../utils/strings')
|
||||
const Logger = require('../logger')
|
||||
|
||||
// TODO: sanitize input for further processing as specified by constraints (correct types, trimming, etc.)
|
||||
|
||||
function isValidBoolean(value) {
|
||||
|
@ -44,7 +48,7 @@ angular.module('ffffng').factory('Validator', function (_, Strings, Logger) {
|
|||
return false;
|
||||
}
|
||||
|
||||
var trimmed = value.trim();
|
||||
const trimmed = value.trim();
|
||||
return (trimmed === '' && constraint.optional) || trimmed.match(constraint.regex);
|
||||
}
|
||||
|
||||
|
@ -72,9 +76,9 @@ angular.module('ffffng').factory('Validator', function (_, Strings, Logger) {
|
|||
}
|
||||
|
||||
function areValid(constraints, acceptUndefined, values) {
|
||||
var fields = Object.keys(constraints);
|
||||
for (var i = 0; i < fields.length; i ++) {
|
||||
var field = fields[i];
|
||||
const fields = Object.keys(constraints);
|
||||
for (let i = 0; i < fields.length; i ++) {
|
||||
const field = fields[i];
|
||||
if (!isValid(constraints[field], acceptUndefined, values[field])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -82,12 +86,11 @@ angular.module('ffffng').factory('Validator', function (_, Strings, Logger) {
|
|||
return true;
|
||||
}
|
||||
|
||||
return {
|
||||
forConstraint: function (constraint, acceptUndefined) {
|
||||
module.exports = {
|
||||
forConstraint (constraint, acceptUndefined) {
|
||||
return _.partial(isValid, constraint, acceptUndefined);
|
||||
},
|
||||
forConstraints: function (constraints, acceptUndefined) {
|
||||
forConstraints (constraints, acceptUndefined) {
|
||||
return _.partial(areValid, constraints, acceptUndefined);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('ffffng').constant('Constraints', {
|
||||
(function () {
|
||||
var constraints = {
|
||||
id:{
|
||||
type: 'string',
|
||||
regex: /^[1-9][0-9]*/,
|
||||
|
@ -110,4 +111,29 @@ angular.module('ffffng').constant('Constraints', {
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let _angular = null
|
||||
try {
|
||||
_angular = angular
|
||||
}
|
||||
catch (error) {
|
||||
// ReferenceError, as angular is not defined.
|
||||
}
|
||||
|
||||
let _module = null
|
||||
try {
|
||||
_module = module
|
||||
}
|
||||
catch (error) {
|
||||
// ReferenceError, as module is not defined.
|
||||
}
|
||||
|
||||
if (_angular) {
|
||||
angular.module('ffffng').constant('Constraints', constraints)
|
||||
}
|
||||
|
||||
if (_module) {
|
||||
module.exports = constraints
|
||||
}
|
||||
})()
|
||||
|
|
Loading…
Reference in a new issue