backup/import/restore: fix crash with root path calcuation

rootPath was calculated before the arguments were validated
This commit is contained in:
Girish Ramakrishnan
2024-04-09 13:53:15 +02:00
parent 5460a64951
commit 2b1b304c6e
4 changed files with 20 additions and 18 deletions

View File

@@ -238,15 +238,20 @@ async function testConfig(apiConfig) {
if ('noHardlinks' in apiConfig && typeof apiConfig.noHardlinks !== 'boolean') throw new BoxError(BoxError.BAD_FIELD, 'noHardlinks must be boolean');
if ('chown' in apiConfig && typeof apiConfig.chown !== 'boolean') throw new BoxError(BoxError.BAD_FIELD, 'chown must be boolean');
let rootPath; // for managed mounts, this uses 'mountPath', which could be some temporary mount location
if (apiConfig.provider === PROVIDER_FILESYSTEM) {
if (!apiConfig.backupFolder || typeof apiConfig.backupFolder !== 'string') throw new BoxError(BoxError.BAD_FIELD, 'backupFolder must be non-empty string');
const error = validateBackupTarget(apiConfig.backupFolder);
if (error) throw error;
rootPath = apiConfig.backupFolder;
} else { // xfs/cifs/ext4/nfs/mountpoint/sshfs
if (apiConfig.provider === PROVIDER_MOUNTPOINT) {
if (!apiConfig.mountPoint || typeof apiConfig.mountPoint !== 'string') throw new BoxError(BoxError.BAD_FIELD, 'mountPoint must be non-empty string');
const error = validateBackupTarget(apiConfig.mountPoint);
if (error) throw error;
const [mountError] = await safe(shell.exec('testStorageConfig', `mountpoint -q -- ${apiConfig.mountPoint}`, { timeout: 5000 }));
if (mountError) throw new BoxError(BoxError.BAD_FIELD, `${apiConfig.mountPoint} is not mounted: ${mountError.message}`);
}
if (typeof apiConfig.prefix !== 'string') throw new BoxError(BoxError.BAD_FIELD, 'prefix must be a string');
@@ -254,27 +259,25 @@ async function testConfig(apiConfig) {
if (path.isAbsolute(apiConfig.prefix)) throw new BoxError(BoxError.BAD_FIELD, 'prefix must be a relative path');
if (path.normalize(apiConfig.prefix) !== apiConfig.prefix) throw new BoxError(BoxError.BAD_FIELD, 'prefix must contain a normalized relative path');
}
}
if (apiConfig.provider === PROVIDER_MOUNTPOINT) {
const [error] = await safe(shell.exec('testStorageConfig', `mountpoint -q -- ${apiConfig.mountPoint}`, { timeout: 5000 }));
if (error) throw new BoxError(BoxError.BAD_FIELD, `${apiConfig.mountPoint} is not mounted: ${error.message}`);
if (apiConfig.provider === PROVIDER_MOUNTPOINT) {
rootPath = path.join(apiConfig.mountPoint, apiConfig.prefix);
} else {
rootPath = path.join(apiConfig.mountPath, apiConfig.prefix);
}
}
const rootPath = apiConfig.rootPath;
const field = apiConfig.provider === PROVIDER_FILESYSTEM ? 'backupFolder' : 'mountPoint';
if (!safe.fs.mkdirSync(path.join(rootPath, 'snapshot'), { recursive: true }) && safe.error.code !== 'EEXIST') {
if (safe.error && safe.error.code === 'EACCES') throw new BoxError(BoxError.BAD_FIELD, `Access denied. Create the directory and run "chown yellowtent:yellowtent ${rootPath}" on the server`, { field });
throw new BoxError(BoxError.BAD_FIELD, safe.error.message, { field });
if (safe.error && safe.error.code === 'EACCES') throw new BoxError(BoxError.BAD_FIELD, `Access denied. Create ${rootPath}/snapshot and run "chown yellowtent:yellowtent ${rootPath}" on the server`);
throw new BoxError(BoxError.BAD_FIELD, safe.error.message);
}
if (!safe.fs.writeFileSync(path.join(rootPath, 'cloudron-testfile'), 'testcontent')) {
throw new BoxError(BoxError.BAD_FIELD, `Unable to create test file as 'yellowtent' user in ${rootPath}: ${safe.error.message}. Check dir/mount permissions`, { field });
throw new BoxError(BoxError.BAD_FIELD, `Unable to create test file as 'yellowtent' user in ${rootPath}: ${safe.error.message}. Check dir/mount permissions`);
}
if (!safe.fs.unlinkSync(path.join(rootPath, 'cloudron-testfile'))) {
throw new BoxError(BoxError.BAD_FIELD, `Unable to remove test file as 'yellowtent' user in ${rootPath}: ${safe.error.message}. Check dir/mount permissions`, { field });
throw new BoxError(BoxError.BAD_FIELD, `Unable to remove test file as 'yellowtent' user in ${rootPath}: ${safe.error.message}. Check dir/mount permissions`);
}
}