c9-core/plugins/c9.vfs.server/vfs_wrapper.js

102 wiersze
3.0 KiB
JavaScript

"use strict";
var path = require("path");
var error = require("http-error");
module.exports = function(vfs, options) {
var root = options.root || "";
var methods = options.methods || Object.keys(vfs);
var readonly = "readonly" in options ? options.readonly : false;
var blocked = !!options.blocked;
var extendToken = options.extendToken;
var roMethods = {
resolve: 1,
stat: 1,
readfile: 1,
readdir: 1,
watch: 1,
on: 1,
off: 1,
extend: 1,
unextend: 1,
use: 1
};
var noWrap = {
connect: true,
spawn: true,
pty: true,
execFile: true,
on: true,
off: true,
emit: true,
extend: true,
unextend: true,
use: true,
killtree: true
};
var wrapper = methods.reduce(function(wrapper, method) {
var vfsMethod = vfs[method];
if (typeof vfsMethod !== "function") return wrapper;
if (blocked)
wrapper[method] = wrapReadOnly(method);
else if (readonly && !roMethods[method])
wrapper[method] = wrapReadOnly(method);
else if (noWrap[method] || !root)
wrapper[method] = vfsMethod.bind(vfs);
else
wrapper[method] = wrapSandbox(vfsMethod);
return wrapper;
}, {});
function wrapSandbox(vfsMethod) {
return function(path, options, callback) {
options.sandbox = root;
vfsMethod.call(vfs, path, options, callback);
};
}
function wrapReadOnly(vfsMethod) {
return function(path, options, callback) {
return callback(new error.Forbidden("VFS method " + vfsMethod + " is blocked in read only mode"));
};
}
var extendDirectory = path.normalize(options.extendDirectory || "");
var extendOptions = options.extendOptions || {};
wrapper.extend = function(name, options, callback) {
for (var key in extendOptions) {
options[key] = extendOptions[key];
}
if (options.code || options.stream) {
if (readonly && (!extendToken || extendToken !== options.extendToken))
return callback(new error.Forbidden("VFS extend: " + name + " with options 'stream' or 'code' not authorized in read only mode"));
else
return vfs.extend(name, options, callback);
}
if (!options.file)
return callback(new error.Forbidden("Option 'file' is missing"));
if (extendDirectory) {
var file = options.file = path.normalize(path.join(extendDirectory, options.file));
var dir = path.dirname(file);
if (dir.indexOf(extendDirectory) !== 0)
return callback(new error.Forbidden("Option 'file' in VFS extend must be in the white listed directory"));
}
return vfs.extend(name, options, callback);
};
wrapper.readonly = readonly;
wrapper.root = root;
return wrapper;
};