var bodyParser = require('body-parser') var Cookies = require('cookies') var express = require('express') var fs = require('fs') var marked = require('marked') var Handlebars = require('handlebars') var Error = require('http-errors') var Search = require('./search') var Middleware = require('./middleware') var match = Middleware.match var validate_name = Middleware.validate_name module.exports = function(config, auth, storage) { var app = express.Router() var can = Middleware.allow(config) // validate all of these params as a package name // this might be too harsh, so ask if it causes trouble app.param('package', validate_name) app.param('filename', validate_name) app.param('version', validate_name) app.param('anything', match(/.*/)) app.use(Cookies.express()) app.use(bodyParser.urlencoded({ extended: false })) app.use(auth.cookie_middleware()) app.use(function(req, res, next) { // disable loading in frames (clickjacking, etc.) res.header('X-Frame-Options', 'deny') next() }) Search.configureStorage(storage) Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.hbs'), 'utf8')) var template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.hbs'), 'utf8')) app.get('/', function(req, res, next) { var base = config.url_prefix || req.protocol + '://' + req.get('host') res.setHeader('Content-Type', 'text/html') storage.get_local(function(err, packages) { if (err) throw err // that function shouldn't produce any next(template({ name: config.web.title || 'Sinopia', packages: packages.filter(allow), baseUrl: base, username: req.remote_user.name, })) }) function allow(package) { return config.allow_access(package.name, req.remote_user) } }) // Static app.get('/-/static/:filename', function(req, res, next) { var file = __dirname + '/static/' + req.params.filename res.sendFile(file, function(err) { if (!err) return if (err.status === 404) { next() } else { next(err) } }) }) app.get('/-/logo', function(req, res, next) { res.sendFile(config.web.logo ? config.web.logo : __dirname + '/static/logo.png') }) app.get('/-/logo-sm', function(req, res, next) { res.sendFile(config.web.logosm ? config.web.logosm : __dirname + '/static/logo-sm.png') }) app.post('/-/login', function(req, res, next) { auth.authenticate(req.body.user, req.body.pass, function(err, user) { if (!err) { req.remote_user = user res.cookies.set('token', auth.issue_token(req.remote_user)) } var base = config.url_prefix || req.protocol + '://' + req.get('host') res.redirect(base) }) }) app.post('/-/logout', function(req, res, next) { var base = config.url_prefix || req.protocol + '://' + req.get('host') res.cookies.set('token', '') res.redirect(base) }) // Search app.get('/-/search/:anything', function(req, res, next) { var results = Search.query(req.params.anything) var packages = [] var getData = function(i) { storage.get_package(results[i].ref, function(err, entry) { if (!err && entry) { 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([]) } }) // Readme marked.setOptions({ highlight: function (code) { return require('highlight.js').highlightAuto(code).value } }) app.get('/-/readme/:package/:version?', can('access'), function(req, res, next) { storage.get_package(req.params.package, {req: req}, function(err, info) { if (err) return next(err) next( marked(info.readme || 'ERROR: No README data found!') ) }) }) return app }