diff --git a/src/api/web/api.js b/src/api/web/api.js index cd27830f0..8ea9d8e47 100644 --- a/src/api/web/api.js +++ b/src/api/web/api.js @@ -10,6 +10,8 @@ const match = Middleware.match; const validateName = Middleware.validate_name; const validatePkg = Middleware.validate_package; const securityIframe = Middleware.securityIframe; +const route = express.Router(); // eslint-disable-line +const async = require('async'); /* This file include all verdaccio only API(Web UI), for npm API please see ../endpoint/ @@ -17,24 +19,100 @@ const securityIframe = Middleware.securityIframe; module.exports = function(config, auth, storage) { Search.configureStorage(storage); - /* eslint new-cap:off */ - const app = express.Router(); - /* eslint new-cap:off */ const can = Middleware.allow(auth); // validate all of these params as a package name // this might be too harsh, so ask if it causes trouble - app.param('package', validatePkg); - app.param('filename', validateName); - app.param('version', validateName); - app.param('anything', match(/.*/)); + route.param('package', validatePkg); + route.param('filename', validateName); + route.param('version', validateName); + route.param('anything', match(/.*/)); - app.use(Cookies.express()); - app.use(bodyParser.urlencoded({extended: false})); - app.use(auth.cookie_middleware()); - app.use(securityIframe); + route.use(Cookies.express()); + route.use(bodyParser.urlencoded({extended: false})); + route.use(auth.cookie_middleware()); + route.use(securityIframe); - app.post('/-/login', function(req, res, next) { + // Get list of all visible package + route.get('/packages', function(req, res, next) { + storage.get_local(function(err, packages) { + if (err) throw err; // that function shouldn't produce any + + async.filterSeries( + packages, + function(pkg, cb) { + auth.allow_access(pkg.name, req.remote_user, function(err, allowed) { + if (err) { + cb(null, false); + } else { + cb(err, allowed); + } + }); + }, + function(err, packages) { + if (err) throw err; + + packages.sort(function(a, b) { + if (a.name < b.name) { + return -1; + } else { + return 1; + } + }); + next(packages); + } + ); + }); + }); + + // Get package readme + route.get('/package/readme(/@:scope?)?/:package/:version?', can('access'), function(req, res, next) { + let packageName = req.params.package; + if (req.params.scope) { + packageName = `@${req.params.scope}/${packageName}`; + } + storage.get_package(packageName, {req: req}, function(err, info) { + if (err) { + return next(err); + } + res.set('Content-Type', 'text/plain'); + next(marked(info.readme || 'ERROR: No README data found!')); + }); + }); + + // Search package + route.get('/search/:anything', function(req, res, next) { + const results = Search.query(req.params.anything); + const packages = []; + + const getPackageInfo = function(i) { + storage.get_package(results[i].ref, (err, entry) => { + if (!err && entry) { + auth.allow_access(entry.name, req.remote_user, function(err, allowed) { + if (err || !allowed) { + return; + } + + packages.push(entry.versions[entry['dist-tags'].latest]); + }); + } + + if (i >= results.length - 1) { + next(packages); + } else { + getPackageInfo(i + 1); + } + }); + }; + + if (results.length) { + getPackageInfo(0); + } else { + next([]); + } + }); + + route.post('/-/login', function(req, res, next) { auth.authenticate(req.body.user, req.body.pass, (err, user) => { if (!err) { req.remote_user = user; @@ -48,56 +126,11 @@ module.exports = function(config, auth, storage) { }); }); - app.post('/-/logout', function(req, res, next) { + route.post('/-/logout', function(req, res, next) { let base = Utils.combineBaseUrl(Utils.getWebProtocol(req), req.get('host'), config.url_prefix); res.cookies.set('token', ''); res.redirect(base); }); - // Search - app.get('/-/search/:anything', function(req, res, next) { - const results = Search.query(req.params.anything); - const packages = []; - - const getData = function(i) { - storage.get_package(results[i].ref, (err, entry) => { - if (!err && entry) { - auth.allow_access(entry.name, req.remote_user, function(err, allowed) { // TODO: This may cause performance issue? - if (err || !allowed) { - return; - } - - packages.push(entry.versions[entry['dist-tags'].latest]); - }); - } - - if (i >= results.length - 1) { - next(packages); - } else { - getData(i + 1); - } - }); - }; - - if (results.length) { - getData(0); - } else { - next([]); - } - }); - - app.get('/-/readme(/@:scope?)?/:package/:version?', can('access'), function(req, res, next) { - let packageName = req.params.package; - if (req.params.scope) { - packageName = `@${req.params.scope}/${packageName}`; - } - storage.get_package(packageName, {req: req}, function(err, info) { - if (err) { - return next(err); - } - res.set('Content-Type', 'text/plain'); - next( marked(info.readme || 'ERROR: No README data found!') ); - }); - }); - return app; + return route; };