diff --git a/src/apps.js b/src/apps.js index 8e1342558..37a0a6f1c 100644 --- a/src/apps.js +++ b/src/apps.js @@ -151,7 +151,7 @@ exports = module.exports = { const appTaskManager = require('./apptaskmanager.js'), archives = require('./archives.js'), assert = require('assert'), - backupListing = require('./backuplisting.js'), + backups = require('./backups.js'), backupTargets = require('./backuptargets.js'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), @@ -2302,7 +2302,7 @@ async function restore(app, backupId, auditSource) { if (error) throw error; // for empty or null backupId, use existing manifest to mimic a reinstall - const backupInfo = backupId ? await backupListing.get(backupId) : { manifest: app.manifest }; + const backupInfo = backupId ? await backups.get(backupId) : { manifest: app.manifest }; if (!backupInfo) throw new BoxError(BoxError.BAD_FIELD, 'No such backup'); const manifest = backupInfo.manifest; @@ -2427,7 +2427,7 @@ async function clone(app, data, user, auditSource) { assert.strictEqual(typeof subdomain, 'string'); assert.strictEqual(typeof domain, 'string'); - const backupInfo = await backupListing.get(backupId); + const backupInfo = await backups.get(backupId); if (!backupInfo) throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); if (!backupInfo.manifest) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Could not detect restore manifest'); @@ -2506,7 +2506,7 @@ async function unarchive(archive, data, auditSource) { assert.strictEqual(typeof data, 'object'); assert(auditSource && typeof auditSource === 'object'); - const backup = await backupListing.get(archive.backupId); + const backup = await backups.get(archive.backupId); const restoreConfig = { remotePath: backup.remotePath, backupFormat: backup.format }; const subdomain = data.subdomain.toLowerCase(), @@ -2602,7 +2602,7 @@ async function archive(app, backupId, auditSource) { if (app.manifest.id === constants.PROXY_APP_APPSTORE_ID) throw new BoxError(BoxError.BAD_FIELD, 'cannot archive proxy app'); - const result = await backupListing.getByIdentifierAndStatePaged(app.id, backupListing.BACKUP_STATE_NORMAL, 1, 1); + const result = await backups.getByIdentifierAndStatePaged(app.id, backups.BACKUP_STATE_NORMAL, 1, 1); if (result.length === 0) throw new BoxError(BoxError.BAD_STATE, 'No recent backup to archive'); if (result[0].id !== backupId) throw new BoxError(BoxError.BAD_STATE, 'Latest backup id has changed'); @@ -2789,7 +2789,7 @@ async function backup(app, auditSource) { // background tasks.startTask(taskId, { timeout: 24 * 60 * 60 * 1000 /* 24 hours */, nice: 15, memoryLimit, oomScoreAdjust: -999 }) .then(async (backupId) => { - const backup = await backupListing.get(backupId); // if task crashed, no result + const backup = await backups.get(backupId); // if task crashed, no result await eventlog.add(eventlog.ACTION_APP_BACKUP_FINISH, auditSource, { app, success: !!backup, errorMessage: '', remotePath: backup?.remotePath, backupId: backupId }); }) .catch(async (error) => { @@ -2809,7 +2809,7 @@ async function listBackups(app, page, perPage) { assert(typeof page === 'number' && page > 0); assert(typeof perPage === 'number' && perPage > 0); - return await backupListing.getByIdentifierAndStatePaged(app.id, backupListing.BACKUP_STATE_NORMAL, page, perPage); + return await backups.getByIdentifierAndStatePaged(app.id, backups.BACKUP_STATE_NORMAL, page, perPage); } async function updateBackup(app, backupId, data) { @@ -2817,18 +2817,18 @@ async function updateBackup(app, backupId, data) { assert.strictEqual(typeof backupId, 'string'); assert.strictEqual(typeof data, 'object'); - const backup = await backupListing.get(backupId); + const backup = await backups.get(backupId); if (!backup) throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); if (backup.identifier !== app.id) throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); // some other app's backup - await backupListing.update(backupId, data); + await backups.update(backupId, data); } async function getBackupDownloadStream(app, backupId) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof backupId, 'string'); - const backup = await backupListing.get(backupId); + const backup = await backups.get(backupId); if (!backup) throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); if (backup.identifier !== app.id) throw new BoxError(BoxError.NOT_FOUND, 'Backup not found'); // some other app's backup if (backup.format !== 'tgz') throw new BoxError(BoxError.BAD_STATE, 'only tgz backups can be downloaded'); @@ -2860,7 +2860,7 @@ async function restoreApps(apps, options, auditSource) { apps = apps.filter(app => app.installationState !== exports.ISTATE_PENDING_RESTORE); // safeguard against tasks being created non-stop if we crash on startup for (const app of apps) { - const [error, result] = await safe(backupListing.getByIdentifierAndStatePaged(app.id, backupListing.BACKUP_STATE_NORMAL, 1, 1)); + const [error, result] = await safe(backups.getByIdentifierAndStatePaged(app.id, backups.BACKUP_STATE_NORMAL, 1, 1)); let installationState, restoreConfig, oldManifest; if (!error && result.length) { installationState = exports.ISTATE_PENDING_RESTORE; diff --git a/src/backupcleaner.js b/src/backupcleaner.js index 8b78cdf56..b11cb0326 100644 --- a/src/backupcleaner.js +++ b/src/backupcleaner.js @@ -12,7 +12,7 @@ const apps = require('./apps.js'), archives = require('./archives.js'), assert = require('assert'), backupFormat = require('./backupformat.js'), - backupListing = require('./backuplisting.js'), + backups = require('./backups.js'), backupTargets = require('./backuptargets.js'), constants = require('./constants.js'), debug = require('debug')('box:backupcleaner'), @@ -30,9 +30,9 @@ function applyBackupRetention(allBackups, retention, referencedBackupIds) { const now = new Date(); for (const backup of allBackups) { - if (backup.state === backupListing.BACKUP_STATE_ERROR) { + if (backup.state === backups.BACKUP_STATE_ERROR) { backup.discardReason = 'error'; - } else if (backup.state === backupListing.BACKUP_STATE_CREATING) { + } else if (backup.state === backups.BACKUP_STATE_CREATING) { if ((now - backup.creationTime) < 48*60*60*1000) backup.keepReason = 'creating'; else backup.discardReason = 'creating-too-long'; } else if (referencedBackupIds.includes(backup.id)) { // could also be in archives @@ -71,7 +71,7 @@ function applyBackupRetention(allBackups, retention, referencedBackupIds) { } if (retention.keepLatest) { - const latestNormalBackup = allBackups.find(b => b.state === backupListing.BACKUP_STATE_NORMAL); + const latestNormalBackup = allBackups.find(b => b.state === backups.BACKUP_STATE_NORMAL); if (latestNormalBackup && !latestNormalBackup.keepReason) latestNormalBackup.keepReason = 'latest'; } @@ -105,7 +105,7 @@ async function removeBackup(target, backup, progressCallback) { const [pruneError] = await safe(storage.api(target.provider).remove(target.config, path.dirname(backupFilePath))); if (pruneError) debug(`removeBackup: unable to prune backup directory ${path.dirname(backupFilePath)}: ${pruneError.message}`); - const [delError] = await safe(backupListing.del(backup.id)); + const [delError] = await safe(backups.del(backup.id)); if (delError) debug(`removeBackup: error removing ${backup.id} from database. %o`, delError); else debug(`removeBackup: removed ${backup.remotePath}`); } @@ -121,7 +121,7 @@ async function cleanupAppBackups(target, referencedBackupIds, progressCallback) const allAppIds = allApps.map(a => a.id); // high number, try to get all app backups as we had a cloudron with over 100 apps with 4 daily backups for one month! - const appBackups = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_APP, 1, 100000); + const appBackups = await backups.getByTypePaged(backups.BACKUP_TYPE_APP, 1, 100000); // collate the backups by app id. note that the app could already have been uninstalled const appBackupsById = {}; @@ -157,7 +157,7 @@ async function cleanupMailBackups(target, referencedBackupIds, progressCallback) const removedMailBackupPaths = []; - const mailBackups = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_MAIL, 1, 100000); + const mailBackups = await backups.getByTypePaged(backups.BACKUP_TYPE_MAIL, 1, 100000); applyBackupRetention(mailBackups, Object.assign({ keepLatest: true }, target.retention), referencedBackupIds); @@ -182,7 +182,7 @@ async function cleanupBoxBackups(target, progressCallback) { // We need to fetch all box backups to be able to compile a list of all referenced app backupTargets. // Otherwise if we miss some app backups, they will get purged! // 100000 here should be seen as infinity - const boxBackups = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_BOX, 1, 100000); + const boxBackups = await backups.getByTypePaged(backups.BACKUP_TYPE_BOX, 1, 100000); applyBackupRetention(boxBackups, Object.assign({ keepLatest: true }, target.retention), [] /* references */); @@ -215,10 +215,10 @@ async function cleanupMissingBackups(target, progressCallback) { let page = 1, result = []; do { - result = await backupListing.list(page, perPage); + result = await backups.list(page, perPage); for (const backup of result) { - if (backup.state !== backupListing.BACKUP_STATE_NORMAL) continue; // note: errored and incomplete backups are cleaned up by the backup retention logic + if (backup.state !== backups.BACKUP_STATE_NORMAL) continue; // note: errored and incomplete backups are cleaned up by the backup retention logic let backupFilePath = backupFormat.api(target.format).getBackupFilePath(target, backup.remotePath); if (target.format === 'rsync') backupFilePath = backupFilePath + '/'; // add trailing slash to indicate directory @@ -228,7 +228,7 @@ async function cleanupMissingBackups(target, progressCallback) { await progressCallback({ message: `Removing missing backup ${backup.remotePath}`}); - const [delError] = await safe(backupListing.del(backup.id)); + const [delError] = await safe(backups.del(backup.id)); if (delError) debug(`cleanupMissingBackups: error removing ${backup.id} from database. %o`, delError); missingBackupPaths.push(backup.remotePath); @@ -278,38 +278,38 @@ async function run(targetId, progressCallback) { assert.strictEqual(typeof targetId, 'string'); assert.strictEqual(typeof progressCallback, 'function'); - const target = await backupTargets.get(targetId); - if (!target) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Target not found'); + const backupTarget = await backupTargets.get(targetId); + if (!backupTarget) throw new BoxError(BoxError.EXTERNAL_ERROR, 'Target not found'); - debug(`run: retention is ${JSON.stringify(target.retention)}`); + debug(`run: retention is ${JSON.stringify(backupTarget.retention)}`); - const status = await backupTargets.ensureMounted(target); + const status = await backupTargets.ensureMounted(backupTarget); debug(`run: mount point status is ${JSON.stringify(status)}`); if (status.state !== 'active') throw new BoxError(BoxError.MOUNT_ERROR, `Backup endpoint is not mounted: ${status.message}`); - if (target.retention.keepWithinSecs < 0) { + if (backupTarget.retention.keepWithinSecs < 0) { debug('run: keeping all backups'); return {}; } await progressCallback({ percent: 10, message: 'Cleaning box backups' }); - const { removedBoxBackupPaths, referencedBackupIds } = await cleanupBoxBackups(target, progressCallback); // references is app or mail backup ids + const { removedBoxBackupPaths, referencedBackupIds } = await cleanupBoxBackups(backupTarget, progressCallback); // references is app or mail backup ids await progressCallback({ percent: 20, message: 'Cleaning mail backups' }); - const removedMailBackupPaths = await cleanupMailBackups(target, referencedBackupIds, progressCallback); + const removedMailBackupPaths = await cleanupMailBackups(backupTarget, referencedBackupIds, progressCallback); await progressCallback({ percent: 40, message: 'Cleaning app backups' }); const archivedBackupIds = await archives.listBackupIds(); - const removedAppBackupPaths = await cleanupAppBackups(target, referencedBackupIds.concat(archivedBackupIds), progressCallback); + const removedAppBackupPaths = await cleanupAppBackups(backupTarget, referencedBackupIds.concat(archivedBackupIds), progressCallback); await progressCallback({ percent: 70, message: 'Checking storage backend and removing stale entries in database' }); - const missingBackupPaths = await cleanupMissingBackups(target, progressCallback); + const missingBackupPaths = await cleanupMissingBackups(backupTarget, progressCallback); await progressCallback({ percent: 80, message: 'Cleaning snapshots' }); - await cleanupSnapshots(target); + await cleanupSnapshots(backupTarget); await progressCallback({ percent: 80, message: 'Cleaning storage artifacts' }); - await storage.api(target.provider).cleanup(target.config, progressCallback); + await storage.api(backupTarget.provider).cleanup(backupTarget.config, progressCallback); return { removedBoxBackupPaths, removedMailBackupPaths, removedAppBackupPaths, missingBackupPaths }; } diff --git a/src/backuplisting.js b/src/backups.js similarity index 100% rename from src/backuplisting.js rename to src/backups.js diff --git a/src/backuptargets.js b/src/backuptargets.js index 68dd0a5be..0533256b9 100644 --- a/src/backuptargets.js +++ b/src/backuptargets.js @@ -34,7 +34,7 @@ exports = module.exports = { }; const assert = require('assert'), - backupListing = require('./backuplisting.js'), + backups = require('./backups.js'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), cron = require('./cron.js'), @@ -272,7 +272,7 @@ async function startBackupTask(target, auditSource) { // background tasks.startTask(taskId, { timeout: 24 * 60 * 60 * 1000 /* 24 hours */, nice: 15, memoryLimit, oomScoreAdjust: -999 }) .then(async (backupId) => { - const backup = await backupListing.get(backupId); + const backup = await backups.get(backupId); await eventlog.add(eventlog.ACTION_BACKUP_FINISH, auditSource, { taskId, backupId, remotePath: backup.remotePath }); }) .catch(async (error) => { diff --git a/src/backuptask.js b/src/backuptask.js index 2ee76336a..34ca69f53 100644 --- a/src/backuptask.js +++ b/src/backuptask.js @@ -17,7 +17,7 @@ exports = module.exports = { const apps = require('./apps.js'), assert = require('assert'), backupFormat = require('./backupformat.js'), - backupListing = require('./backuplisting.js'), + backups = require('./backups.js'), backupTargets = require('./backuptargets.js'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), @@ -235,19 +235,19 @@ async function rotateBoxBackup(backupTarget, tag, options, dependsOn, progressCa remotePath, encryptionVersion: backupTarget.encryption ? 2 : null, packageVersion: constants.VERSION, - type: backupListing.BACKUP_TYPE_BOX, - state: backupListing.BACKUP_STATE_CREATING, - identifier: backupListing.BACKUP_IDENTIFIER_BOX, + type: backups.BACKUP_TYPE_BOX, + state: backups.BACKUP_STATE_CREATING, + identifier: backups.BACKUP_IDENTIFIER_BOX, dependsOn, manifest: null, preserveSecs: options.preserveSecs || 0, appConfig: null }; - const id = await backupListing.add(data); + const id = await backups.add(data); const [error] = await safe(copy(backupTarget, 'snapshot/box', remotePath, progressCallback)); - const state = error ? backupListing.BACKUP_STATE_ERROR : backupListing.BACKUP_STATE_NORMAL; - await backupListing.setState(id, state); + const state = error ? backups.BACKUP_STATE_ERROR : backups.BACKUP_STATE_NORMAL; + await backups.setState(id, state); if (error) throw error; return id; @@ -282,8 +282,8 @@ async function rotateAppBackup(backupTarget, app, tag, options, progressCallback remotePath, encryptionVersion: backupTarget.encryption ? 2 : null, packageVersion: manifest.version, - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_CREATING, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_CREATING, identifier: app.id, dependsOn: [], manifest, @@ -291,10 +291,10 @@ async function rotateAppBackup(backupTarget, app, tag, options, progressCallback appConfig: app }; - const id = await backupListing.add(data); + const id = await backups.add(data); const [error] = await safe(copy(backupTarget, `snapshot/app_${app.id}`, remotePath, progressCallback)); - const state = error ? backupListing.BACKUP_STATE_ERROR : backupListing.BACKUP_STATE_NORMAL; - await backupListing.setState(id, state); + const state = error ? backups.BACKUP_STATE_ERROR : backups.BACKUP_STATE_NORMAL; + await backups.setState(id, state); if (error) throw error; return id; @@ -371,7 +371,7 @@ async function backupAppWithTag(app, backupTarget, tag, options, progressCallbac assert.strictEqual(typeof progressCallback, 'function'); if (!apps.canBackupApp(app)) { // if we cannot backup, reuse it's most recent backup - const results = await backupListing.getByIdentifierAndStatePaged(app.id, backupListing.BACKUP_STATE_NORMAL, 1, 1); + const results = await backups.getByIdentifierAndStatePaged(app.id, backups.BACKUP_STATE_NORMAL, 1, 1); if (results.length === 0) return null; // no backup to re-use return results[0].id; @@ -420,19 +420,19 @@ async function rotateMailBackup(target, tag, options, progressCallback) { remotePath, encryptionVersion: target.encryption ? 2 : null, packageVersion: constants.VERSION, - type: backupListing.BACKUP_TYPE_MAIL, - state: backupListing.BACKUP_STATE_CREATING, - identifier: backupListing.BACKUP_IDENTIFIER_MAIL, + type: backups.BACKUP_TYPE_MAIL, + state: backups.BACKUP_STATE_CREATING, + identifier: backups.BACKUP_IDENTIFIER_MAIL, dependsOn: [], manifest: null, preserveSecs: options.preserveSecs || 0, appConfig: null }; - const id = await backupListing.add(data); + const id = await backups.add(data); const [error] = await safe(copy(target, 'snapshot/mail', remotePath, progressCallback)); - const state = error ? backupListing.BACKUP_STATE_ERROR : backupListing.BACKUP_STATE_NORMAL; - await backupListing.setState(id, state); + const state = error ? backups.BACKUP_STATE_ERROR : backups.BACKUP_STATE_NORMAL; + await backups.setState(id, state); if (error) throw error; return id; diff --git a/src/provision.js b/src/provision.js index 31151d235..28b8f413d 100644 --- a/src/provision.js +++ b/src/provision.js @@ -10,7 +10,7 @@ exports = module.exports = { const appstore = require('./appstore.js'), assert = require('assert'), backupTargets = require('./backuptargets.js'), - backupListing = require('./backuplisting.js'), + backups = require('./backups.js'), backuptask = require('./backuptask.js'), BoxError = require('./boxerror.js'), dashboard = require('./dashboard.js'), @@ -186,7 +186,7 @@ async function restoreTask(backupConfig, remotePath, ipv4Config, ipv6Config, opt await backuptask.restore(backupConfig, remotePath, (progress) => setProgress('restore', progress.message)); setProgress('restore', 'Downloading mail backup'); - const mailBackups = await backupListing.getByIdentifierAndStatePaged(backupListing.BACKUP_IDENTIFIER_MAIL, backupListing.BACKUP_STATE_NORMAL, 1, 1); + const mailBackups = await backups.getByIdentifierAndStatePaged(backups.BACKUP_IDENTIFIER_MAIL, backups.BACKUP_STATE_NORMAL, 1, 1); if (mailBackups.length === 0) throw new BoxError(BoxError.NOT_FOUND, 'mail backup not found'); const mailRestoreConfig = { backupConfig, remotePath: mailBackups[0].remotePath, backupFormat: mailBackups[0].format }; await backuptask.downloadMail(mailRestoreConfig, (progress) => setProgress('restore', progress.message)); diff --git a/src/routes/backuplisting.js b/src/routes/backups.js similarity index 80% rename from src/routes/backuplisting.js rename to src/routes/backups.js index a6be02bf5..dd4de5587 100644 --- a/src/routes/backuplisting.js +++ b/src/routes/backups.js @@ -6,7 +6,7 @@ exports = module.exports = { }; const assert = require('assert'), - backupListing = require('../backuplisting.js'), + backups = require('../backups.js'), BoxError = require('../boxerror.js'), HttpError = require('@cloudron/connect-lastmile').HttpError, HttpSuccess = require('@cloudron/connect-lastmile').HttpSuccess, @@ -19,7 +19,7 @@ async function list(req, res, next) { const perPage = typeof req.query.per_page === 'string'? parseInt(req.query.per_page) : 25; if (!perPage || perPage < 0) return next(new HttpError(400, 'per_page query param has to be a postive number')); - const [error, result] = await safe(backupListing.getByIdentifierAndStatePaged(backupListing.BACKUP_IDENTIFIER_BOX, backupListing.BACKUP_STATE_NORMAL, page, perPage)); + const [error, result] = await safe(backups.getByIdentifierAndStatePaged(backups.BACKUP_IDENTIFIER_BOX, backups.BACKUP_STATE_NORMAL, page, perPage)); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, { backups: result })); @@ -33,7 +33,7 @@ async function update(req, res, next) { if (typeof label !== 'string') return next(new HttpError(400, 'label must be a string')); if (typeof preserveSecs !== 'number') return next(new HttpError(400, 'preserveSecs must be a number')); - const [error] = await safe(backupListing.update(req.params.backupId, { label, preserveSecs })); + const [error] = await safe(backups.update(req.params.backupId, { label, preserveSecs })); if (error) return next(BoxError.toHttpError(error)); next(new HttpSuccess(200, {})); diff --git a/src/routes/index.js b/src/routes/index.js index 954d6c3bb..fa7051bab 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -8,7 +8,7 @@ exports = module.exports = { appstore: require('./appstore.js'), archives: require('./archives.js'), auth: require('./auth.js'), - backupListing: require('./backuplisting.js'), + backups: require('./backups.js'), backupTargets: require('./backuptargets.js'), branding: require('./branding.js'), cloudron: require('./cloudron.js'), diff --git a/src/routes/test/archives-test.js b/src/routes/test/archives-test.js index ede24916d..e4e9d0895 100644 --- a/src/routes/test/archives-test.js +++ b/src/routes/test/archives-test.js @@ -6,7 +6,7 @@ 'use strict'; const archives = require('../../archives.js'), - backupListing = require('../../backuplisting.js'), + backups = require('../../backups.js'), common = require('./common.js'), expect = require('expect.js'), superagent = require('@cloudron/superagent'); @@ -19,8 +19,8 @@ describe('Archives API', function () { remotePath: 'app_appid_123', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_CREATING, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_CREATING, identifier: 'appid', dependsOn: [ ], manifest: { foo: 'bar' }, @@ -33,7 +33,7 @@ describe('Archives API', function () { before(async function () { await setup(); - appBackup.id = await backupListing.add(appBackup); + appBackup.id = await backups.add(appBackup); archiveId = await archives.add(appBackup.id, {}, auditSource); }); after(cleanup); diff --git a/src/server.js b/src/server.js index f92fcbe63..1e025741b 100644 --- a/src/server.js +++ b/src/server.js @@ -152,9 +152,10 @@ async function initializeExpressSync() { router.post('/api/v1/notifications/:notificationId', json, token, authorizeAdmin, routes.notifications.load, routes.notifications.update); // backup routes - router.get ('/api/v1/backups', token, authorizeAdmin, routes.backupListing.list); - router.post('/api/v1/backups/:backupId', json, token, authorizeAdmin, routes.backupListing.update); + router.get ('/api/v1/backups', token, authorizeAdmin, routes.backups.list); + router.post('/api/v1/backups/:backupId', json, token, authorizeAdmin, routes.backups.update); + // backup target (destination) routes router.get ('/api/v1/backup_targets/', token, authorizeAdmin, routes.backupTargets.list); router.get ('/api/v1/backup_targets/:id', token, authorizeAdmin, routes.backupTargets.load, routes.backupTargets.get); router.post('/api/v1/backup_targets/:id', token, authorizeOwner, routes.backupTargets.add); diff --git a/src/test/archives-test.js b/src/test/archives-test.js index 2ff04179b..8551ca228 100644 --- a/src/test/archives-test.js +++ b/src/test/archives-test.js @@ -6,7 +6,7 @@ 'use strict'; const archives = require('../archives.js'), - backupListing = require('../backuplisting.js'), + backups = require('../backups.js'), BoxError = require('../boxerror.js'), common = require('./common.js'), expect = require('expect.js'), @@ -20,8 +20,8 @@ describe('Archives', function () { remotePath: 'backup-box', encryptionVersion: 2, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_NORMAL, identifier: 'box', dependsOn: [ 'dep1' ], manifest: null, @@ -32,7 +32,7 @@ describe('Archives', function () { before(async function () { await setup(); - appBackup.id = await backupListing.add(appBackup); + appBackup.id = await backups.add(appBackup); }); after(cleanup); diff --git a/src/test/backupcleaner-test.js b/src/test/backupcleaner-test.js index 9dd8d8c50..cc3919958 100644 --- a/src/test/backupcleaner-test.js +++ b/src/test/backupcleaner-test.js @@ -8,7 +8,7 @@ const archives = require('../archives.js'), backupCleaner = require('../backupcleaner.js'), - backupListing = require('../backuplisting.js'), + backups = require('../backups.js'), backupTargets = require('../backuptargets.js'), common = require('./common.js'), expect = require('expect.js'), @@ -27,8 +27,8 @@ describe('backup cleaner', function () { remotePath: 'somepath', encryptionVersion: 2, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_BOX, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_BOX, + state: backups.BACKUP_STATE_NORMAL, identifier: 'box', dependsOn: [ 'dep1' ], manifest: null, @@ -38,13 +38,13 @@ describe('backup cleaner', function () { describe('retention', function () { it('keeps latest', function () { - const backup = Object.assign({}, backupTemplate, { creationTime: moment().subtract(5, 's').toDate(), state: backupListing.BACKUP_STATE_NORMAL }); + const backup = Object.assign({}, backupTemplate, { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL }); backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: true }, []); expect(backup.keepReason).to.be('latest'); }); it('does not keep latest', function () { - const backup = { creationTime: moment().subtract(5, 's').toDate(), state: backupListing.BACKUP_STATE_NORMAL }; + const backup = { creationTime: moment().subtract(5, 's').toDate(), state: backups.BACKUP_STATE_NORMAL }; backupCleaner._applyBackupRetention([backup], { keepWithinSecs: 1, keepLatest: false }, []); expect(backup.keepReason).to.be(undefined); }); @@ -63,11 +63,11 @@ describe('backup cleaner', function () { it('1 daily', function () { const b = [ - { id: '0', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, - { id: '1', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, - { id: '2', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, - { id: '3', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(20, 'h').toDate() }, - { id: '4', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() } + { id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, + { id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, + { id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, + { id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(20, 'h').toDate() }, + { id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() } ]; backupCleaner._applyBackupRetention(b, { keepDaily: 1, keepLatest: true }, []); expect(b[0].keepReason).to.be('keepDaily'); @@ -80,13 +80,13 @@ describe('backup cleaner', function () { // if you are debugging this test, it's because of some timezone issue with all the hour substraction! it('2 daily, 1 weekly', function () { const b = [ - { id: '0', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, - { id: '1', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, - { id: '2', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, - { id: '3', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() }, - { id: '4', state: backupListing.BACKUP_STATE_ERROR, creationTime: moment().subtract(32, 'h').toDate() }, - { id: '5', state: backupListing.BACKUP_STATE_CREATING, creationTime: moment().subtract(50, 'h').toDate() }, - { id: '6', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() } + { id: '0', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, + { id: '1', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, + { id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, + { id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() }, + { id: '4', state: backups.BACKUP_STATE_ERROR, creationTime: moment().subtract(32, 'h').toDate() }, + { id: '5', state: backups.BACKUP_STATE_CREATING, creationTime: moment().subtract(50, 'h').toDate() }, + { id: '6', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(5, 'd').toDate() } ]; backupCleaner._applyBackupRetention(b, { keepDaily: 2, keepWeekly: 1, keepLatest: false }, []); expect(b[0].keepReason).to.be('keepDaily'); // today @@ -100,16 +100,16 @@ describe('backup cleaner', function () { it('2 daily, 3 monthly, 1 yearly', function () { const b = [ - { id: '0', state: backupListing.BACKUP_STATE_CREATING, creationTime: moment().toDate() }, - { id: '1', state: backupListing.BACKUP_STATE_ERROR, creationTime: moment().toDate() }, - { id: '2', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, - { id: '3', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, - { id: '4', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, - { id: '5', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() }, - { id: '6', state: backupListing.BACKUP_STATE_CREATING, creationTime: moment().subtract(49, 'h').toDate() }, - { id: '7', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(51, 'd').toDate() }, - { id: '8', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(84, 'd').toDate() }, - { id: '9', state: backupListing.BACKUP_STATE_NORMAL, creationTime: moment().subtract(97, 'd').toDate() }, + { id: '0', state: backups.BACKUP_STATE_CREATING, creationTime: moment().toDate() }, + { id: '1', state: backups.BACKUP_STATE_ERROR, creationTime: moment().toDate() }, + { id: '2', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().toDate() }, + { id: '3', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(1, 'h').toDate() }, + { id: '4', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(3, 'h').toDate() }, + { id: '5', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(26, 'h').toDate() }, + { id: '6', state: backups.BACKUP_STATE_CREATING, creationTime: moment().subtract(49, 'h').toDate() }, + { id: '7', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(51, 'd').toDate() }, + { id: '8', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(84, 'd').toDate() }, + { id: '9', state: backups.BACKUP_STATE_NORMAL, creationTime: moment().subtract(97, 'd').toDate() }, ]; backupCleaner._applyBackupRetention(b, { keepDaily: 2, keepMonthly: 3, keepYearly: 1, keepLatest: true }, []); expect(b[0].keepReason).to.be('creating'); @@ -134,8 +134,8 @@ describe('backup cleaner', function () { identifier: 'box', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_BOX, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_BOX, + state: backups.BACKUP_STATE_NORMAL, dependsOn: [ 'backup-app-00', 'backup-app-01' ], manifest: null, preserveSecs: 0, @@ -148,8 +148,8 @@ describe('backup cleaner', function () { identifier: app.id, encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_NORMAL, dependsOn: [], manifest: null, preserveSecs: 0, @@ -162,8 +162,8 @@ describe('backup cleaner', function () { identifier: 'app1', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_NORMAL, dependsOn: [], manifest: null, preserveSecs: 0, @@ -175,8 +175,8 @@ describe('backup cleaner', function () { remotePath: 'backup-box-1', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_BOX, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_BOX, + state: backups.BACKUP_STATE_NORMAL, identifier: 'box', dependsOn: [ 'backup-app-10', 'backup-app-11' ], manifest: null, @@ -189,8 +189,8 @@ describe('backup cleaner', function () { remotePath: 'backup-app-10', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_NORMAL, identifier: app.id, dependsOn: [], manifest: null, @@ -203,8 +203,8 @@ describe('backup cleaner', function () { remotePath: 'backup-app-11', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_NORMAL, identifier: 'app1', dependsOn: [], manifest: null, @@ -217,8 +217,8 @@ describe('backup cleaner', function () { remotePath: 'backup-app-2', encryptionVersion: null, packageVersion: '2.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_NORMAL, identifier: 'app2', dependsOn: [], manifest: null, @@ -258,56 +258,56 @@ describe('backup cleaner', function () { }); it('add the backups', async function () { - BACKUP_0_APP_0.id = await backupListing.add(BACKUP_0_APP_0); - BACKUP_0_APP_1.id = await backupListing.add(BACKUP_0_APP_1); + BACKUP_0_APP_0.id = await backups.add(BACKUP_0_APP_0); + BACKUP_0_APP_1.id = await backups.add(BACKUP_0_APP_1); BACKUP_0_BOX.dependsOn = [ BACKUP_0_APP_0.id, BACKUP_0_APP_1.id ]; - BACKUP_0_BOX.id = await backupListing.add(BACKUP_0_BOX); + BACKUP_0_BOX.id = await backups.add(BACKUP_0_BOX); await timers.setTimeout(2000); // space out backups - BACKUP_1_APP_0.id = await backupListing.add(BACKUP_1_APP_0); - BACKUP_1_APP_1.id = await backupListing.add(BACKUP_1_APP_1); + BACKUP_1_APP_0.id = await backups.add(BACKUP_1_APP_0); + BACKUP_1_APP_1.id = await backups.add(BACKUP_1_APP_1); BACKUP_1_BOX.dependsOn = [ BACKUP_1_APP_0.id, BACKUP_1_APP_1.id ]; - BACKUP_1_BOX.id = await backupListing.add(BACKUP_1_BOX); + BACKUP_1_BOX.id = await backups.add(BACKUP_1_BOX); - BACKUP_2_APP_2.id = await backupListing.add(BACKUP_2_APP_2); + BACKUP_2_APP_2.id = await backups.add(BACKUP_2_APP_2); await archives.add(BACKUP_2_APP_2.id, {}, common.auditSource); }); it('succeeds with box backups, keeps latest', async function () { await cleanupBackups(target); - const results = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_BOX, 1, 1000); + const results = await backups.getByTypePaged(backups.BACKUP_TYPE_BOX, 1, 1000); expect(results.length).to.equal(1); expect(results[0].id).to.equal(BACKUP_1_BOX.id); // check that app backups are gone as well. only backup_1 will remain - const result = await backupListing.get(BACKUP_0_APP_0.id); + const result = await backups.get(BACKUP_0_APP_0.id); expect(result).to.be(null); }); it('does not remove expired backups if only one left', async function () { await cleanupBackups(target); - const results = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_BOX, 1, 1000); + const results = await backups.getByTypePaged(backups.BACKUP_TYPE_BOX, 1, 1000); expect(results[0].id).to.equal(BACKUP_1_BOX.id); // check that app backups are also still there. backup_1 is still there - const result = await backupListing.get(BACKUP_1_APP_0.id); + const result = await backups.get(BACKUP_1_APP_0.id); expect(result.id).to.equal(BACKUP_1_APP_0.id); }); it('succeeds for app backups not referenced by a box backup', async function () { // add two dangling app backups not referenced by box backup. app1 is uninstalled. app0 is there for (const backup of [BACKUP_0_APP_0, BACKUP_0_APP_1]) { - backup.id = await backupListing.add(backup); + backup.id = await backups.add(backup); } await timers.setTimeout(2000); // wait for expiration await cleanupBackups(target); - let result = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_APP, 1, 1000); + let result = await backups.getByTypePaged(backups.BACKUP_TYPE_APP, 1, 1000); expect(result.length).to.equal(4); result = result.sort((r1, r2) => r1.remotePath.localeCompare(r2.remotePath)); expect(result[0].id).to.be(BACKUP_0_APP_0.id); // because app is installed, latest backup is preserved diff --git a/src/test/backups-test.js b/src/test/backups-test.js index 7fac786e5..5f7f0d52e 100644 --- a/src/test/backups-test.js +++ b/src/test/backups-test.js @@ -6,7 +6,7 @@ 'use strict'; -const backupListing = require('../backuplisting.js'), +const backups = require('../backups.js'), backupTargets = require('../backuptargets.js'), BoxError = require('../boxerror.js'), common = require('./common.js'), @@ -21,8 +21,8 @@ describe('backups', function () { remotePath: 'backup-box', encryptionVersion: 2, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_BOX, - state: backupListing.BACKUP_STATE_NORMAL, + type: backups.BACKUP_TYPE_BOX, + state: backups.BACKUP_STATE_NORMAL, identifier: 'box', dependsOn: [ 'dep1' ], manifest: null, @@ -37,8 +37,8 @@ describe('backups', function () { remotePath: 'app_appid_123', encryptionVersion: null, packageVersion: '1.0.0', - type: backupListing.BACKUP_TYPE_APP, - state: backupListing.BACKUP_STATE_CREATING, + type: backups.BACKUP_TYPE_APP, + state: backups.BACKUP_STATE_CREATING, identifier: 'appid', dependsOn: [ ], manifest: { foo: 'bar' }, @@ -61,65 +61,65 @@ describe('backups', function () { describe('crud', function () { it('add succeeds', async function () { - boxBackup.id = await backupListing.add(boxBackup); + boxBackup.id = await backups.add(boxBackup); }); it('fails with duplicate path', async function () { - const [error] = await safe(backupListing.add(boxBackup)); + const [error] = await safe(backups.add(boxBackup)); expect(error.reason).to.be(BoxError.ALREADY_EXISTS); }); it('get succeeds', async function () { - const result = await backupListing.get(boxBackup.id); + const result = await backups.get(boxBackup.id); delete result.creationTime; expect(result).to.eql(boxBackup); }); it('get of unknown id fails', async function () { - const result = await backupListing.get('somerandom'); + const result = await backups.get('somerandom'); expect(result).to.be(null); }); it('getByTypePaged succeeds', async function () { - const results = await backupListing.getByTypePaged(backupListing.BACKUP_TYPE_BOX, 1, 5); + const results = await backups.getByTypePaged(backups.BACKUP_TYPE_BOX, 1, 5); expect(results.length).to.be(1); delete results[0].creationTime; expect(results[0]).to.eql(boxBackup); }); it('update succeeds', async function () { - await backupListing.update(boxBackup.id, { label: 'DuMonde', preserveSecs: 30 }); - const result = await backupListing.get(boxBackup.id); + await backups.update(boxBackup.id, { label: 'DuMonde', preserveSecs: 30 }); + const result = await backups.get(boxBackup.id); expect(result.label).to.eql('DuMonde'); expect(result.preserveSecs).to.eql(30); }); it('delete succeeds', async function () { - await backupListing.del(boxBackup.id); - const result = await backupListing.get(boxBackup.id); + await backups.del(boxBackup.id); + const result = await backups.get(boxBackup.id); expect(result).to.be(null); }); it('add app backup succeeds', async function () { - appBackup.id = await backupListing.add(appBackup); + appBackup.id = await backups.add(appBackup); }); it('get app backup succeeds', async function () { - const result = await backupListing.get(appBackup.id); + const result = await backups.get(appBackup.id); delete result.creationTime; expect(result).to.eql(appBackup); }); it('getByIdentifierAndStatePaged succeeds', async function () { - const results = await backupListing.getByIdentifierAndStatePaged(appBackup.identifier, backupListing.BACKUP_STATE_CREATING, 1, 5); + const results = await backups.getByIdentifierAndStatePaged(appBackup.identifier, backups.BACKUP_STATE_CREATING, 1, 5); expect(results.length).to.be(1); delete results[0].creationTime; expect(results[0]).to.eql(appBackup); }); it('delete app backup succeeds', async function () { - await backupListing.del(appBackup.id); - const result = await backupListing.get(appBackup.id); + await backups.del(appBackup.id); + const result = await backups.get(appBackup.id); expect(result).to.be(null); }); }); diff --git a/src/test/backuptask-test.js b/src/test/backuptask-test.js index 2f9a35c61..5ef72f5bd 100644 --- a/src/test/backuptask-test.js +++ b/src/test/backuptask-test.js @@ -6,7 +6,7 @@ 'use strict'; -const backupListing = require('../backuplisting.js'), +const backups = require('../backups.js'), backupTargets = require('../backuptargets.js'), common = require('./common.js'), expect = require('expect.js'), @@ -50,7 +50,7 @@ describe('backuptask', function () { if (p.error) throw new Error(`backup failed: taskId: ${taskId} ${p.error.message}`); if (!p.result) throw new Error('backup has no result:' + p); - const result = await backupListing.getByIdentifierAndStatePaged(backupListing.BACKUP_IDENTIFIER_BOX, backupListing.BACKUP_STATE_NORMAL, 1, 1); + const result = await backups.getByIdentifierAndStatePaged(backups.BACKUP_IDENTIFIER_BOX, backups.BACKUP_STATE_NORMAL, 1, 1); if (result.length !== 1) throw new Error('result is not of length 1');