diff --git a/src/apps.js b/src/apps.js index 022039509..b4c87f39f 100644 --- a/src/apps.js +++ b/src/apps.js @@ -879,26 +879,21 @@ function createNewBackup(app, addonsToBackup, callback) { assert(!addonsToBackup || typeof addonsToBackup, 'object'); assert.strictEqual(typeof callback, 'function'); - backups.getBackupUrl(app, function (error, backupArchive) { + backups.getAppBackupUrl(app, function (error, result) { if (error && error.reason === BackupsError.EXTERNAL_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message)); if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - backups.getAppBackupConfigUrl(app, function (error, backupConfig) { - if (error && error.reason === BackupsError.EXTERNAL_ERROR) return callback(new AppsError(AppsError.EXTERNAL_ERROR, error.message)); + debugApp(app, 'backupApp: backup url:%s backup config url:%s', result.url, result.configUrl); + + async.series([ + ignoreError(shell.sudo.bind(null, 'mountSwap', [ BACKUP_SWAP_CMD, '--on' ])), + addons.backupAddons.bind(null, app, addonsToBackup), + shell.sudo.bind(null, 'backupApp', [ BACKUP_APP_CMD, app.id, result.url, result.configUrl, result.backupKey, result.sessionToken ]), + ignoreError(shell.sudo.bind(null, 'unmountSwap', [ BACKUP_SWAP_CMD, '--off' ])), + ], function (error) { if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - debugApp(app, 'backupApp: backup url:%s backup config url:%s', backupArchive.url, backupConfig.url); - - async.series([ - ignoreError(shell.sudo.bind(null, 'mountSwap', [ BACKUP_SWAP_CMD, '--on' ])), - addons.backupAddons.bind(null, app, addonsToBackup), - shell.sudo.bind(null, 'backupApp', [ BACKUP_APP_CMD, app.id, backupArchive.url, backupConfig.url, backupArchive.backupKey, backupArchive.sessionToken ]), - ignoreError(shell.sudo.bind(null, 'unmountSwap', [ BACKUP_SWAP_CMD, '--off' ])), - ], function (error) { - if (error) return callback(new AppsError(AppsError.INTERNAL_ERROR, error)); - - callback(null, backupArchive.id); - }); + callback(null, result.id); }); }); } diff --git a/src/backups.js b/src/backups.js index 454e7fb72..d13e6b76f 100644 --- a/src/backups.js +++ b/src/backups.js @@ -6,7 +6,7 @@ exports = module.exports = { getAllPaged: getAllPaged, getBackupUrl: getBackupUrl, - getAppBackupConfigUrl: getAppBackupConfigUrl, + getAppBackupUrl: getAppBackupUrl, getRestoreUrl: getRestoreUrl, copyLastBackup: copyLastBackup @@ -68,16 +68,10 @@ function getAllPaged(page, perPage, callback) { }); } -function getBackupUrl(app, callback) { - assert(!app || typeof app === 'object'); +function getBackupUrl(callback) { assert.strictEqual(typeof callback, 'function'); - var filename = ''; - if (app) { - filename = util.format('appbackup_%s_%s-v%s.tar.gz', app.id, (new Date()).toISOString(), app.manifest.version); - } else { - filename = util.format('backup_%s-v%s.tar.gz', (new Date()).toISOString(), config.version()); - } + var filename = util.format('backup_%s-v%s.tar.gz', (new Date()).toISOString(), config.version()); settings.getBackupConfig(function (error, backupConfig) { if (error) return callback(new BackupsError(BackupsError.INTERNAL_ERROR, error)); @@ -99,27 +93,35 @@ function getBackupUrl(app, callback) { }); } -function getAppBackupConfigUrl(app, callback) { +function getAppBackupUrl(app, callback) { assert.strictEqual(typeof app, 'object'); assert.strictEqual(typeof callback, 'function'); - var filename = util.format('appbackup_%s_%s-v%s.json', app.id, (new Date()).toISOString(), app.manifest.version); - + var timestamp = (new Date()).toISOString(); + var configFilename = util.format('appbackup_%s_%s-v%s.json', app.id, timestamp, app.manifest.version), + dataFilename = util.format('appbackup_%s_%s-v%s.tar.gz', app.id, timestamp, app.manifest.version); + settings.getBackupConfig(function (error, backupConfig) { if (error) return callback(new BackupsError(BackupsError.INTERNAL_ERROR, error)); - api(backupConfig.provider).getSignedUploadUrl(backupConfig, filename, function (error, result) { + api(backupConfig.provider).getSignedUploadUrl(backupConfig, configFilename, function (error, configResult) { if (error) return callback(error); - var obj = { - id: filename, - url: result.url, - sessionToken: result.sessionToken - }; + api(backupConfig.provider).getSignedUploadUrl(backupConfig, dataFilename, function (error, dataResult) { + if (error) return callback(error); - debug('getAppBackupConfigUrl: id:%s url:%s sessionToken:%s backupKey:%s', obj.id, obj.url, obj.sessionToken, obj.backupKey); + var obj = { + id: dataFilename, + url: dataResult.url, + configUrl: configResult.url, + sessionToken: dataResult.sessionToken, // this token can be used for both config and data upload + backupKey: backupConfig.key // only data is encrypted + }; - callback(null, obj); + debug('getAppBackupUrl: %j', obj); + + callback(null, obj); + }); }); }); } diff --git a/src/cloudron.js b/src/cloudron.js index b269d4e69..6bfb8e6d2 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -644,7 +644,7 @@ function ensureBackup(callback) { function backupBoxWithAppBackupIds(appBackupIds, callback) { assert(util.isArray(appBackupIds)); - backups.getBackupUrl(null /* app */, function (error, result) { + backups.getBackupUrl(function (error, result) { if (error && error.reason === BackupsError.EXTERNAL_ERROR) return callback(new CloudronError(CloudronError.EXTERNAL_ERROR, error.message)); if (error) return callback(new CloudronError(CloudronError.INTERNAL_ERROR, error));