diff --git a/src/apps.js b/src/apps.js index c8495276e..77a70941f 100644 --- a/src/apps.js +++ b/src/apps.js @@ -1780,10 +1780,11 @@ async function importApp(app, data, auditSource) { error = checkAppState(app, exports.ISTATE_PENDING_IMPORT); if (error) throw error; - const testProviderConfig = util.promisify(backups.testProviderConfig); - // TODO: make this smarter to do a read-only test and check if the file exists in the storage backend - if (backupConfig) await testProviderConfig(backupConfig); + if (backupConfig) { + error = await backups.testProviderConfig(backupConfig); + if (error) throw error; + } if (backupConfig) { if ('password' in backupConfig) { diff --git a/src/backups.js b/src/backups.js index c39519a7b..19ed80440 100644 --- a/src/backups.js +++ b/src/backups.js @@ -54,7 +54,8 @@ const assert = require('assert'), safe = require('safetydance'), settings = require('./settings.js'), storage = require('./storage.js'), - tasks = require('./tasks.js'); + tasks = require('./tasks.js'), + util = require('util'); const COLLECTD_CONFIG_EJS = fs.readFileSync(__dirname + '/collectd/cloudron-backup.ejs', { encoding: 'utf8' }); @@ -278,42 +279,42 @@ async function configureCollectd(backupConfig) { } } -function testConfig(backupConfig, callback) { +async function testConfig(backupConfig) { assert.strictEqual(typeof backupConfig, 'object'); - assert.strictEqual(typeof callback, 'function'); const func = storage.api(backupConfig.provider); - if (!func) return callback(new BoxError(BoxError.BAD_FIELD, 'unknown storage provider', { field: 'provider' })); + if (!func) return new BoxError(BoxError.BAD_FIELD, 'unknown storage provider', { field: 'provider' }); - if (backupConfig.format !== 'tgz' && backupConfig.format !== 'rsync') return callback(new BoxError(BoxError.BAD_FIELD, 'unknown format', { field: 'format' })); + if (backupConfig.format !== 'tgz' && backupConfig.format !== 'rsync') return new BoxError(BoxError.BAD_FIELD, 'unknown format', { field: 'format' }); const job = safe.safeCall(function () { return new CronJob(backupConfig.schedulePattern); }); - if (!job) return callback(new BoxError(BoxError.BAD_FIELD, 'Invalid schedule pattern', { field: 'schedulePattern' })); + if (!job) return new BoxError(BoxError.BAD_FIELD, 'Invalid schedule pattern', { field: 'schedulePattern' }); if ('password' in backupConfig) { - if (typeof backupConfig.password !== 'string') return callback(new BoxError(BoxError.BAD_FIELD, 'password must be a string', { field: 'password' })); - if (backupConfig.password.length < 8) return callback(new BoxError(BoxError.BAD_FIELD, 'password must be atleast 8 characters', { field: 'password' })); + if (typeof backupConfig.password !== 'string') return new BoxError(BoxError.BAD_FIELD, 'password must be a string', { field: 'password' }); + if (backupConfig.password.length < 8) return new BoxError(BoxError.BAD_FIELD, 'password must be atleast 8 characters', { field: 'password' }); } const policy = backupConfig.retentionPolicy; - if (!policy) return callback(new BoxError(BoxError.BAD_FIELD, 'retentionPolicy is required', { field: 'retentionPolicy' })); - if (!['keepWithinSecs','keepDaily','keepWeekly','keepMonthly','keepYearly'].find(k => !!policy[k])) return callback(new BoxError(BoxError.BAD_FIELD, 'properties missing', { field: 'retentionPolicy' })); - if ('keepWithinSecs' in policy && typeof policy.keepWithinSecs !== 'number') return callback(new BoxError(BoxError.BAD_FIELD, 'keepWithinSecs must be a number', { field: 'retentionPolicy' })); - if ('keepDaily' in policy && typeof policy.keepDaily !== 'number') return callback(new BoxError(BoxError.BAD_FIELD, 'keepDaily must be a number', { field: 'retentionPolicy' })); - if ('keepWeekly' in policy && typeof policy.keepWeekly !== 'number') return callback(new BoxError(BoxError.BAD_FIELD, 'keepWeekly must be a number', { field: 'retentionPolicy' })); - if ('keepMonthly' in policy && typeof policy.keepMonthly !== 'number') return callback(new BoxError(BoxError.BAD_FIELD, 'keepMonthly must be a number', { field: 'retentionPolicy' })); - if ('keepYearly' in policy && typeof policy.keepYearly !== 'number') return callback(new BoxError(BoxError.BAD_FIELD, 'keepYearly must be a number', { field: 'retentionPolicy' })); + if (!policy) return new BoxError(BoxError.BAD_FIELD, 'retentionPolicy is required', { field: 'retentionPolicy' }); + if (!['keepWithinSecs','keepDaily','keepWeekly','keepMonthly','keepYearly'].find(k => !!policy[k])) return new BoxError(BoxError.BAD_FIELD, 'properties missing', { field: 'retentionPolicy' }); + if ('keepWithinSecs' in policy && typeof policy.keepWithinSecs !== 'number') return new BoxError(BoxError.BAD_FIELD, 'keepWithinSecs must be a number', { field: 'retentionPolicy' }); + if ('keepDaily' in policy && typeof policy.keepDaily !== 'number') return new BoxError(BoxError.BAD_FIELD, 'keepDaily must be a number', { field: 'retentionPolicy' }); + if ('keepWeekly' in policy && typeof policy.keepWeekly !== 'number') return new BoxError(BoxError.BAD_FIELD, 'keepWeekly must be a number', { field: 'retentionPolicy' }); + if ('keepMonthly' in policy && typeof policy.keepMonthly !== 'number') return new BoxError(BoxError.BAD_FIELD, 'keepMonthly must be a number', { field: 'retentionPolicy' }); + if ('keepYearly' in policy && typeof policy.keepYearly !== 'number') return new BoxError(BoxError.BAD_FIELD, 'keepYearly must be a number', { field: 'retentionPolicy' }); - storage.api(backupConfig.provider).testConfig(backupConfig, callback); + const [error] = await safe(util.promisify(storage.api(backupConfig.provider).testConfig)(backupConfig)); + return error; } // this skips password check since that policy is only at creation time -function testProviderConfig(backupConfig, callback) { +async function testProviderConfig(backupConfig) { assert.strictEqual(typeof backupConfig, 'object'); - assert.strictEqual(typeof callback, 'function'); const func = storage.api(backupConfig.provider); - if (!func) return callback(new BoxError(BoxError.BAD_FIELD, 'unknown storage provider', { field: 'provider' })); + if (!func) return new BoxError(BoxError.BAD_FIELD, 'unknown storage provider', { field: 'provider' }); - storage.api(backupConfig.provider).testConfig(backupConfig, callback); + const [error] = await safe(util.promisify(storage.api(backupConfig.provider).testConfig)(backupConfig)); + return error; } diff --git a/src/provision.js b/src/provision.js index 8e6248aef..f81798eaf 100644 --- a/src/provision.js +++ b/src/provision.js @@ -202,7 +202,7 @@ async function restore(backupConfig, backupId, version, sysinfoConfig, options, await safe(mounts.tryAddMount(newMount, { timeout: 10 })); // 10 seconds } - let [error] = await safe(util.promisify(backups.testProviderConfig)(backupConfig)); + let error = await backups.testProviderConfig(backupConfig); if (error) throw error; if ('password' in backupConfig) { diff --git a/src/settings.js b/src/settings.js index 4bb1aa051..06d53fc65 100644 --- a/src/settings.js +++ b/src/settings.js @@ -403,9 +403,8 @@ async function setBackupConfig(backupConfig) { } } - const backupsTestConfigAsync = util.promisify(backups.testConfig); - - await backupsTestConfigAsync(backupConfig); + const error = await backups.testConfig(backupConfig); + if (error) throw error; if ('password' in backupConfig) { // user set password backupConfig.encryption = backups.generateEncryptionKeysSync(backupConfig.password);