1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-11-13 03:35:52 +01:00
verdaccio/lib/index.js

242 lines
6.5 KiB
JavaScript
Raw Normal View History

2013-05-31 08:26:11 +02:00
var express = require('express');
var cookies = require('cookies');
var utils = require('./utils');
2013-06-08 03:16:28 +02:00
var Storage = require('./storage');
var Config = require('./config');
var UError = require('./error').UserError;
var basic_auth = require('./middleware').basic_auth;
var validate_name = require('./middleware').validate_name;
var media = require('./middleware').media;
2013-07-03 03:49:24 +02:00
var etagify = require('./middleware').etagify;
2013-06-08 03:16:28 +02:00
var expect_json = require('./middleware').expect_json;
2013-05-31 08:26:11 +02:00
2013-06-08 03:16:28 +02:00
module.exports = function(config_hash) {
var config = new Config(config_hash);
var storage = new Storage(config);
var can = function(action) {
return function(req, res, next) {
2013-06-08 03:16:28 +02:00
if (config['allow_'+action](req.params.package, req.remoteUser)) {
next();
} else {
2013-10-05 16:49:08 +02:00
if (req.remoteUser === 'anonymous') {
next(new UError({
status: 403,
msg: "can't "+action+" restricted package without auth, did you forget 'npm set always-auth true'?",
}));
} else {
next(new UError({
status: 403,
msg: 'user '+req.remoteUser+' not allowed to '+action+' it'
}));
}
2013-06-08 03:16:28 +02:00
}
};
2013-06-08 03:16:28 +02:00
};
2013-06-01 00:57:28 +02:00
2013-05-31 08:26:11 +02:00
var app = express();
app.use(express.logger());
2013-07-03 03:49:24 +02:00
app.use(etagify);
app.use(basic_auth(function(user, pass) {
return config.authenticate(user, pass);
2013-09-28 18:46:55 +02:00
}));
app.use(express.bodyParser({strict: false}));
2013-06-08 03:16:28 +02:00
// TODO: npm DO NOT support compression :(
app.use(express.compress());
2013-05-31 08:26:11 +02:00
app.param('package', validate_name);
2013-06-01 00:57:28 +02:00
app.param('filename', validate_name);
2013-05-31 08:26:11 +02:00
/* app.get('/', function(req, res) {
res.send({
error: 'unimplemented'
});
});*/
2013-06-08 03:16:28 +02:00
/* app.get('/-/all', function(req, res) {
var https = require('https');
var JSONStream = require('JSONStream');
var request = require('request')({
url: 'https://registry.npmjs.org/-/all',
ca: require('./npmsslkeys'),
})
.pipe(JSONStream.parse('*'))
.on('data', function(d) {
console.log(d);
});
});*/
2013-06-13 16:21:14 +02:00
// TODO: anonymous user?
app.get('/:package/:version?', can('access'), function(req, res, next) {
2013-05-31 08:26:11 +02:00
storage.get_package(req.params.package, function(err, info) {
2013-06-08 03:16:28 +02:00
if (err) return next(err);
2013-06-18 20:14:55 +02:00
info = utils.filter_tarball_urls(info, req, config);
2013-06-13 16:21:14 +02:00
var version = req.params.version;
if (!version) {
return res.send(info);
}
if (info.versions[version] != null) {
return res.send(info.versions[version]);
}
if (info['dist-tags'] != null) {
if (info['dist-tags'][version] != null) {
version = info['dist-tags'][version];
if (info.versions[version] != null) {
return res.send(info.versions[version]);
}
2013-06-13 16:21:14 +02:00
}
}
return next(new UError({
status: 404,
msg: 'version not found: ' + req.params.version
}));
2013-06-01 00:57:28 +02:00
});
});
2013-06-08 03:16:28 +02:00
app.get('/:package/-/:filename', can('access'), function(req, res, next) {
2013-06-20 15:07:34 +02:00
var stream = storage.get_tarball(req.params.package, req.params.filename);
stream.on('error', function(err) {
return next(err);
2013-05-31 08:26:11 +02:00
});
2013-06-20 15:07:34 +02:00
res.header('content-type', 'application/octet-stream');
stream.pipe(res);
2013-05-31 08:26:11 +02:00
});
//app.get('/*', function(req, res) {
// proxy.request(req, res);
//});
// placeholder 'cause npm require to be authenticated to publish
// we do not do any real authentication yet
app.post('/_session', cookies.express(), function(req, res) {
res.cookies.set('AuthSession', String(Math.random()), {
// npmjs.org sets 10h expire
expires: new Date(Date.now() + 10*60*60*1000)
});
2013-06-08 03:16:28 +02:00
res.send({"ok":true,"name":"somebody","roles":[]});
});
app.get('/-/user/:argument', function(req, res, next) {
// can't put 'org.couchdb.user' in route address for some reason
if (req.params.argument.split(':')[0] !== 'org.couchdb.user') return next('route');
res.status(200);
return res.send({
2013-06-14 09:56:02 +02:00
ok: 'you are authenticated as "' + req.user + '"',
2013-06-08 03:16:28 +02:00
});
});
app.put('/-/user/:argument', function(req, res, next) {
2013-06-14 09:56:02 +02:00
// can't put 'org.couchdb.user' in route address for some reason
if (req.params.argument.split(':')[0] !== 'org.couchdb.user') return next('route');
res.status(409);
return res.send({
error: 'registration is not implemented',
});
});
app.put('/-/user/:argument/-rev/*', function(req, res, next) {
2013-06-08 03:16:28 +02:00
// can't put 'org.couchdb.user' in route address for some reason
if (req.params.argument.split(':')[0] !== 'org.couchdb.user') return next('route');
res.status(201);
return res.send({
2013-06-14 09:56:02 +02:00
ok: 'you are authenticated as "' + req.user + '"',
2013-06-08 03:16:28 +02:00
});
2013-05-31 08:26:11 +02:00
});
// publishing a package
2013-06-08 03:16:28 +02:00
app.put('/:package', can('publish'), media('application/json'), expect_json, function(req, res, next) {
2013-05-31 08:26:11 +02:00
var name = req.params.package;
if (Object.keys(req.body).length == 1 && typeof(req.body.users) === 'object') {
return next(new UError({
// 501 status is more meaningful, but npm doesn't show error message for 5xx
status: 404,
msg: 'npm star|unstar calls are not implemented',
}));
}
2013-06-01 00:57:28 +02:00
try {
var metadata = utils.validate_metadata(req.body, name);
} catch(err) {
2013-06-08 03:16:28 +02:00
return next(new UError({
2013-06-01 00:57:28 +02:00
status: 422,
msg: 'bad incoming package data',
2013-06-08 03:16:28 +02:00
}));
2013-05-31 08:26:11 +02:00
}
2013-06-01 00:57:28 +02:00
storage.add_package(name, metadata, function(err) {
2013-05-31 08:26:11 +02:00
if (err) return next(err);
2013-06-01 00:57:28 +02:00
res.status(201);
return res.send({
ok: 'created new package'
});
2013-05-31 08:26:11 +02:00
});
});
// uploading package tarball
2013-06-08 03:16:28 +02:00
app.put('/:package/-/:filename/*', can('publish'), media('application/octet-stream'), function(req, res, next) {
2013-06-01 00:57:28 +02:00
var name = req.params.package;
2013-06-20 15:07:34 +02:00
var stream = storage.add_tarball(name, req.params.filename);
req.pipe(stream);
2013-09-24 08:28:26 +02:00
// checking if end event came before closing
var complete = false;
req.on('end', function() {
complete = true;
2013-09-27 13:31:28 +02:00
stream.done();
2013-09-24 08:28:26 +02:00
});
req.on('close', function() {
if (!complete) {
2013-09-27 13:31:28 +02:00
stream.abort();
2013-09-24 08:28:26 +02:00
}
});
2013-06-20 15:07:34 +02:00
stream.on('error', function(err) {
return next(err);
});
2013-09-27 13:31:28 +02:00
stream.on('success', function() {
2013-06-01 00:57:28 +02:00
res.status(201);
return res.send({
ok: 'tarball uploaded successfully'
});
2013-05-31 08:26:11 +02:00
});
});
// adding a version
2013-06-08 03:16:28 +02:00
app.put('/:package/:version/-tag/:tag', can('publish'), media('application/json'), expect_json, function(req, res, next) {
2013-05-31 08:26:11 +02:00
var name = req.params.package;
2013-06-01 00:57:28 +02:00
var version = req.params.version;
var tag = req.params.tag;
2013-05-31 08:26:11 +02:00
2013-06-01 00:57:28 +02:00
storage.add_version(name, version, req.body, tag, function(err) {
2013-05-31 08:26:11 +02:00
if (err) return next(err);
2013-06-01 00:57:28 +02:00
res.status(201);
return res.send({
ok: 'package published'
});
2013-05-31 08:26:11 +02:00
});
});
2013-06-01 00:57:28 +02:00
app.use(app.router);
app.use(function(err, req, res, next) {
2013-09-25 10:10:59 +02:00
if (err.status && err.status >= 400 && err.status < 600) {
2013-06-01 00:57:28 +02:00
res.status(err.status);
2013-09-25 10:10:59 +02:00
res.send({error: err.msg || err.message || 'unknown error'});
2013-06-01 00:57:28 +02:00
} else {
console.log(err);
console.log(err.stack);
res.status(500);
res.send({error: 'internal server error'});
}
});
2013-05-31 08:26:11 +02:00
return app;
};