'use strict'; exports = module.exports = { getBoxBackupDetails: getBoxBackupDetails, getAppBackupDetails: getAppBackupDetails, getRestoreUrl: getRestoreUrl, getAppRestoreConfig: getAppRestoreConfig, getLocalFilePath: getLocalFilePath, copyObject: copyObject, removeBackup: removeBackup, backupDone: backupDone, testConfig: testConfig }; var assert = require('assert'), async = require('async'), BackupsError = require('../backups.js').BackupsError, checksum = require('checksum'), fs = require('fs'), path = require('path'), safe = require('safetydance'), SettingsError = require('../settings.js').SettingsError, shell = require('../shell.js'), util = require('util'); var FALLBACK_BACKUP_FOLDER = '/var/backups'; var RMBACKUP_CMD = path.join(__dirname, '../scripts/rmbackup.sh'); function getBoxBackupDetails(apiConfig, id, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof id, 'string'); assert.strictEqual(typeof callback, 'function'); var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; var details = { backupScriptArguments: [ 'filesystem', backupFolder, id, apiConfig.key ] }; callback(null, details); } function getAppBackupDetails(apiConfig, appId, dataId, configId, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof appId, 'string'); assert.strictEqual(typeof dataId, 'string'); assert.strictEqual(typeof configId, 'string'); assert.strictEqual(typeof callback, 'function'); var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; var details = { backupScriptArguments: [ 'filesystem', appId, backupFolder, configId, dataId, apiConfig.key ] }; callback(null, details); } function getRestoreUrl(apiConfig, filename, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof filename, 'string'); assert.strictEqual(typeof callback, 'function'); var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; var restoreUrl = 'file://' + path.join(backupFolder, filename); checksum.file(path.join(backupFolder, filename), function (error, result) { if (error) return callback(new BackupsError(BackupsError.INTERNAL_ERROR, util.format('Failed to calculate checksum:', error))); callback(null, { url: restoreUrl, sha1: result }); }); } function getAppRestoreConfig(apiConfig, backupId, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof backupId, 'string'); assert.strictEqual(typeof callback, 'function'); var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; var configFilename = backupId.replace(/\.tar\.gz$/, '.json'); var restoreConfig = safe.require(path.join(backupFolder, configFilename)); if (!restoreConfig) return callback(new BackupsError(BackupsError.NOT_FOUND, 'No app backup config found for ' + configFilename)); callback(null, restoreConfig); } function getLocalFilePath(apiConfig, filename, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof filename, 'string'); assert.strictEqual(typeof callback, 'function'); var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; callback(null, { filePath: path.join(backupFolder, filename) }); } function copyObject(apiConfig, from, to, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof from, 'string'); assert.strictEqual(typeof to, 'string'); assert.strictEqual(typeof callback, 'function'); var calledBack = false; function done (error) { if (!calledBack) callback(error); calledBack = true; } var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; var readStream = fs.createReadStream(path.join(backupFolder, from)); var writeStream = fs.createWriteStream(path.join(backupFolder, to)); readStream.on('error', done); writeStream.on('error', done); writeStream.on('close', function () { // avoid passing arguments done(null); }); readStream.pipe(writeStream); } function removeBackup(apiConfig, backupId, appBackupIds, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof backupId, 'string'); assert(Array.isArray(appBackupIds)); assert.strictEqual(typeof callback, 'function'); var backupFolder = apiConfig.backupFolder || FALLBACK_BACKUP_FOLDER; var appBackupJSONFiles = appBackupIds.map(function (id) { return id.replace(/\.tar\.gz$/, '.json'); }); async.each([backupId].concat(appBackupIds).concat(appBackupJSONFiles), function (id, callback) { var filePath = path.join(backupFolder, id); shell.sudo('deleteBackup', [ RMBACKUP_CMD, filePath ], function (error) { if (error) console.error('Unable to remove %s. Not fatal.', filePath, safe.error); callback(); }); }, callback); } function testConfig(apiConfig, callback) { assert.strictEqual(typeof apiConfig, 'object'); assert.strictEqual(typeof callback, 'function'); if (typeof apiConfig.backupFolder !== 'string') return callback(new SettingsError(SettingsError.BAD_FIELD, 'backupFolder must be string')); callback(); } function backupDone(filename, app, appBackupIds, callback) { assert.strictEqual(typeof filename, 'string'); assert(!app || typeof app === 'object'); assert(!appBackupIds || Array.isArray(appBackupIds)); assert.strictEqual(typeof callback, 'function'); callback(); }