Make volume.getVolume() async

This commit is contained in:
Johannes Zellner
2014-02-07 09:21:54 -08:00
parent bb515f0f0c
commit a2a8812371
4 changed files with 83 additions and 56 deletions
+2
View File
@@ -32,6 +32,8 @@ var server;
function setup(done) {
server = new Server(CONFIG);
server.start(function (err) {
expect(err).to.not.be.ok();
SERVER_URL = 'http://localhost:' + CONFIG.port;
database.USERS_TABLE.removeAll(function () {
request.post(SERVER_URL + '/api/v1/createadmin')
+13 -15
View File
@@ -41,8 +41,6 @@ function listVolumes(req, res, next) {
return next(new HttpError(500, 'Unable to list volumes: ' + error));
}
var ret = [];
async.map(result, function (volume, callback) {
var ret = {};
ret.name = volume.name;
@@ -68,16 +66,16 @@ function createVolume(req, res, next) {
return next(new HttpError(400, 'New volume name not specified'));
}
if (volume.get(req.body.name, req.user.username, config)) {
return next(new HttpError(409, 'Volume already exists'));
}
volume.get(req.body.name, req.user.username, config, function (error, result) {
if (result) next(new HttpError(409, 'Volume already exists'));
volume.create(req.body.name, req.user, config, function (error, result) {
if (error) {
return next(new HttpError(500, 'Volume creation failed: ' + error));
}
volume.create(req.body.name, req.user, config, function (error, result) {
if (error) {
return next(new HttpError(500, 'Volume creation failed: ' + error));
}
res.send(201, {});
res.send(201, {});
});
});
}
@@ -131,11 +129,11 @@ function isMounted(req, res, next) {
function attachVolume(req, res, next, volumeId) {
if (!volumeId) return next(new HttpError(400, 'Volume not specified'));
req.volume = volume.get(volumeId, req.user.username, config);
if (!req.volume) return next(new HttpError(404, 'No such volume'));
next();
volume.get(volumeId, req.user.username, config, function (error, result) {
if (error) return next(new HttpError(404, 'No such volume'));
req.volume = result;
next();
});
}
function requireMountedVolume(req, res, next) {
+11 -6
View File
@@ -85,15 +85,20 @@ describe('Volume', function () {
});
describe('get', function () {
it('succeeds', function () {
var vol = volume.get(VOLUME, USERNAME, config);
expect(vol).to.be.ok();
expect(vol).to.be.an(volume.Volume);
it('succeeds', function (done) {
volume.get(VOLUME, USERNAME, config, function (error, result) {
expect(error).to.not.be.ok();
expect(result).to.be.ok();
expect(result).to.be.an(volume.Volume);
done();
});
});
it('fails, no such volume', function () {
var vol = volume.get(VOLUME_3, USERNAME, config);
expect(vol).to.not.be.ok();
volume.get(VOLUME_3, USERNAME, config, function (error, result) {
expect(error).to.be.ok();
expect(result).to.not.be.ok();
});
});
it('list', function (done) {
+57 -35
View File
@@ -8,7 +8,8 @@ var fs = require('fs'),
path = require('path'),
assert = require('assert'),
crypto = require('crypto'),
aes = require("./aes-helper"),
aes = require('./aes-helper'),
async = require('async'),
util = require('util'),
HttpError = require('./httperror.js'),
Repo = require('./repo.js'),
@@ -50,7 +51,7 @@ VolumeError.NO_SUCH_VOLUME = 5;
function generateNewVolumePassword() {
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()_+?{}[]|:;'~`<>,.-=";
var charsLength = chars.length;
var password = "";
var password = '';
for (var i = 0; i < 64; ++i) {
password += chars.charAt(Math.floor(Math.random() * charsLength));
@@ -66,8 +67,10 @@ function Volume(name, config) {
this.mountPoint = this._resolveVolumeMountPoint();
this.tmpPath = path.join(this.mountPoint, 'tmp');
this.encfs = new encfs.Root(this.dataPath, this.mountPoint);
this.repo = undefined;
this.meta = undefined;
this.repo = null;
this.meta = null;
this._initMetaDatabase();
}
Volume.prototype._resolveVolumeRootPath = function() {
@@ -107,8 +110,6 @@ Volume.prototype.open = function (username, password, callback) {
var that = this;
this._initMetaDatabase();
this.encfs.isMounted(function (error, mounted) {
if (error) {
return callback(error);
@@ -266,6 +267,18 @@ Volume.prototype.removeUser = function (user, callback) {
this.meta.remove(user.username, callback);
};
Volume.prototype.hasUserByName = function (username, callback) {
if (!this.meta) {
debug('Invalid volume "' + this.name + '". Misses the meta database.');
return callback(new VolumeError(null, VolumeError.META_MISSING));
}
this.meta.get(username, function (error, result) {
// TODO maybe more error checking?
callback(null, !!result);
});
};
function listVolumes(username, config, callback) {
assert(typeof username === 'string');
assert(username.length !== 0);
@@ -282,28 +295,31 @@ function listVolumes(username, config, callback) {
var ret = [];
files.forEach(function (file) {
var stat = safe.fs.statSync(path.join(config.dataRoot, file));
if (!stat) {
debug('Unable to stat "' + file + '".');
return;
}
async.each(files, function (file, callback) {
fs.stat(path.join(config.dataRoot, file), function (error, stat) {
if (error) {
debug('Unable to stat "' + file + '".', error);
return callback(null);
}
// ignore everythin else than directories
if (!stat.isDirectory()) {
return;
}
// ignore everythin else than directories
if (!stat.isDirectory()) {
return callback(null);
}
var vol = getVolume(file, username, config);
if (!vol) {
return;
}
getVolume(file, username, config, function (error, result) {
if (!error) {
debug('Detected volume with repo: "' + file + '".');
ret.push(result);
}
ret.push(vol);
debug('Detected volume with repo: "' + file + '".');
callback(null);
});
});
}, function (error) {
if (error) debug('This should never happen.');
callback(null, ret);
});
callback(null, ret);
});
}
@@ -358,35 +374,41 @@ function destroyVolume(name, username, config, callback) {
assert(username.length !== 0);
assert(typeof callback === 'function');
var vol = getVolume(name, username, config);
if (!vol) {
return callback(new VolumeError(null, VolumeError.NO_SUCH_VOLUME));
}
vol.destroy(callback);
getVolume(name, username, config, function (error, result) {
if (error) return callback(new VolumeError(null, VolumeError.NO_SUCH_VOLUME));
result.destroy(callback);
});
}
function getVolume(name, username, config) {
function getVolume(name, username, config, callback) {
assert(typeof name === 'string');
assert(name.length !== 0);
assert(typeof username === 'string');
assert(username.length !== 0);
assert(typeof config === 'object');
assert(typeof callback === 'function');
// TODO check if username has access and if it exists
var vol = new Volume(name, config);
if (!safe.fs.existsSync(vol.dataPath)) {
debug('No volume "' + name + '" for user "' + username + '". ' + safe.JSON.stringify(safe.error));
return null;
return callback(new VolumeError());
}
// Check if that volume has a meta information file, if not it is not created properly or broken
if (!safe.fs.existsSync(path.join(vol.dataPath, VOLUME_META_FILENAME))) {
debug('Volume "' + name + '" for user "' + username + '" does not have meta information, it is possibly broken.');
return null;
return callback(new VolumeError());
}
vol.repo = new Repo(path.join(vol.mountPoint, REPO_SUBFOLDER), vol.tmpPath);
vol.hasUserByName(username, function (error, result) {
if (error || !result) {
debug('User "' + username + '" has no access to volume "' + name + '".');
return callback(new VolumeError());
}
return vol;
vol.repo = new Repo(path.join(vol.mountPoint, REPO_SUBFOLDER), vol.tmpPath);
callback(null, vol);
});
}