Files
cloudron-box/src/routes/backups.js
T

159 lines
6.4 KiB
JavaScript

'use strict';
exports = module.exports = {
list,
update,
create,
cleanup,
remount,
getMountStatus,
getConfig,
setStorage,
setLimits,
getPolicy,
setPolicy
};
const assert = require('assert'),
AuditSource = require('../auditsource.js'),
backups = require('../backups.js'),
BoxError = require('../boxerror.js'),
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess,
safe = require('safetydance');
async function list(req, res, next) {
const page = typeof req.query.page !== 'undefined' ? parseInt(req.query.page) : 1;
if (!page || page < 0) return next(new HttpError(400, 'page query param has to be a postive number'));
const perPage = typeof req.query.per_page !== 'undefined'? 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(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 }));
}
async function update(req, res, next) {
assert.strictEqual(typeof req.params.backupId, 'string');
assert.strictEqual(typeof req.body, 'object');
const { label, preserveSecs } = req.body;
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(backups.update(req.params.backupId, { label, preserveSecs }));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, {}));
}
async function create(req, res, next) {
const [error, taskId] = await safe(backups.startBackupTask(AuditSource.fromRequest(req)));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(202, { taskId }));
}
async function cleanup(req, res, next) {
const [error, taskId] = await safe(backups.startCleanupTask(AuditSource.fromRequest(req)));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(202, { taskId }));
}
async function remount(req, res, next) {
const [error] = await safe(backups.remount(AuditSource.fromRequest(req)));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(202, {}));
}
async function getMountStatus(req, res, next) {
const [error, mountStatus] = await safe(backups.getMountStatus());
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, mountStatus));
}
async function getConfig(req, res, next) {
const [error, backupConfig] = await safe(backups.getConfig());
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, backups.removePrivateFields(backupConfig)));
}
async function setLimits(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
const limits = req.body;
if ('syncConcurrency' in limits) {
if (typeof limits.syncConcurrency !== 'number') return next(new HttpError(400, 'syncConcurrency must be a positive integer'));
if (limits.syncConcurrency < 1) return next(new HttpError(400, 'syncConcurrency must be a positive integer'));
}
if ('copyConcurrency' in limits) {
if (typeof limits.copyConcurrency !== 'number') return next(new HttpError(400, 'copyConcurrency must be a positive integer'));
if (limits.copyConcurrency < 1) return next(new HttpError(400, 'copyConcurrency must be a positive integer'));
}
if ('downloadConcurrency' in limits) {
if (typeof limits.downloadConcurrency !== 'number') return next(new HttpError(400, 'downloadConcurrency must be a positive integer'));
if (limits.downloadConcurrency < 1) return next(new HttpError(400, 'downloadConcurrency must be a positive integer'));
}
if ('deleteConcurrency' in limits) {
if (typeof limits.deleteConcurrency !== 'number') return next(new HttpError(400, 'deleteConcurrency must be a positive integer'));
if (limits.deleteConcurrency < 1) return next(new HttpError(400, 'deleteConcurrency must be a positive integer'));
}
if ('uploadPartSize' in limits) {
if (typeof limits.uploadPartSize !== 'number') return next(new HttpError(400, 'uploadPartSize must be a positive integer'));
if (limits.uploadPartSize < 1) return next(new HttpError(400, 'uploadPartSize must be a positive integer'));
}
if ('memoryLimit' in limits && typeof limits.memoryLimit !== 'number') return next(new HttpError(400, 'memoryLimit must be a positive integer'));
const [error] = await safe(backups.setLimits(req.body));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, {}));
}
async function setStorage(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
// provider specific options are validated by provider backends
if (typeof req.body.provider !== 'string') return next(new HttpError(400, 'provider is required'));
if (typeof req.body.format !== 'string') return next(new HttpError(400, 'format must be a string'));
if ('password' in req.body && typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be a string'));
if ('encryptedFilenames' in req.body && typeof req.body.encryptedFilenames !== 'boolean') return next(new HttpError(400, 'encryptedFilenames must be a boolean'));
// testing the backup using put/del takes a bit of time at times
req.clearTimeout();
const [error] = await safe(backups.setStorage(req.body));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, {}));
}
async function getPolicy(req, res, next) {
const [error, policy] = await safe(backups.getPolicy());
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, { policy }));
}
async function setPolicy(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.schedule !== 'string') return next(new HttpError(400, 'schedule is required'));
if (!req.body.retention || typeof req.body.retention !== 'object') return next(new HttpError(400, 'retention is required'));
const [error] = await safe(backups.setPolicy(req.body));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(200, {}));
}