diff --git a/src/apphealthmonitor.js b/src/apphealthmonitor.js index c9daaba38..22332312b 100644 --- a/src/apphealthmonitor.js +++ b/src/apphealthmonitor.js @@ -4,6 +4,7 @@ var appdb = require('./appdb.js'), apps = require('./apps.js'), assert = require('assert'), async = require('async'), + auditSource = require('./auditsource.js'), DatabaseError = require('./databaseerror.js'), debug = require('debug')('box:apphealthmonitor'), docker = require('./docker.js'), @@ -22,8 +23,6 @@ const UNHEALTHY_THRESHOLD = 10 * 60 * 1000; // 10 minutes const OOM_EVENT_LIMIT = 60 * 60 * 1000; // 60 minutes let gLastOomMailTime = Date.now() - (5 * 60 * 1000); // pretend we sent email 5 minutes ago -const AUDIT_SOURCE = { userId: null, username: 'healthmonitor' }; - function debugApp(app) { assert(typeof app === 'object'); @@ -43,14 +42,14 @@ function setHealth(app, health, callback) { debugApp(app, 'app switched from %s to healthy', curHealth); // do not send mails for dev apps - if (!app.debugMode) eventlog.add(eventlog.ACTION_APP_UP, AUDIT_SOURCE, { app: app }); + if (!app.debugMode) eventlog.add(eventlog.ACTION_APP_UP, auditSource.HEALTH_MONITOR, { app: app }); } } else if (Math.abs(now - healthTime) > UNHEALTHY_THRESHOLD) { if (curHealth === appdb.HEALTH_HEALTHY) { debugApp(app, 'marking as unhealthy since not seen for more than %s minutes', UNHEALTHY_THRESHOLD/(60 * 1000)); // do not send mails for dev apps - if (!app.debugMode) eventlog.add(eventlog.ACTION_APP_DOWN, AUDIT_SOURCE, { app: app }); + if (!app.debugMode) eventlog.add(eventlog.ACTION_APP_DOWN, auditSource.HEALTH_MONITOR, { app: app }); } } else { debugApp(app, 'waiting for %s seconds to update the app health', (UNHEALTHY_THRESHOLD - Math.abs(now - healthTime))/1000); @@ -159,7 +158,7 @@ function processDockerEvents(intervalSecs, callback) { // do not send mails for dev apps if (notifyUser) { // app can be null for addon containers - eventlog.add(eventlog.ACTION_APP_OOM, AUDIT_SOURCE, { event: event, containerId: containerId, addon: addon || null, app: app || null }); + eventlog.add(eventlog.ACTION_APP_OOM, auditSource.HEALTH_MONITOR, { event: event, containerId: containerId, addon: addon || null, app: app || null }); gLastOomMailTime = now; } diff --git a/src/auditsource.js b/src/auditsource.js index 26d54a9bd..c9a0bc608 100644 --- a/src/auditsource.js +++ b/src/auditsource.js @@ -1,5 +1,15 @@ 'use strict'; exports = module.exports = { - CRON: { userId: null, username: 'cron' } + CRON: { userId: null, username: 'cron' }, + HEALTH_MONITOR: { userId: null, username: 'healthmonitor' }, + SYSADMIN: { userId: null, username: 'sysadmin' }, + TASK_MANAGER: { userId: null, username: 'taskmanager' }, + + fromRequest: fromRequest }; + +function fromRequest(req) { + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; + return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; +} diff --git a/src/crashnotifier.js b/src/crashnotifier.js index 4c3cfe33e..686068afb 100644 --- a/src/crashnotifier.js +++ b/src/crashnotifier.js @@ -5,6 +5,7 @@ exports = module.exports = { }; var assert = require('assert'), + auditSource = require('./auditsource.js'), eventlog = require('./eventlog.js'), safe = require('safetydance'), path = require('path'), @@ -16,8 +17,6 @@ const COLLECT_LOGS_CMD = path.join(__dirname, 'scripts/collectlogs.sh'); const CRASH_LOG_TIMESTAMP_OFFSET = 1000 * 60 * 60; // 60 min const CRASH_LOG_TIMESTAMP_FILE = '/tmp/crashlog.timestamp'; -const AUDIT_SOURCE = { userId: null, username: 'healthmonitor' }; - function collectLogs(unitName, callback) { assert.strictEqual(typeof unitName, 'string'); assert.strictEqual(typeof callback, 'function'); @@ -50,7 +49,7 @@ function sendFailureLogs(unitName, callback) { if (!safe.fs.writeFileSync(path.join(paths.CRASH_LOG_DIR, `${crashId}.log`), logs)) console.log(`Failed to stash logs to ${crashId}.log:`, safe.error); - eventlog.add(eventlog.ACTION_PROCESS_CRASH, AUDIT_SOURCE, { processName: unitName, crashId: crashId }, function (error) { + eventlog.add(eventlog.ACTION_PROCESS_CRASH, auditSource.HEALTH_MONITOR, { processName: unitName, crashId: crashId }, function (error) { if (error) console.log(`Error sending crashlog. Logs stashed at ${crashId}.log`); safe.fs.writeFileSync(CRASH_LOG_TIMESTAMP_FILE, String(Date.now())); diff --git a/src/routes/apps.js b/src/routes/apps.js index 3e236a183..32b350a36 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -32,6 +32,7 @@ exports = module.exports = { var apps = require('../apps.js'), AppsError = apps.AppsError, assert = require('assert'), + auditSource = require('../auditsource.js'), config = require('../config.js'), debug = require('debug')('box:routes/apps'), fs = require('fs'), @@ -42,11 +43,6 @@ var apps = require('../apps.js'), util = require('util'), WebSocket = require('ws'); -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function verifyOwnership(req, res, next) { if (req.user.admin) return next(); @@ -158,7 +154,7 @@ function installApp(req, res, next) { debug('Installing app :%j', data); - apps.install(data, req.user, auditSource(req), function (error, app) { + apps.install(data, req.user, auditSource.fromRequest(req), function (error, app) { if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.')); @@ -226,7 +222,7 @@ function configureApp(req, res, next) { debug('Configuring app id:%s data:%j', req.params.id, data); - apps.configure(req.params.id, data, req.user, auditSource(req), function (error) { + apps.configure(req.params.id, data, req.user, auditSource.fromRequest(req), function (error) { if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.')); if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.')); @@ -251,7 +247,7 @@ function restoreApp(req, res, next) { if (!('backupId' in req.body)) return next(new HttpError(400, 'backupId is required')); if (data.backupId !== null && typeof data.backupId !== 'string') return next(new HttpError(400, 'backupId must be string or null')); - apps.restore(req.params.id, data, auditSource(req), function (error) { + apps.restore(req.params.id, data, auditSource.fromRequest(req), function (error) { if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app')); if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message)); @@ -276,7 +272,7 @@ function cloneApp(req, res, next) { if (typeof data.domain !== 'string') return next(new HttpError(400, 'domain is required')); if (('portBindings' in data) && typeof data.portBindings !== 'object') return next(new HttpError(400, 'portBindings must be an object')); - apps.clone(req.params.id, data, req.user, auditSource(req), function (error, result) { + apps.clone(req.params.id, data, req.user, auditSource.fromRequest(req), function (error, result) { if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app')); if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.')); if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.')); @@ -312,7 +308,7 @@ function uninstallApp(req, res, next) { debug('Uninstalling app id:%s', req.params.id); - apps.uninstall(req.params.id, auditSource(req), function (error) { + apps.uninstall(req.params.id, auditSource.fromRequest(req), function (error) { if (error && error.reason === AppsError.BILLING_REQUIRED) return next(new HttpError(402, 'Billing required')); if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app')); if (error) return next(new HttpError(500, error)); @@ -365,7 +361,7 @@ function updateApp(req, res, next) { debug('Update app id:%s to manifest:%j', req.params.id, data.manifest); - apps.update(req.params.id, req.body, auditSource(req), function (error) { + apps.update(req.params.id, req.body, auditSource.fromRequest(req), function (error) { if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app')); if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message)); diff --git a/src/routes/backups.js b/src/routes/backups.js index ff9942aeb..e6c160ab6 100644 --- a/src/routes/backups.js +++ b/src/routes/backups.js @@ -5,17 +5,13 @@ exports = module.exports = { startBackup: startBackup }; -var backupdb = require('../backupdb.js'), +let auditSource = require('../auditsource.js'), + backupdb = require('../backupdb.js'), backups = require('../backups.js'), BackupsError = require('../backups.js').BackupsError, HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess; -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function list(req, res, next) { var page = typeof req.query.page !== 'undefined' ? parseInt(req.query.page) : 1; if (!page || page < 0) return next(new HttpError(400, 'page query param has to be a postive number')); @@ -32,7 +28,7 @@ function list(req, res, next) { } function startBackup(req, res, next) { - backups.startBackupTask(auditSource(req), function (error, taskId) { + backups.startBackupTask(auditSource.fromRequest(req), function (error, taskId) { if (error && error.reason === BackupsError.BAD_STATE) return next(new HttpError(409, error.message)); if (error) return next(new HttpError(500, error)); diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 12c53ee59..a994efadc 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -17,6 +17,7 @@ exports = module.exports = { let assert = require('assert'), async = require('async'), + auditSource = require('../auditsource.js'), cloudron = require('../cloudron.js'), CloudronError = cloudron.CloudronError, HttpError = require('connect-lastmile').HttpError, @@ -25,11 +26,6 @@ let assert = require('assert'), updateChecker = require('../updatechecker.js'), UpdaterError = require('../updater.js').UpdaterError; -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function reboot(req, res, next) { // Finish the request, to let the appstore know we triggered the reboot next(new HttpSuccess(202, {})); @@ -62,7 +58,7 @@ function getDisks(req, res, next) { function update(req, res, next) { // this only initiates the update, progress can be checked via the progress route - updater.updateToLatest(auditSource(req), function (error, taskId) { + updater.updateToLatest(auditSource.fromRequest(req), function (error, taskId) { if (error && error.reason === UpdaterError.ALREADY_UPTODATE) return next(new HttpError(422, error.message)); if (error && error.reason === UpdaterError.BAD_STATE) return next(new HttpError(409, error.message)); if (error) return next(new HttpError(500, error)); @@ -154,7 +150,7 @@ function getLogStream(req, res, next) { function setDashboardAndMailDomain(req, res, next) { if (!req.body.domain || typeof req.body.domain !== 'string') return next(new HttpError(400, 'domain must be a string')); - cloudron.setDashboardAndMailDomain(req.body.domain, auditSource(req), function (error) { + cloudron.setDashboardAndMailDomain(req.body.domain, auditSource.fromRequest(req), function (error) { if (error && error.reason === CloudronError.BAD_FIELD) return next(new HttpError(404, error.message)); if (error) return next(new HttpError(500, error)); @@ -165,7 +161,7 @@ function setDashboardAndMailDomain(req, res, next) { function prepareDashboardDomain(req, res, next) { if (!req.body.domain || typeof req.body.domain !== 'string') return next(new HttpError(400, 'domain must be a string')); - cloudron.prepareDashboardDomain(req.body.domain, auditSource(req), function (error, taskId) { + cloudron.prepareDashboardDomain(req.body.domain, auditSource.fromRequest(req), function (error, taskId) { if (error && error.reason === CloudronError.BAD_FIELD) return next(new HttpError(404, error.message)); if (error && error.reason === CloudronError.BAD_STATE) return next(new HttpError(409, error.message)); if (error) return next(new HttpError(500, error)); @@ -175,7 +171,7 @@ function prepareDashboardDomain(req, res, next) { } function renewCerts(req, res, next) { - cloudron.renewCerts({ domain: req.body.domain || null }, auditSource(req), function (error, taskId) { + cloudron.renewCerts({ domain: req.body.domain || null }, auditSource.fromRequest(req), function (error, taskId) { if (error && error.reason === CloudronError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error) return next(new HttpError(500, error)); diff --git a/src/routes/domains.js b/src/routes/domains.js index 9cabdee49..dd63360a1 100644 --- a/src/routes/domains.js +++ b/src/routes/domains.js @@ -11,16 +11,12 @@ exports = module.exports = { }; var assert = require('assert'), + auditSource = require('../auditsource.js'), domains = require('../domains.js'), DomainsError = domains.DomainsError, HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess; -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function verifyDomainLock(req, res, next) { assert.strictEqual(typeof req.params.domain, 'string'); @@ -69,7 +65,7 @@ function add(req, res, next) { tlsConfig: req.body.tlsConfig || { provider: 'letsencrypt-prod' } }; - domains.add(req.body.domain, data, auditSource(req), function (error) { + domains.add(req.body.domain, data, auditSource.fromRequest(req), function (error) { if (error && error.reason === DomainsError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === DomainsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === DomainsError.INVALID_PROVIDER) return next(new HttpError(400, error.message)); @@ -135,7 +131,7 @@ function update(req, res, next) { tlsConfig: req.body.tlsConfig || { provider: 'letsencrypt-prod' } }; - domains.update(req.params.domain, data, auditSource(req), function (error) { + domains.update(req.params.domain, data, auditSource.fromRequest(req), function (error) { if (error && error.reason === DomainsError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error && error.reason === DomainsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === DomainsError.INVALID_PROVIDER) return next(new HttpError(400, error.message)); @@ -148,7 +144,7 @@ function update(req, res, next) { function del(req, res, next) { assert.strictEqual(typeof req.params.domain, 'string'); - domains.del(req.params.domain, auditSource(req), function (error) { + domains.del(req.params.domain, auditSource.fromRequest(req), function (error) { if (error && error.reason === DomainsError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error && error.reason === DomainsError.IN_USE) return next(new HttpError(409, 'Domain is still in use. Remove all apps and mailboxes using this domain')); if (error) return next(new HttpError(500, error)); diff --git a/src/routes/mail.js b/src/routes/mail.js index 6e8f2245c..019209d59 100644 --- a/src/routes/mail.js +++ b/src/routes/mail.js @@ -35,6 +35,7 @@ exports = module.exports = { }; var assert = require('assert'), + auditSource = require('../auditsource.js'), mail = require('../mail.js'), MailError = mail.MailError, HttpError = require('connect-lastmile').HttpError, @@ -44,11 +45,6 @@ var assert = require('assert'), var mailProxy = middleware.proxy(url.parse('http://127.0.0.1:2020')); -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function getDomain(req, res, next) { assert.strictEqual(typeof req.params.domain, 'string'); @@ -190,7 +186,7 @@ function setMailEnabled(req, res, next) { if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required')); - mail.setMailEnabled(req.params.domain, !!req.body.enabled, auditSource(req), function (error) { + mail.setMailEnabled(req.params.domain, !!req.body.enabled, auditSource.fromRequest(req), function (error) { if (error && error.reason === MailError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === MailError.BILLING_REQUIRED) return next(new HttpError(402, error.message)); @@ -243,7 +239,7 @@ function addMailbox(req, res, next) { if (typeof req.body.name !== 'string') return next(new HttpError(400, 'name must be a string')); if (typeof req.body.userId !== 'string') return next(new HttpError(400, 'userId must be a string')); - mail.addMailbox(req.body.name, req.params.domain, req.body.userId, auditSource(req), function (error) { + mail.addMailbox(req.body.name, req.params.domain, req.body.userId, auditSource.fromRequest(req), function (error) { if (error && error.reason === MailError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error && error.reason === MailError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message)); @@ -272,7 +268,7 @@ function removeMailbox(req, res, next) { assert.strictEqual(typeof req.params.domain, 'string'); assert.strictEqual(typeof req.params.name, 'string'); - mail.removeMailbox(req.params.name, req.params.domain, auditSource(req), function (error) { + mail.removeMailbox(req.params.name, req.params.domain, auditSource.fromRequest(req), function (error) { if (error && error.reason === MailError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error) return next(new HttpError(500, error)); @@ -358,7 +354,7 @@ function addList(req, res, next) { if (typeof req.body.members[i] !== 'string') return next(new HttpError(400, 'member must be a string')); } - mail.addList(req.body.name, req.params.domain, req.body.members, auditSource(req), function (error) { + mail.addList(req.body.name, req.params.domain, req.body.members, auditSource.fromRequest(req), function (error) { if (error && error.reason === MailError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error && error.reason === MailError.ALREADY_EXISTS) return next(new HttpError(409, 'list already exists')); if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message)); @@ -391,7 +387,7 @@ function removeList(req, res, next) { assert.strictEqual(typeof req.params.domain, 'string'); assert.strictEqual(typeof req.params.name, 'string'); - mail.removeList(req.params.name, req.params.domain, auditSource(req), function (error) { + mail.removeList(req.params.name, req.params.domain, auditSource.fromRequest(req), function (error) { if (error && error.reason === MailError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error) return next(new HttpError(500, error)); diff --git a/src/routes/profile.js b/src/routes/profile.js index 9b614e894..d3619e5cd 100644 --- a/src/routes/profile.js +++ b/src/routes/profile.js @@ -10,17 +10,13 @@ exports = module.exports = { }; var assert = require('assert'), + auditSource = require('../auditsource.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, users = require('../users.js'), UsersError = users.UsersError, _ = require('underscore'); -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function get(req, res, next) { assert.strictEqual(typeof req.user, 'object'); @@ -45,7 +41,7 @@ function update(req, res, next) { var data = _.pick(req.body, 'email', 'fallbackEmail', 'displayName'); - users.update(req.user.id, data, auditSource(req), function (error) { + users.update(req.user.id, data, auditSource.fromRequest(req), function (error) { if (error && error.reason === UsersError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === UsersError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === UsersError.NOT_FOUND) return next(new HttpError(404, 'User not found')); diff --git a/src/routes/provision.js b/src/routes/provision.js index 6dfa3a67a..a56820013 100644 --- a/src/routes/provision.js +++ b/src/routes/provision.js @@ -10,6 +10,7 @@ exports = module.exports = { }; var assert = require('assert'), + auditSource = require('../auditsource'), caas = require('../caas.js'), CaasError = require('../caas.js').CaasError, config = require('../config.js'), @@ -20,11 +21,6 @@ var assert = require('assert'), ProvisionError = require('../provision.js').ProvisionError, superagent = require('superagent'); -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function providerTokenAuth(req, res, next) { assert.strictEqual(typeof req.body, 'object'); @@ -84,7 +80,7 @@ function setup(req, res, next) { // it can take sometime to setup DNS, register cloudron req.clearTimeout(); - provision.setup(dnsConfig, req.body.autoconf || {}, auditSource(req), function (error) { + provision.setup(dnsConfig, req.body.autoconf || {}, auditSource.fromRequest(req), function (error) { if (error && error.reason === ProvisionError.ALREADY_SETUP) return next(new HttpError(409, error.message)); if (error && error.reason === ProvisionError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === ProvisionError.BAD_STATE) return next(new HttpError(409, error.message)); @@ -110,7 +106,7 @@ function activate(req, res, next) { var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; debug('activate: username:%s ip:%s', username, ip); - provision.activate(username, password, email, displayName, ip, auditSource(req), function (error, info) { + provision.activate(username, password, email, displayName, ip, auditSource.fromRequest(req), function (error, info) { if (error && error.reason === ProvisionError.ALREADY_PROVISIONED) return next(new HttpError(409, 'Already setup')); if (error && error.reason === ProvisionError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error) return next(new HttpError(500, error)); @@ -147,7 +143,7 @@ function restore(req, res, next) { // TODO: validate subfields of these objects if (req.body.autoconf && typeof req.body.autoconf !== 'object') return next(new HttpError(400, 'autoconf must be an object')); - provision.restore(backupConfig, req.body.backupId, req.body.version, req.body.autoconf || {}, auditSource(req), function (error) { + provision.restore(backupConfig, req.body.backupId, req.body.version, req.body.autoconf || {}, auditSource.fromRequest(req), function (error) { if (error && error.reason === ProvisionError.ALREADY_SETUP) return next(new HttpError(409, error.message)); if (error && error.reason === ProvisionError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === ProvisionError.BAD_STATE) return next(new HttpError(409, error.message)); diff --git a/src/routes/sysadmin.js b/src/routes/sysadmin.js index 779545efb..57fde4b28 100644 --- a/src/routes/sysadmin.js +++ b/src/routes/sysadmin.js @@ -13,6 +13,7 @@ exports = module.exports = { var apps = require('../apps.js'), AppsError = apps.AppsError, addons = require('../addons.js'), + auditSource = require('../auditsource.js'), backups = require('../backups.js'), BackupsError = require('../backups.js').BackupsError, cloudron = require('../cloudron.js'), @@ -28,8 +29,7 @@ function backup(req, res, next) { // note that cloudron.backup only waits for backup initiation and not for backup to complete // backup progress can be checked up ny polling the progress api call - var auditSource = { userId: null, username: 'sysadmin' }; - backups.startBackupTask(auditSource, function (error, taskId) { + backups.startBackupTask(auditSource.SYSADMIN, function (error, taskId) { if (error && error.reason === BackupsError.BAD_STATE) return next(new HttpError(409, error.message)); if (error) return next(new HttpError(500, error)); @@ -41,8 +41,7 @@ function update(req, res, next) { debug('triggering update'); // this only initiates the update, progress can be checked via the progress route - var auditSource = { userId: null, username: 'sysadmin' }; - updater.updateToLatest(auditSource, function (error, taskId) { + updater.updateToLatest(auditSource.SYSADMIN, function (error, taskId) { if (error && error.reason === UpdaterError.ALREADY_UPTODATE) return next(new HttpError(422, error.message)); if (error && error.reason === UpdaterError.BAD_STATE) return next(new HttpError(409, error.message)); if (error) return next(new HttpError(500, error)); diff --git a/src/routes/users.js b/src/routes/users.js index 9addd036d..3faba52aa 100644 --- a/src/routes/users.js +++ b/src/routes/users.js @@ -15,16 +15,12 @@ exports = module.exports = { }; var assert = require('assert'), + auditSource = require('../auditsource.js'), HttpError = require('connect-lastmile').HttpError, HttpSuccess = require('connect-lastmile').HttpSuccess, users = require('../users.js'), UsersError = users.UsersError; -function auditSource(req) { - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; - return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; -} - function create(req, res, next) { assert.strictEqual(typeof req.body, 'object'); @@ -39,7 +35,7 @@ function create(req, res, next) { var username = 'username' in req.body ? req.body.username : null; var displayName = req.body.displayName || ''; - users.create(username, password, email, displayName, { invitor: req.user, admin: req.body.admin }, auditSource(req), function (error, user) { + users.create(username, password, email, displayName, { invitor: req.user, admin: req.body.admin }, auditSource.fromRequest(req), function (error, user) { if (error && error.reason === UsersError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === UsersError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error) return next(new HttpError(500, error)); @@ -74,7 +70,7 @@ function update(req, res, next) { if (req.user.id === req.params.userId && !req.body.admin) return next(new HttpError(409, 'Cannot remove admin flag on self')); } - users.update(req.params.userId, req.body, auditSource(req), function (error) { + users.update(req.params.userId, req.body, auditSource.fromRequest(req), function (error) { if (error && error.reason === UsersError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === UsersError.ALREADY_EXISTS) return next(new HttpError(409, error.message)); if (error && error.reason === UsersError.NOT_FOUND) return next(new HttpError(404, 'User not found')); @@ -119,7 +115,7 @@ function remove(req, res, next) { if (req.user.id === req.params.userId) return next(new HttpError(409, 'Not allowed to remove yourself.')); - users.remove(req.params.userId, auditSource(req), function (error) { + users.remove(req.params.userId, auditSource.fromRequest(req), function (error) { if (error && error.reason === UsersError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error && error.reason === UsersError.NOT_FOUND) return next(new HttpError(404, 'No such user')); if (error) return next(new HttpError(500, error)); @@ -189,7 +185,7 @@ function transferOwnership(req, res, next) { if (typeof req.body.ownerId !== 'string') return next(new HttpError(400, 'ownerId must be a string')); - users.transferOwnership(req.params.userId, req.body.ownerId, auditSource(req), function (error) { + users.transferOwnership(req.params.userId, req.body.ownerId, auditSource.fromRequest(req), function (error) { if (error && error.reason === UsersError.NOT_FOUND) return next(new HttpError(404, 'No such user')); if (error) return next(new HttpError(500, error)); diff --git a/src/taskmanager.js b/src/taskmanager.js index 689845b4c..33e1134ca 100644 --- a/src/taskmanager.js +++ b/src/taskmanager.js @@ -17,6 +17,7 @@ var appdb = require('./appdb.js'), apps = require('./apps.js'), assert = require('assert'), async = require('async'), + auditSource = require('./auditsource.js'), child_process = require('child_process'), debug = require('debug')('box:taskmanager'), fs = require('fs'), @@ -35,8 +36,6 @@ var TASK_CONCURRENCY = 3; var NOOP_CALLBACK = function (error) { if (error) debug(error); }; var gPaused = true; -const AUDIT_SOURCE = { userId: null, username: 'taskmanager' }; - // resume app tasks when platform is ready or after a crash function resumeTasks(callback) { callback = callback || NOOP_CALLBACK; @@ -154,9 +153,9 @@ function startAppTask(appId, callback) { if (code === null /* signal */ || (code !== 0 && code !== 50)) { // apptask crashed debug('Apptask crashed with code %s and signal %s', code, signal); appdb.update(appId, { installationState: appdb.ISTATE_ERROR, installationProgress: 'Apptask crashed with code ' + code + ' and signal ' + signal }, NOOP_CALLBACK); - eventlog.add(eventlog.ACTION_APP_TASK_CRASH, AUDIT_SOURCE, { appId: appId, crashLogFile: logFilePath }, NOOP_CALLBACK); + eventlog.add(eventlog.ACTION_APP_TASK_CRASH, auditSource.TASK_MANAGER, { appId: appId, crashLogFile: logFilePath }, NOOP_CALLBACK); } else if (code === 50) { // task exited cleanly but with an error - eventlog.add(eventlog.ACTION_APP_TASK_CRASH, AUDIT_SOURCE, { appId: appId, crashLogFile: logFilePath }, NOOP_CALLBACK); + eventlog.add(eventlog.ACTION_APP_TASK_CRASH, auditSource.TASK_MANAGER, { appId: appId, crashLogFile: logFilePath }, NOOP_CALLBACK); } delete gActiveTasks[appId]; locker.unlock(locker.OP_APPTASK); // unlock event will trigger next task