Removing ng-di on the server.
This commit is contained in:
parent
ddb2f47a9d
commit
8697d79ba5
37 changed files with 2730 additions and 2770 deletions
|
|
@ -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,24 +32,24 @@ 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'
|
||||
];
|
||||
|
||||
router.use(compress());
|
||||
|
||||
function serveTemplate(mimeType, req, res, next) {
|
||||
function serveTemplate (mimeType, req, res, next) {
|
||||
return fs.readFile(templateDir + '/' + req.path, 'utf8', function (err, body) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.writeHead(200, {'Content-Type': mimeType});
|
||||
res.end(_.template(body)( { config: config.client }));
|
||||
res.writeHead(200, { 'Content-Type': mimeType });
|
||||
res.end(_.template(body)({ config: config.client }));
|
||||
|
||||
return null; // to suppress warning
|
||||
});
|
||||
|
|
@ -63,4 +68,4 @@ angular.module('ffffng').factory('app', function (fs, config, _) {
|
|||
app.use(config.server.rootPath, router);
|
||||
|
||||
return app;
|
||||
});
|
||||
})()
|
||||
|
|
|
|||
258
server/config.js
258
server/config.js
|
|
@ -1,156 +1,158 @@
|
|||
'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 = [
|
||||
{ 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' }
|
||||
];
|
||||
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;
|
||||
try {
|
||||
commandLineOptions = commandLineArgs(commandLineDefs);
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
console.error('Try \'--help\' for more information.');
|
||||
process.exit(1);
|
||||
}
|
||||
let commandLineOptions;
|
||||
try {
|
||||
commandLineOptions = commandLineArgs(commandLineDefs);
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
console.error('Try \'--help\' for more information.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var fs = require('graceful-fs');
|
||||
const fs = require('graceful-fs');
|
||||
|
||||
var packageJsonFile = __dirname + '/../package.json';
|
||||
var version = 'unknown';
|
||||
if (fs.existsSync(packageJsonFile)) {
|
||||
version = JSON.parse(fs.readFileSync(packageJsonFile, 'utf8')).version;
|
||||
}
|
||||
const packageJsonFile = __dirname + '/../package.json';
|
||||
let version = 'unknown';
|
||||
if (fs.existsSync(packageJsonFile)) {
|
||||
version = JSON.parse(fs.readFileSync(packageJsonFile, 'utf8')).version;
|
||||
}
|
||||
|
||||
function usage() {
|
||||
console.log(commandLineUsage([
|
||||
{
|
||||
header: 'ffffng - ' + version + ' - Freifunk node management form',
|
||||
optionList: commandLineDefs
|
||||
}
|
||||
]));
|
||||
}
|
||||
function usage () {
|
||||
console.log(commandLineUsage([
|
||||
{
|
||||
header: 'ffffng - ' + version + ' - Freifunk node management form',
|
||||
optionList: commandLineDefs
|
||||
}
|
||||
]));
|
||||
}
|
||||
|
||||
if (commandLineOptions.help) {
|
||||
usage();
|
||||
process.exit(0);
|
||||
}
|
||||
if (commandLineOptions.help) {
|
||||
usage();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (commandLineOptions.version) {
|
||||
console.log('ffffng - ' + version);
|
||||
process.exit(0);
|
||||
}
|
||||
if (commandLineOptions.version) {
|
||||
console.log('ffffng - ' + version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!commandLineOptions.config) {
|
||||
usage();
|
||||
process.exit(1);
|
||||
}
|
||||
if (!commandLineOptions.config) {
|
||||
usage();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var deepExtend = require('deep-extend');
|
||||
const deepExtend = require('deep-extend');
|
||||
|
||||
var defaultConfig = {
|
||||
server: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
port: 8080,
|
||||
const defaultConfig = {
|
||||
server: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
port: 8080,
|
||||
|
||||
databaseFile: '/tmp/ffffng.sqlite',
|
||||
peersPath: '/tmp/peers',
|
||||
databaseFile: '/tmp/ffffng.sqlite',
|
||||
peersPath: '/tmp/peers',
|
||||
|
||||
logging: {
|
||||
directory: '/tmp/logs',
|
||||
debug: false,
|
||||
profile: false,
|
||||
logRequests: false
|
||||
},
|
||||
logging: {
|
||||
directory: '/tmp/logs',
|
||||
debug: false,
|
||||
profile: false,
|
||||
logRequests: false
|
||||
},
|
||||
|
||||
internal: {
|
||||
active: false,
|
||||
user: 'admin',
|
||||
password: 'secret'
|
||||
},
|
||||
internal: {
|
||||
active: false,
|
||||
user: 'admin',
|
||||
password: 'secret'
|
||||
},
|
||||
|
||||
email: {
|
||||
from: 'Freifunk Knotenformular <no-reply@musterstadt.freifunk.net>',
|
||||
email: {
|
||||
from: 'Freifunk Knotenformular <no-reply@musterstadt.freifunk.net>',
|
||||
|
||||
// For details see: https://nodemailer.com/2-0-0-beta/setup-smtp/
|
||||
smtp: {
|
||||
host: 'mail.example.com',
|
||||
port: '465',
|
||||
secure: true,
|
||||
auth: {
|
||||
user: 'user@example.com',
|
||||
pass: 'pass'
|
||||
// For details see: https://nodemailer.com/2-0-0-beta/setup-smtp/
|
||||
smtp: {
|
||||
host: 'mail.example.com',
|
||||
port: '465',
|
||||
secure: true,
|
||||
auth: {
|
||||
user: 'user@example.com',
|
||||
pass: 'pass'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
map: {
|
||||
nodesJsonUrl: ['http://map.musterstadt.freifunk.net/nodes.json']
|
||||
}
|
||||
},
|
||||
|
||||
map: {
|
||||
nodesJsonUrl: ['http://map.musterstadt.freifunk.net/nodes.json']
|
||||
client: {
|
||||
community: {
|
||||
name: 'Freifunk Musterstadt',
|
||||
domain: 'musterstadt.freifunk.net',
|
||||
contactEmail: 'kontakt@musterstadt.freifunk.net',
|
||||
sites: [],
|
||||
domains: []
|
||||
},
|
||||
legal: {
|
||||
privacyUrl: null,
|
||||
imprintUrl: null
|
||||
},
|
||||
map: {
|
||||
mapUrl: 'http://map.musterstadt.freifunk.net'
|
||||
},
|
||||
monitoring: {
|
||||
enabled: false
|
||||
},
|
||||
coordsSelector: {
|
||||
showInfo: false,
|
||||
showBorderForDebugging: false,
|
||||
localCommunityPolygon: [],
|
||||
lat: 53.565278,
|
||||
lng: 10.001389,
|
||||
defaultZoom: 10,
|
||||
layers: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
client: {
|
||||
community: {
|
||||
name: 'Freifunk Musterstadt',
|
||||
domain: 'musterstadt.freifunk.net',
|
||||
contactEmail: 'kontakt@musterstadt.freifunk.net',
|
||||
sites: [],
|
||||
domains: []
|
||||
},
|
||||
legal: {
|
||||
privacyUrl: null,
|
||||
imprintUrl: null
|
||||
},
|
||||
map: {
|
||||
mapUrl: 'http://map.musterstadt.freifunk.net'
|
||||
},
|
||||
monitoring: {
|
||||
enabled: false
|
||||
},
|
||||
coordsSelector: {
|
||||
showInfo: false,
|
||||
showBorderForDebugging: false,
|
||||
localCommunityPolygon: [],
|
||||
lat: 53.565278,
|
||||
lng: 10.001389,
|
||||
defaultZoom: 10,
|
||||
layers: {}
|
||||
};
|
||||
|
||||
const configJSONFile = commandLineOptions.config;
|
||||
let configJSON = {};
|
||||
|
||||
if (fs.existsSync(configJSONFile)) {
|
||||
configJSON = JSON.parse(fs.readFileSync(configJSONFile, 'utf8'));
|
||||
} else {
|
||||
console.error('config.json not found: ' + configJSONFile);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
function stripTrailingSlash (obj, field) {
|
||||
const url = obj[field];
|
||||
if (_.isString(url) && _.last(url) === '/') {
|
||||
obj[field] = url.substr(0, url.length - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var configJSONFile = commandLineOptions.config;
|
||||
var configJSON = {};
|
||||
const config = deepExtend({}, defaultConfig, configJSON);
|
||||
|
||||
if (fs.existsSync(configJSONFile)) {
|
||||
configJSON = JSON.parse(fs.readFileSync(configJSONFile, 'utf8'));
|
||||
} else {
|
||||
console.error('config.json not found: ' + configJSONFile);
|
||||
process.exit(1);
|
||||
}
|
||||
stripTrailingSlash(config.server, 'baseUrl');
|
||||
stripTrailingSlash(config.client.map, 'mapUrl');
|
||||
|
||||
var _ = require('lodash');
|
||||
const url = require('url');
|
||||
config.server.rootPath = url.parse(config.server.baseUrl).pathname;
|
||||
config.client.rootPath = config.server.rootPath;
|
||||
|
||||
function stripTrailingSlash(obj, field) {
|
||||
var url = obj[field];
|
||||
if (_.isString(url) && _.last(url) === '/') {
|
||||
obj[field] = url.substr(0, url.length - 1);
|
||||
return {
|
||||
config,
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
var config = deepExtend({}, defaultConfig, configJSON);
|
||||
|
||||
stripTrailingSlash(config.server, 'baseUrl');
|
||||
stripTrailingSlash(config.client.map, 'mapUrl');
|
||||
|
||||
var 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);
|
||||
})()
|
||||
|
|
|
|||
|
|
@ -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,98 +1,99 @@
|
|||
'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 = {};
|
||||
let taskId = 1;
|
||||
function nextTaskId() {
|
||||
const id = taskId;
|
||||
taskId += 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
var taskId = 1;
|
||||
function nextTaskId() {
|
||||
var id = taskId;
|
||||
taskId += 1;
|
||||
return id;
|
||||
function schedule(expr, jobName) {
|
||||
Logger.tag('jobs').info('Scheduling job: %s %s', expr, jobName);
|
||||
|
||||
var job = require(`../jobs/${jobName}`);
|
||||
|
||||
if (!_.isFunction(job.run)) {
|
||||
throw new Error('The job ' + jobName + ' does not provide a "run" function.');
|
||||
}
|
||||
|
||||
function schedule(expr, jobName) {
|
||||
Logger.tag('jobs').info('Scheduling job: %s %s', expr, jobName);
|
||||
|
||||
var job = $injector.get(jobName);
|
||||
|
||||
if (!_.isFunction(job.run)) {
|
||||
throw new Error('The job ' + jobName + ' does not provide a "run" function.');
|
||||
}
|
||||
|
||||
var id = nextTaskId();
|
||||
var task = {
|
||||
id: id,
|
||||
name: jobName,
|
||||
description: job.description,
|
||||
schedule: expr,
|
||||
job: job,
|
||||
runningSince: false,
|
||||
lastRunStarted: false,
|
||||
lastRunDuration: null,
|
||||
state: 'idle',
|
||||
enabled: true
|
||||
};
|
||||
|
||||
task.run = function () {
|
||||
if (task.runningSince || !task.enabled) {
|
||||
// job is still running, skip execution
|
||||
return;
|
||||
}
|
||||
|
||||
task.runningSince = moment();
|
||||
task.lastRunStarted = task.runningSince;
|
||||
task.state = 'running';
|
||||
|
||||
job.run(function () {
|
||||
var now = moment();
|
||||
var duration = now.diff(task.runningSince);
|
||||
Logger.tag('jobs').profile('[%sms]\t%s', duration, task.name);
|
||||
|
||||
task.runningSince = false;
|
||||
task.lastRunDuration = duration;
|
||||
task.state = 'idle';
|
||||
});
|
||||
};
|
||||
|
||||
cron.schedule(expr, task.run);
|
||||
|
||||
tasks['' + id] = task;
|
||||
}
|
||||
|
||||
return {
|
||||
init: function () {
|
||||
Logger.tag('jobs').info('Scheduling background jobs...');
|
||||
|
||||
try {
|
||||
schedule('0 */1 * * * *', 'MailQueueJob');
|
||||
schedule('15 */1 * * * *', 'FixNodeFilenamesJob');
|
||||
|
||||
if (config.client.monitoring.enabled) {
|
||||
schedule('30 */15 * * * *', 'NodeInformationRetrievalJob');
|
||||
schedule('45 */5 * * * *', 'MonitoringMailsSendingJob');
|
||||
schedule('0 0 3 * * *', 'OfflineNodesDeletionJob'); // every night at 3:00
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
Logger.tag('jobs').error('Error during scheduling of background jobs:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
Logger.tag('jobs').info('Scheduling of background jobs done.');
|
||||
},
|
||||
|
||||
getTasks: function () {
|
||||
return tasks;
|
||||
}
|
||||
var id = nextTaskId();
|
||||
var task = {
|
||||
id: id,
|
||||
name: jobName,
|
||||
description: job.description,
|
||||
schedule: expr,
|
||||
job: job,
|
||||
runningSince: false,
|
||||
lastRunStarted: false,
|
||||
lastRunDuration: null,
|
||||
state: 'idle',
|
||||
enabled: true
|
||||
};
|
||||
});
|
||||
|
||||
task.run = function () {
|
||||
if (task.runningSince || !task.enabled) {
|
||||
// job is still running, skip execution
|
||||
return;
|
||||
}
|
||||
|
||||
task.runningSince = moment();
|
||||
task.lastRunStarted = task.runningSince;
|
||||
task.state = 'running';
|
||||
|
||||
job.run(function () {
|
||||
var now = moment();
|
||||
var duration = now.diff(task.runningSince);
|
||||
Logger.tag('jobs').profile('[%sms]\t%s', duration, task.name);
|
||||
|
||||
task.runningSince = false;
|
||||
task.lastRunDuration = duration;
|
||||
task.state = 'idle';
|
||||
});
|
||||
};
|
||||
|
||||
cron.schedule(expr, task.run);
|
||||
|
||||
tasks['' + id] = task;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function () {
|
||||
Logger.tag('jobs').info('Scheduling background jobs...');
|
||||
|
||||
try {
|
||||
schedule('0 */1 * * * *', 'MailQueueJob');
|
||||
schedule('15 */1 * * * *', 'FixNodeFilenamesJob');
|
||||
|
||||
if (config.client.monitoring.enabled) {
|
||||
schedule('30 */15 * * * *', 'NodeInformationRetrievalJob');
|
||||
schedule('45 */5 * * * *', 'MonitoringMailsSendingJob');
|
||||
schedule('0 0 3 * * *', 'OfflineNodesDeletionJob'); // every night at 3:00
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
Logger.tag('jobs').error('Error during scheduling of background jobs:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
Logger.tag('jobs').info('Scheduling of background jobs done.');
|
||||
},
|
||||
|
||||
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,30 +33,26 @@ 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;
|
||||
app.use(prefix + '/internal/logs', scribe.webPanel());
|
||||
}
|
||||
if (config.server.logging.logRequests) {
|
||||
app.use(scribe.express.logger());
|
||||
}
|
||||
if (config.server.internal.active) {
|
||||
const prefix = config.server.rootPath === '/' ? '' : config.server.rootPath;
|
||||
app.use(prefix + '/internal/logs', scribe.webPanel());
|
||||
}
|
||||
|
||||
// Hack to allow correct logging of node.js Error objects.
|
||||
// See: https://github.com/bluejamesbond/Scribe.js/issues/70
|
||||
Object.defineProperty(Error.prototype, 'toJSON', {
|
||||
configurable: true,
|
||||
value: function () {
|
||||
var alt = {};
|
||||
var storeKey = function (key) {
|
||||
alt[key] = this[key];
|
||||
};
|
||||
Object.getOwnPropertyNames(this).forEach(storeKey, this);
|
||||
return alt;
|
||||
}
|
||||
});
|
||||
|
||||
return process.console;
|
||||
// Hack to allow correct logging of node.js Error objects.
|
||||
// See: https://github.com/bluejamesbond/Scribe.js/issues/70
|
||||
Object.defineProperty(Error.prototype, 'toJSON', {
|
||||
configurable: true,
|
||||
value: function () {
|
||||
const alt = {};
|
||||
const storeKey = function (key) {
|
||||
alt[key] = this[key];
|
||||
};
|
||||
Object.getOwnPropertyNames(this).forEach(storeKey, this);
|
||||
return alt;
|
||||
}
|
||||
});
|
||||
|
||||
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('./db/database').init()
|
||||
.then(() => {
|
||||
Logger.tag('main').info('Initializing...');
|
||||
|
||||
require('./utils/databaseUtil');
|
||||
require('./utils/errorTypes');
|
||||
require('./utils/resources');
|
||||
require('./utils/strings');
|
||||
require('./utils/urlBuilder');
|
||||
const app = require('./app');
|
||||
|
||||
require('./resources/versionResource');
|
||||
require('./resources/statisticsResource');
|
||||
require('./resources/frontendResource');
|
||||
require('./resources/taskResource');
|
||||
require('./resources/mailResource');
|
||||
require('./resources/nodeResource');
|
||||
require('./resources/monitoringResource');
|
||||
require('./jobs/scheduler').init();
|
||||
require('./router').init();
|
||||
|
||||
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) {
|
||||
Logger.tag('main').info('Initializing...');
|
||||
|
||||
Scheduler.init();
|
||||
Router.init();
|
||||
|
||||
app.listen(config.server.port, '::');
|
||||
module.exports = app;
|
||||
});
|
||||
}).catch(error => {
|
||||
app.listen(config.server.port, '::');
|
||||
module.exports = app;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Could not init database: ', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
'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')
|
||||
|
||||
fs.readFile(indexHtml, 'utf8', function (err, body) {
|
||||
if (err) {
|
||||
Logger.tag('frontend').error('Could not read file: ', indexHtml, err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
const indexHtml = __dirname + '/../../client/index.html';
|
||||
|
||||
return Resources.successHtml(
|
||||
res,
|
||||
body.replace(
|
||||
/<body/,
|
||||
'<script>window.__nodeToken = \''+ data.token + '\';</script><body'
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
render (req, res) {
|
||||
const data = Resources.getData(req);
|
||||
|
||||
fs.readFile(indexHtml, 'utf8', function (err, body) {
|
||||
if (err) {
|
||||
Logger.tag('frontend').error('Could not read file: ', indexHtml, err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
return Resources.successHtml(
|
||||
res,
|
||||
body.replace(
|
||||
/<body/,
|
||||
'<script>window.__nodeToken = \''+ data.token + '\';</script><body'
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,101 +1,99 @@
|
|||
'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')
|
||||
|
||||
function withValidMailId(req, res, callback) {
|
||||
var id = Strings.normalizeString(Resources.getData(req).id);
|
||||
const isValidId = Validator.forConstraint(Constraints.id);
|
||||
|
||||
if (!isValidId(id)) {
|
||||
return callback({data: 'Invalid mail id.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
function withValidMailId(req, res, callback) {
|
||||
const id = Strings.normalizeString(Resources.getData(req).id);
|
||||
|
||||
callback(null, id);
|
||||
if (!isValidId(id)) {
|
||||
return callback({data: 'Invalid mail id.', type: ErrorTypes.badRequest});
|
||||
}
|
||||
|
||||
return {
|
||||
get: function (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
callback(null, id);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
MailService.getMail(id, function (err, mail) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
Logger.tag('mails', 'admin').error('Error getting mail:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
MailService.getMail(id, function (err, mail) {
|
||||
if (!mail) {
|
||||
return Resources.error(res, {data: 'Mail not found.', type: ErrorTypes.notFound});
|
||||
}
|
||||
|
||||
return Resources.success(res, mail);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getAll (req, res) {
|
||||
Resources.getValidRestParams('list', null, req, function (err, restParams) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
return MailService.getPendingMails(
|
||||
restParams,
|
||||
function (err, mails, total) {
|
||||
if (err) {
|
||||
Logger.tag('mails', 'admin').error('Error getting mail:', err);
|
||||
Logger.tag('mails', 'admin').error('Could not get pending mails:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
if (!mail) {
|
||||
return Resources.error(res, {data: 'Mail not found.', type: ErrorTypes.notFound});
|
||||
}
|
||||
res.set('X-Total-Count', total);
|
||||
return Resources.success(res, mails);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
return Resources.success(res, mail);
|
||||
});
|
||||
});
|
||||
},
|
||||
delete (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
getAll: function (req, res) {
|
||||
Resources.getValidRestParams('list', null, req, function (err, restParams) {
|
||||
MailService.deleteMail(id, function (err) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
Logger.tag('mails', 'admin').error('Error deleting mail:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
return MailService.getPendingMails(
|
||||
restParams,
|
||||
function (err, mails, total) {
|
||||
if (err) {
|
||||
Logger.tag('mails', 'admin').error('Could not get pending mails:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
res.set('X-Total-Count', total);
|
||||
return Resources.success(res, mails);
|
||||
}
|
||||
);
|
||||
return Resources.success(res);
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
delete: function (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
resetFailures (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
MailService.resetFailures(id, function (err, mail) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
Logger.tag('mails', 'admin').error('Error resetting failure count:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
MailService.deleteMail(id, function (err) {
|
||||
if (err) {
|
||||
Logger.tag('mails', 'admin').error('Error deleting mail:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
return Resources.success(res);
|
||||
});
|
||||
return Resources.success(res, mail);
|
||||
});
|
||||
},
|
||||
|
||||
resetFailures: function (req, res) {
|
||||
withValidMailId(req, res, function (err, id) {
|
||||
if (err) {
|
||||
return Resources.error(res, err);
|
||||
}
|
||||
|
||||
MailService.resetFailures(id, function (err, mail) {
|
||||
if (err) {
|
||||
Logger.tag('mails', 'admin').error('Error resetting failure count:', err);
|
||||
return Resources.error(res, {data: 'Internal error.', type: ErrorTypes.internalError});
|
||||
}
|
||||
|
||||
return Resources.success(res, mail);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue