diff --git a/src/apps.js b/src/apps.js index 7d4e01a39..a6c7c517c 100644 --- a/src/apps.js +++ b/src/apps.js @@ -1034,22 +1034,24 @@ async function onTaskFinished(appId, installationState, taskId, error) { const success = !error; const errorMessage = error?.message || null; + const app = await get(appId); + const task = await tasks.get(taskId); + if (!app || !task) return; + switch (installationState) { case exports.ISTATE_PENDING_DATA_DIR_MIGRATION: if (success) await safe(services.rebuildService('sftp', AuditSource.APPTASK), { debug }); break; case exports.ISTATE_PENDING_UPDATE: { - const app = await get(appId); - if (!app) break; - const task = await tasks.get(taskId); - if (!task) break; - const fromManifest = success ? task.args[1].updateConfig.manifest : app.manifest; const toManifest = success ? app.manifest : task.args[1].updateConfig.manifest; await eventlog.add(eventlog.ACTION_APP_UPDATE_FINISH, AuditSource.APPTASK, { app, toManifest, fromManifest, success, errorMessage }); break; } + case exports.ISTATE_PENDING_BACKUP: + await eventlog.add(eventlog.ACTION_APP_BACKUP_FINISH, AuditSource.APPTASK, { app, success, errorMessage, backupId: task.result }); + break; } } @@ -2067,7 +2069,7 @@ async function clone(app, data, user, auditSource) { await purchaseApp({ appId: newAppId, appstoreId: app.appStoreId, manifestId: manifest.id || 'customapp' }); - const restoreConfig = { backupId: backupId, backupFormat: backupInfo.format }; + const restoreConfig = { backupId, backupFormat: backupInfo.format }; const task = { args: { restoreConfig, overwriteDns, skipDnsSetup, oldManifest: null }, values: {}, @@ -2080,7 +2082,7 @@ async function clone(app, data, user, auditSource) { newApp.alternateDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); newApp.aliasDomains.forEach(function (ad) { ad.fqdn = dns.fqdn(ad.subdomain, domainObjectMap[ad.domain]); }); - await eventlog.add(eventlog.ACTION_APP_CLONE, auditSource, { appId: newAppId, oldAppId: appId, backupId: backupId, oldApp: app, newApp: newApp, taskId }); + await eventlog.add(eventlog.ACTION_APP_CLONE, auditSource, { appId: newAppId, oldAppId: appId, backupId, oldApp: app, newApp, taskId }); return { id: newAppId, taskId }; } @@ -2276,8 +2278,9 @@ async function autoupdateApps(updateInfo, auditSource) { // updateInfo is { appI } } -async function backup(app) { +async function backup(app, auditSource) { assert.strictEqual(typeof app, 'object'); + assert.strictEqual(typeof auditSource, 'object'); const appId = app.id; @@ -2289,6 +2292,7 @@ async function backup(app) { values: {} }; const taskId = await addTask(appId, exports.ISTATE_PENDING_BACKUP, task); + await eventlog.add(eventlog.ACTION_APP_BACKUP, auditSource, { app, appId, taskId }); return { taskId }; } diff --git a/src/apptask.js b/src/apptask.js index d29ea35b3..33c0b0793 100644 --- a/src/apptask.js +++ b/src/apptask.js @@ -404,12 +404,13 @@ async function backup(app, args, progressCallback) { assert.strictEqual(typeof progressCallback, 'function'); await progressCallback({ percent: 10, message: 'Backing up' }); - await backuptask.backupApp(app, { snapshotOnly: !!args.snapshotOnly }, (progress) => { + const backupId = await backuptask.backupApp(app, { snapshotOnly: !!args.snapshotOnly }, (progress) => { progressCallback({ percent: 30, message: progress.message }); - }), + }); await progressCallback({ percent: 100, message: 'Done' }); await updateApp(app, { installationState: apps.ISTATE_INSTALLED, error: null }); + return backupId; } async function create(app, args, progressCallback) { @@ -777,7 +778,7 @@ async function run(appId, args, progressCallback) { throw new BoxError(BoxError.INTERNAL_ERROR, 'Unknown install command in apptask:' + app.installationState); } - const [error] = await safe(cmd); + const [error, result] = await safe(cmd); // only some commands like backup return a result if (error) { debug(`run: app error for state ${app.installationState}:`, error); @@ -793,4 +794,6 @@ async function run(appId, args, progressCallback) { throw error; } + + return result || null; } diff --git a/src/backuptask.js b/src/backuptask.js index ab5591a42..74751f53f 100644 --- a/src/backuptask.js +++ b/src/backuptask.js @@ -867,7 +867,7 @@ async function backupApp(app, options, progressCallback) { debug(`backupApp: backing up ${app.fqdn} with tag ${tag}`); - await backupAppWithTag(app, tag, options, progressCallback); + return await backupAppWithTag(app, tag, options, progressCallback); } async function snapshotApp(app, progressCallback) { diff --git a/src/eventlog.js b/src/eventlog.js index 902ef0550..7cd72c8f0 100644 --- a/src/eventlog.js +++ b/src/eventlog.js @@ -19,6 +19,8 @@ exports = module.exports = { ACTION_APP_UNINSTALL: 'app.uninstall', ACTION_APP_UPDATE: 'app.update', ACTION_APP_UPDATE_FINISH: 'app.update.finish', + ACTION_APP_BACKUP: 'app.backup', + ACTION_APP_BACKUP_FINISH: 'app.backup.finish', ACTION_APP_LOGIN: 'app.login', ACTION_APP_OOM: 'app.oom', ACTION_APP_UP: 'app.up', diff --git a/src/routes/apps.js b/src/routes/apps.js index 7df6d23d0..b205fbeeb 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -509,7 +509,7 @@ async function clone(req, res, next) { async function backup(req, res, next) { assert.strictEqual(typeof req.app, 'object'); - const [error, result] = await safe(apps.backup(req.app)); + const [error, result] = await safe(apps.backup(req.app, AuditSource.fromRequest(req))); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(202, { taskId: result.taskId }));