0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-16 21:56:25 -05:00

(test): Refactor and add documentation some unit test, relocate storages

This commit is contained in:
Juan Picado @jotadeveloper 2017-07-02 00:05:58 +02:00
parent 1ae08b6b78
commit 6e91aa88be
No known key found for this signature in database
GPG key ID: 18AC54485952D158
18 changed files with 343 additions and 246 deletions

View file

@ -1,21 +1,31 @@
'use strict';
module.exports = function() {
describe('access control', function() {
let server = process.server;
let oldauth;
describe('package access control', function() {
const server = process.server;
const buildToken = (auth) => {
return `Basic ${(new Buffer(auth).toString('base64'))}`;
};
let oldAuth;
before(function() {
oldauth = server.authstr;
oldAuth = server.authstr;
});
after(function() {
server.authstr = oldauth;
server.authstr = oldAuth;
});
function check_access(auth, pkg, ok) {
/**
* Check whether the user is allowed to fetch packages
* @param auth {object} disable auth
* @param pkg {string} package name
* @param ok {boolean}
*/
function checkAccess(auth, pkg, ok) {
it((ok ? 'allows' : 'forbids') +' access ' + auth + ' to ' + pkg, function() {
server.authstr = auth? `Basic ${(new Buffer(auth).toString('base64'))}`: undefined;
server.authstr = auth ? buildToken(auth) : undefined;
let req = server.getPackage(pkg);
if (ok) {
return req.status(404).body_error(/no such package available/);
@ -25,10 +35,16 @@ module.exports = function() {
});
}
function check_publish(auth, pkg, ok) {
/**
* Check whether the user is allowed to publish packages
* @param auth {object} disable auth
* @param pkg {string} package name
* @param ok {boolean}
*/
function checkPublish(auth, pkg, ok) {
it(`${(ok ? 'allows' : 'forbids')} publish ${auth} to ${pkg}`, function() {
server.authstr = auth? `Basic ${(new Buffer(auth).toString('base64'))}`: undefined;
let req = server.putPackage(pkg, require('./lib/package')(pkg));
server.authstr = auth ? buildToken(auth) : undefined;
const req = server.putPackage(pkg, require('./lib/package')(pkg));
if (ok) {
return req.status(404).body_error(/this package cannot be added/);
} else {
@ -36,38 +52,48 @@ module.exports = function() {
}
});
}
const badPass = 'test:badpass';
const testPass = 'test:test';
// credentials
const badCredentials = 'test:badpass';
// test user is logged by default
const validCredentials = 'test:test';
// defined on server1 configuration
const testAccessOnly = 'test-access-only';
const testPublishOnly = 'test-publish-only';
const testOnlyTest = 'test-only-test';
const testOnlyAuth = 'test-only-auth';
check_access(testPass, testAccessOnly, true);
check_access(undefined, testAccessOnly, true);
check_access(badPass, testAccessOnly, true);
check_publish(testPass, testAccessOnly, false);
check_publish(undefined, testAccessOnly, false);
check_publish(badPass, testAccessOnly, false);
check_access(testPass, testPublishOnly, false);
check_access(undefined, testPublishOnly, false);
check_access(badPass, testPublishOnly, false);
check_publish(testPass, testPublishOnly, true);
check_publish(undefined, testPublishOnly, true);
check_publish(badPass, testPublishOnly, true);
// all are allowed to access
checkAccess(validCredentials, testAccessOnly, true);
checkAccess(undefined, testAccessOnly, true);
checkAccess(badCredentials, testAccessOnly, true);
checkPublish(validCredentials, testAccessOnly, false);
checkPublish(undefined, testAccessOnly, false);
checkPublish(badCredentials, testAccessOnly, false);
check_access(testPass, testOnlyTest, true);
check_access(undefined, testOnlyTest, false);
check_access(badPass, testOnlyTest, false);
check_publish(testPass, testOnlyTest, true);
check_publish(undefined, testOnlyTest, false);
check_publish(badPass, testOnlyTest, false);
// all are allowed to publish
checkAccess(validCredentials, testPublishOnly, false);
checkAccess(undefined, testPublishOnly, false);
checkAccess(badCredentials, testPublishOnly, false);
checkPublish(validCredentials, testPublishOnly, true);
checkPublish(undefined, testPublishOnly, true);
checkPublish(badCredentials, testPublishOnly, true);
check_access(testPass, testOnlyAuth, true);
check_access(undefined, testOnlyAuth, false);
check_access(badPass, testOnlyAuth, false);
check_publish(testPass, testOnlyAuth, true);
check_publish(undefined, testOnlyAuth, false);
check_publish(badPass, testOnlyAuth, false);
// only user "test" is allowed to publish and access
checkAccess(validCredentials, testOnlyTest, true);
checkAccess(undefined, testOnlyTest, false);
checkAccess(badCredentials, testOnlyTest, false);
checkPublish(validCredentials, testOnlyTest, true);
checkPublish(undefined, testOnlyTest, false);
checkPublish(badCredentials, testOnlyTest, false);
// only authenticated users are allowed
checkAccess(validCredentials, testOnlyAuth, true);
checkAccess(undefined, testOnlyAuth, false);
checkAccess(badCredentials, testOnlyAuth, false);
checkPublish(validCredentials, testOnlyAuth, true);
checkPublish(undefined, testOnlyAuth, false);
checkPublish(badCredentials, testOnlyAuth, false);
});
};

View file

@ -36,7 +36,7 @@ module.exports = function() {
let pass = 'preexisting';
before(function() {
return fs.appendFileSync(
path.join(__dirname, 'test-storage', '.htpasswd'),
path.join(__dirname, 'store/test-storage', '.htpasswd'),
'preexisting:$apr1$4YSboUa9$yVKjE7.PxIOuK3M4D7VjX.'
);
});

View file

@ -1,7 +1,5 @@
'use strict';
require('./lib/startup');
const assert = require('assert');
const crypto = require('crypto');
@ -21,122 +19,137 @@ module.exports = function() {
let server = process.server;
let server2 = process.server2;
it('trying to fetch non-existent package', function() {
return server.getPackage('testpkg').status(404).body_error(/no such package/);
});
describe('basic test endpoints', function() {
describe('testpkg', function() {
require('./basic/whoIam')(server);
require('./basic/ping')(server);
before(function() {
return server.addPackage('testpkg');
});
describe('handling packages', function() {
it('creating new package', function() {/* test for before() */});
it('downloading non-existent tarball', function() {
return server.getTarball('testpkg', 'blahblah').status(404).body_error(/no such file/);
});
it('uploading incomplete tarball', function() {
return server.putTarballIncomplete('testpkg', 'blahblah1', readfile('fixtures/binary'), 3000);
});
describe('tarball', function() {
before(function() {
return server.putTarball('testpkg', 'blahblah', readfile('fixtures/binary'))
.status(201)
.body_ok(/.*/);
return server.addPackage('testpkg');
});
after(function() {
return server.removeTarball('testpkg').status(201);
it('creating new package', function() {/* test for before() */});
it('downloading non-existent tarball', function() {
return server.getTarball('testpkg', 'blahblah').status(404).body_error(/no such file/);
});
it('remove a tarball', function() {/* test for before() */});
it('uploading new tarball', function() {/* test for before() */});
it('remove non existing tarball', function() {
return server.removeTarball('testpkg404').status(404);
it('uploading incomplete tarball', function() {
return server.putTarballIncomplete('testpkg', 'blahblah1', readfile('fixtures/binary'), 3000);
});
it('downloading newly created tarball', function() {
return server.getTarball('testpkg', 'blahblah')
.status(200)
.then(function(body) {
assert.deepEqual(body, readfile('fixtures/binary'));
});
});
describe('publishing package', function() {
it('uploading new package version (bad sha)', function() {
let pkg = getPackage('testpkg');
pkg.dist.shasum = createHash().update('fake').digest('hex');
return server.putVersion('testpkg', '0.0.1', pkg)
.status(400)
.body_error(/shasum error/);
});
describe('version', function() {
before(function() {
const pkg = getPackage('testpkg');
pkg.dist.shasum = createHash().update(readfile('fixtures/binary')).digest('hex');
return server.putVersion('testpkg', '0.0.1', pkg)
return server.putTarball('testpkg', 'blahblah', readfile('fixtures/binary'))
.status(201)
.body_ok(/published/);
.body_ok(/.*/);
});
it('uploading new package version', function() {
after(function() {
return server.removeTarball('testpkg').status(201);
});
it('remove a tarball', function() {
/* test for before() */
});
it('downloading newly created package', function() {
return server.getPackage('testpkg')
it('uploading new tarball', function() {
/* test for after() */
});
it('remove non existing tarball', function() {
return server.removeTarball('testpkg404').status(404);
});
it('downloading newly created tarball', function() {
return server.getTarball('testpkg', 'blahblah')
.status(200)
.then(function(body) {
assert.equal(body.name, 'testpkg');
assert.equal(body.versions['0.0.1'].name, 'testpkg');
assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/testpkg/-/blahblah');
assert.deepEqual(body['dist-tags'], {latest: '0.0.1'});
assert.deepEqual(body, readfile('fixtures/binary'));
});
});
it('downloading package via server2', function() {
return server2.getPackage('testpkg')
.status(200)
.then(function(body) {
assert.equal(body.name, 'testpkg');
assert.equal(body.versions['0.0.1'].name, 'testpkg');
assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55552/testpkg/-/blahblah');
assert.deepEqual(body['dist-tags'], {latest: '0.0.1'});
});
it('uploading new package version (bad sha)', function() {
let pkg = getPackage('testpkg');
pkg.dist.shasum = createHash().update('fake').digest('hex');
return server.putVersion('testpkg', '0.0.1', pkg)
.status(400)
.body_error(/shasum error/);
});
describe('publishing version', function() {
before(function() {
const pkg = getPackage('testpkg');
pkg.dist.shasum = createHash().update(readfile('fixtures/binary')).digest('hex');
return server.putVersion('testpkg', '0.0.1', pkg)
.status(201)
.body_ok(/published/);
});
it('uploading new package version', function() {
/* test for before() */
});
it('downloading newly created package', function() {
return server.getPackage('testpkg')
.status(200)
.then(function(body) {
assert.equal(body.name, 'testpkg');
assert.equal(body.versions['0.0.1'].name, 'testpkg');
assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/testpkg/-/blahblah');
assert.deepEqual(body['dist-tags'], {
latest: '0.0.1'
});
});
});
it('downloading package via server2', function() {
return server2.getPackage('testpkg')
.status(200)
.then(function(body) {
assert.equal(body.name, 'testpkg');
assert.equal(body.versions['0.0.1'].name, 'testpkg');
assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55552/testpkg/-/blahblah');
assert.deepEqual(body['dist-tags'], {
latest: '0.0.1'
});
});
});
});
});
});
});
it('uploading new package version for bad pkg', function() {
return server.putVersion('testpxg', '0.0.1', getPackage('testpxg'))
.status(404)
.body_error(/no such package/);
});
describe('handle failures on endpoints', function() {
it('doubleerr test', function() {
return server.putTarball('testfwd2', 'blahblah', readfile('fixtures/binary'))
.status(404)
.body_error(/no such/);
});
it('publishing package / bad ro uplink', function() {
return server.putPackage('baduplink', getPackage('baduplink'))
.status(503)
.body_error(/one of the uplinks is down, refuse to publish/);
});
it('should fails trying to fetch non-existent package', function() {
return server.getPackage('testpkg').status(404).body_error(/no such package/);
});
it('should fails on publish a version for non existing package', function() {
return server.putVersion('testpxg', '0.0.1', getPackage('testpxg'))
.status(404)
.body_error(/no such package/);
});
it('should be a package not found', function() {
return server.putTarball('nonExistingPackage', 'blahblah', readfile('fixtures/binary'))
.status(404)
.body_error(/no such/);
});
it('should fails on publish package in a bad uplink', function() {
return server.putPackage('baduplink', getPackage('baduplink'))
.status(503)
.body_error(/one of the uplinks is down, refuse to publish/);
});
it('who am I?', function() {
return server.whoami().then(function(username) {
assert.equal(username, 'test');
});
});
};

View file

@ -0,0 +1,16 @@
'use strict';
const assert = require('assert');
const _ = require('lodash');
module.exports = function(server) {
it('ping', function () {
return server.ping().then(function (data) {
// it's always an empty object
assert.ok(_.isObject(data));
});
});
};

View file

@ -0,0 +1,14 @@
'use strict';
const assert = require('assert');
module.exports = function(server) {
it('who am I?', function () {
return server.whoami().then(function (username) {
assert.equal(username, 'test');
});
});
};

View file

@ -1,91 +0,0 @@
'use strict';
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const crypto = require('crypto');
const STORAGE = 'test-storage3';
const TARBALL = 'blahblah';
const PKG_GH131 = 'pkg-gh131';
const PKG_GH1312 = 'pkg-gh1312';
function isCached(pkgname, tarballname) {
return fs.existsSync(path.join(__dirname, STORAGE, pkgname, tarballname));
}
function readfile(x) {
return fs.readFileSync(path.join(__dirname, x));
}
module.exports = function() {
const server = process.server;
const server2 = process.server2;
const server3 = process.server3;
before(function() {
return server.addPackage(PKG_GH131);
});
before(function() {
return server.putTarball(PKG_GH131, TARBALL, readfile('fixtures/binary'))
.status(201)
.body_ok(/.*/);
});
before(function() {
const pkg = require('./lib/package')(PKG_GH131);
pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server.putVersion(PKG_GH131, '0.0.1', pkg)
.status(201)
.body_ok(/published/);
});
before(function() {
return server3.getPackage(PKG_GH131)
.status(200);
});
before(function() {
return server3.getTarball(PKG_GH131, TARBALL)
.status(200);
});
it('should be caching packages from uplink server1', function () {
assert.equal(isCached(PKG_GH131, TARBALL), true);
});
before(function() {
return server2.addPackage(PKG_GH1312);
});
before(function() {
return server2.putTarball(PKG_GH1312, TARBALL, readfile('fixtures/binary'))
.status(201)
.body_ok(/.*/);
});
before(function() {
const pkg = require('./lib/package')(PKG_GH1312);
pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server2.putVersion(PKG_GH1312, '0.0.1', pkg)
.status(201)
.body_ok(/published/);
});
before(function() {
return server3.getPackage(PKG_GH1312)
.status(200);
});
before(function() {
return server3.getTarball(PKG_GH1312, TARBALL)
.status(200);
});
it('must not be caching packages from uplink server2', function () {
assert.equal(isCached(PKG_GH1312, TARBALL), false);
});
};

View file

@ -6,30 +6,33 @@ const _ = require('lodash');
const assert = require('assert');
const exec = require('child_process').exec;
describe('Func', function() {
describe('Create registry servers', function() {
const server = process.server;
const server2 = process.server2;
const server3 = process.server3;
before(function(done) {
Promise.all([
require('./lib/startup').start('./test-storage', './config-1.yaml'),
require('./lib/startup').start('./test-storage2', './config-2.yaml'),
require('./lib/startup').start('./test-storage3', './config-3.yaml'),
require('./lib/startup').start('./store/test-storage', '/store/config-1.yaml'),
require('./lib/startup').start('./store/test-storage2', '/store/config-2.yaml'),
require('./lib/startup').start('./store/test-storage3', '/store/config-3.yaml'),
]).then(() => {
done();
});
});
});
before(function() {
return Promise.all([server, server2, server3].map(function(server) {
return server.debug().status(200).then(function(body) {
server.pid = body.pid;
return new Promise(function(resolve, reject) {
exec('lsof -p ' + Number(server.pid), function(err, result) {
if (_.isNil(err) === false) {
reject(err);
}
assert.equal(err, null);
server.fdlist = result.replace(/ +/g, ' ');
resolve();
@ -39,13 +42,19 @@ describe('Func', function() {
}));
});
before(function auth() {
return Promise.all([server, server2, server3].map(function(server, cb) {
return server.auth('test', 'test').status(201).body_ok(/'test'/);
before(function testBasicAuthentication() {
return Promise.all([server, server2, server3].map(function(server) {
// log in on server1
return server.auth('test', 'test')
.status(201)
.body_ok(/'test'/);
}));
});
it('authenticate', function() {/* test for before() */});
it('authenticate', function() {
/* test for before() */
});
require('./access')();
require('./basic')();
@ -64,9 +73,9 @@ describe('Func', function() {
require('./logout')();
require('./addtag')();
require('./plugins')();
// requires packages published to server1/server2
require('./gh131')();
require('./notify')();
// requires packages published to server1/server2
require('./uplink.cache')();
after(function(done) {
const check = (server) => {
@ -93,12 +102,14 @@ describe('Func', function() {
});
});
};
Promise.all([check(server), check(server2), check(server3)]).then(function() {
done();
}, (reason) => {
assert.equal(reason, null);
done();
});
done();
});
});
});

View file

@ -1,6 +1,6 @@
module.exports = function(name, version) {
return {
name,
name: name,
version: version || '0.0.0',
dist: {
shasum: 'fake',

View file

@ -176,6 +176,15 @@ class Server {
});
}
ping() {
return this.request({
uri: '/-/ping'
}).status(200)
.then(function(body) {
return body;
});
}
debug() {
return this.request({
uri: '/-/_debug',

View file

@ -5,6 +5,7 @@ const fork = require('child_process').fork;
const bodyParser = require('body-parser');
const express = require('express');
const rimRaf = require('rimraf');
const path = require('path');
const Server = require('./server');
const forks = process.forks = [];
@ -21,7 +22,9 @@ process.express.listen(55550);
module.exports.start = function(dir, conf) {
return new Promise(function(resolve, reject) {
rimRaf(__dirname + '/../' + dir, function(err) {
const storageDir = path.join(__dirname, `/../${dir}`);
const configPath = path.join(__dirname, '../', conf);
rimRaf(storageDir, function(err) {
if(_.isNil(err) === false) {
reject(err);
}
@ -31,9 +34,10 @@ module.exports.start = function(dir, conf) {
});
const childFork = fork(__dirname + '/../../../bin/verdaccio',
['-c', __dirname + '/../' + conf],
['-c', configPath],
{
silent: !process.env.TRAVIS
// silent: false
}
);

View file

@ -2,7 +2,7 @@
module.exports = Plugin;
function Plugin(config, stuff) {
function Plugin(config) {
let self = Object.create(Plugin.prototype);
self._config = config;
return self;
@ -12,13 +12,12 @@ function Plugin(config, stuff) {
Plugin.prototype.verdaccio_version = '1.1.0';
Plugin.prototype.authenticate = function(user, password, cb) {
let self = this;
if (user !== self._config.accept_user) {
if (user !== this._config.accept_user) {
// delegate to next plugin
return cb(null, false);
}
if (password !== self._config.with_password) {
let err = Error('i don\'t like your password');
if (password !== this._config.with_password) {
const err = Error('i don\'t like your password');
err.status = 403;
return cb(err);
}

View file

@ -2,7 +2,7 @@
module.exports = Plugin;
function Plugin(config, stuff) {
function Plugin(config) {
let self = Object.create(Plugin.prototype);
self._config = config;
return self;
@ -12,17 +12,16 @@ function Plugin(config, stuff) {
Plugin.prototype.verdaccio_version = '1.1.0';
Plugin.prototype.allow_access = function(user, pkg, cb) {
let self = this;
if (!pkg.handled_by_auth_plugin) {
// delegate to next plugin
return cb(null, false);
}
if (user.name !== self._config.allow_user) {
if (user.name !== this._config.allow_user) {
let err = Error('i don\'t know anything about you');
err.status = 403;
return cb(err);
}
if (pkg.name !== self._config.to_access) {
if (pkg.name !== this._config.to_access) {
let err = Error('you\'re not allowed here');
err.status = 403;
return cb(err);

View file

@ -15,11 +15,11 @@ web:
enable: true
auth:
./plugins/authenticate:
../plugins/authenticate:
accept_user: authtest2
with_password: blahblah
./plugins/authorize:
../plugins/authorize:
allow_user: authtest
to_access: test-auth-allow

View file

@ -10,7 +10,6 @@ web:
uplinks:
server1:
url: http://localhost:55551/
# cache: true
server2:
url: http://localhost:55552/
cache: false

View file

@ -0,0 +1,98 @@
'use strict';
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const crypto = require('crypto');
const STORAGE = 'store/test-storage3';
const TARBALL = 'blahblah';
const PKG_GH131 = 'pkg-gh131';
const PKG_GH1312 = 'pkg-gh1312';
function isCached(pkgName, tarballName) {
return fs.existsSync(path.join(__dirname, STORAGE, pkgName, tarballName));
}
function readfile(x) {
return fs.readFileSync(path.join(__dirname, x));
}
module.exports = function() {
const server = process.server;
const server2 = process.server2;
const server3 = process.server3;
describe('storage tarball cache test', function() {
//more info #131
before(function () {
return server.addPackage(PKG_GH131);
});
before(function () {
return server.putTarball(PKG_GH131, TARBALL, readfile('fixtures/binary'))
.status(201)
.body_ok(/.*/);
});
before(function () {
const pkg = require('./lib/package')(PKG_GH131);
pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server.putVersion(PKG_GH131, '0.0.1', pkg)
.status(201)
.body_ok(/published/);
});
before(function () {
return server3.getPackage(PKG_GH131)
.status(200);
});
before(function () {
return server3.getTarball(PKG_GH131, TARBALL)
.status(200);
});
it('should be caching packages from uplink server1', function () {
assert.equal(isCached(PKG_GH131, TARBALL), true);
});
before(function () {
return server2.addPackage(PKG_GH1312);
});
before(function () {
return server2.putTarball(PKG_GH1312, TARBALL, readfile('fixtures/binary'))
.status(201)
.body_ok(/.*/);
});
before(function () {
const pkg = require('./lib/package')(PKG_GH1312);
pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex');
return server2.putVersion(PKG_GH1312, '0.0.1', pkg)
.status(201)
.body_ok(/published/);
});
before(function () {
return server3.getPackage(PKG_GH1312)
.status(200);
});
before(function () {
return server3.getTarball(PKG_GH1312, TARBALL)
.status(200);
});
it('must not be caching packages from uplink server2', function () {
assert.equal(isCached(PKG_GH1312, TARBALL), false);
});
});
};

View file

@ -1,7 +1,7 @@
'use strict';
const config = {
storage: __dirname + '/test-storage',
storage: __dirname + '/store/test-storage',
uplinks: {
'npmjs': {
'url': 'https://registry.npmjs.org/'

View file

@ -11,7 +11,7 @@ describe('toplevel', function() {
let port;
before(function(done) {
rimraf(__dirname + '/test-storage', done);
rimraf(__dirname + '/store/test-storage', done);
});
before(function(done) {