Skip to content
Permalink
Browse files

[fix] support auth on the whole API surface (#15)

* [fix] support auth on the whole API surface

* [fix] correct auth reference

* [fix] add package-lock

* [fix] module.exports

* [fix] add basic-auth package

* [fix] support basic auth on publish appropriately

* [fix] make API like the external modules

* [ci] update ci

* [fix] be explicit with hostname
  • Loading branch information...
jcrugzz committed Dec 5, 2017
1 parent 14e1619 commit 32872577a7605c5406393151e1ab8138c4a1d442
@@ -0,0 +1 @@
package-lock.json binary
@@ -1,9 +1,9 @@
sudo: false
sudo: required
dist: trusty
language: node_js
node_js:
- "8"
- "6"
- "4"
services:
- cassandra
before_install:
- "npm install -g npm@3"
@@ -0,0 +1,18 @@
const auth = require('basic-auth');

module.exports = function authorize(app) {
const credentials = app.config.get('auth');
if (!credentials) return ((req, res, next) => next(null));
const user = credentials.user;
const password = credentials.password;

return (req, res, next) => {
const creds = auth(req);

if (!creds || creds.name !== user || creds.pass !== password) {
return res.status(401).json({ error: 'Not authorized' });
}

next();
};
};
@@ -14,7 +14,8 @@ module.exports = function (app, options, done) {
// we can use them in various stacks.
//
var middlewares = app.middlewares = {
error: require('./error')(app)
error: require('./error')(app),
auth: require('./auth')(app)
};

app.log.verbose('Adding standard middlewares');
@@ -1,7 +1,7 @@
'use strict';

var Publisher = require('./publisher'),
Tagger = require('./tagger');
const Publisher = require('./publisher');
const Tagger = require('./tagger');

module.exports = function (app, options, done) {
//
@@ -14,6 +14,7 @@ module.exports = function (app, options, done) {
//
app.publisher = new Publisher({
npm: app.config.get('npm'),
auth: app.npmAuthMiddleware,
carpenter: app.carpenter,
agents: app.agents,
models: app.models,
@@ -31,13 +31,15 @@ var Publisher = module.exports = function Publisher(opts) {

opts = opts || {};
opts.npm = opts.npm || {};
opts.auth = opts.auth || ((req, res, next) => next(null));
opts.agents = opts.agents || {};
opts.npm.cluster = opts.npm.cluster || {};
opts.npm.urls = opts.npm.urls || {};
opts.npm.urls.write = opts.npm.urls.write || {};

this.npm = opts.npm;
this.log = opts.log;
this.auth = opts.auth;
this.models = opts.models;
this.agents = opts.agents;
this.carpenter = opts.carpenter;
@@ -78,6 +80,7 @@ Publisher.prototype.setup = function () {
// Publish a package but only when verified.
//
this.router = params(new Router())
.use(this.auth)
.put('/:pkg', this.verify.bind(this));

this.request = require('hyperquest');
@@ -3,6 +3,9 @@
var LoadingBay = require('../loading-bay');

module.exports = function (app, options, done) {
const redis = app.config.get('redis');
if (!redis) return done();

app.bay = new LoadingBay({
redis: app.config.get('redis'),
PackageCache: app.models.PackageCache,
@@ -11,12 +11,13 @@ module.exports = function (app, options, done) {
done();
return;
}

passport.use('npm', new NPMStrategy(
// note: this registers /-/user/org.couchdb.user:*
Object.assign(
Object.create(null),
require(app.config.get('npm:auth-argument-factory'))
.createPassportNPMOptions(),
.createPassportOptions(app.config.get('npm-auth') || {}),
{ router: app.routes })
));
const authenticator = passport.authenticate('npm', {
@@ -27,11 +27,12 @@ function spec(params, query, env) {
}

module.exports = function (app) {
const auth = app.middlewares.auth;
//
// ### /builds/head
// List the build heads or latest builds
//
app.routes.get('/builds/-/head/', function compose(req, res, next) {
app.routes.get('/builds/-/head/', auth, function compose(req, res, next) {
app.models.BuildHead.findAll(req.query || {})
.once('error', err => {
err.status = 500;
@@ -46,7 +47,7 @@ module.exports = function (app) {
// ### /builds/
// List ALL of the builds that are in the database
//
app.routes.get('/builds/', function (req, res, next) {
app.routes.get('/builds/', auth, function (req, res, next) {
app.models.Build.findAll(req.query || {})
.once('error', err => {
err.status = 500;
@@ -60,7 +61,7 @@ module.exports = function (app) {
// ### /builds/cancel/:pkg/:version/:env
// Cancel the specified build.
//
app.routes.get('/builds/cancel/:pkg/:env/:version', function compose(req, res, next) {
app.routes.get('/builds/cancel/:pkg/:env/:version', auth, function compose(req, res, next) {
app.carpenter.cancel(req.params, function client(error, response) {
if (error) return next(error);

@@ -73,7 +74,7 @@ module.exports = function (app) {
// Get build or trigger build for the package.
//
app.routes.route('/builds/:pkg')
.get(function (req, res, next) {
.get(auth, function (req, res, next) {
// TODO: fetch the latest build from artifactory or CDN
// Investigate how this interacts with the CDN.
/* eslint no-unused-vars: 0*/
@@ -84,7 +85,7 @@ module.exports = function (app) {
// Trigger a build in carpenter through POST request, pipe the response. This
// route assumes valid `npm publish` like JSON as data.
//
.post(function build(req, res, next) {
.post(auth, function build(req, res, next) {
app.carpenter.build({
data: req.body || {}
}, function client(error, response) {
@@ -94,7 +95,7 @@ module.exports = function (app) {
}).on('error', next);
});

app.routes.get('/builds/-/meta/:pkg/:version', function (req, res, next) {
app.routes.get('/builds/-/meta/:pkg/:version', auth, function (req, res, next) {
var error;

app.bffs.meta(spec(req.params, req.query), function meta(err, build) {
@@ -117,7 +118,7 @@ module.exports = function (app) {
// Get the build for the specified environment. Returns builds for all
// environments if no env is specified.
//
app.routes.get('/builds/:pkg/:env/:version?', function (req, res, next) {
app.routes.get('/builds/:pkg/:env/:version?', auth, function (req, res, next) {
var error;
var defaulted = false;

@@ -2,11 +2,12 @@
'use strict';

module.exports = function (app) {
const auth = app.middlewares.auth;
//
// ### /checks
// List all checks that run against the package.
//
app.routes.get('/checks/:pkg', function (req, res, next) {
app.routes.get('/checks/:pkg', auth, function (req, res, next) {
// TODO: list all checks that will run for the package, ignore 2nd param
// Theoretical this can fetched from the check-suite by keyword.
});
@@ -15,15 +16,15 @@ module.exports = function (app) {
// ### /checks/run
// Run checks against the package and report.
//
app.routes.post('/checks/:pkg/run', function (req, res, next) {
app.routes.post('/checks/:pkg/run', auth, function (req, res, next) {
// TODO: execute the checks, requires the same payload as npm publish
});

//
// ### /checks/stats
// Statistics from historic runs.
//
app.routes.get('/checks/:pkg/stats', function (req, res, next) {
app.routes.get('/checks/:pkg/stats', auth, function (req, res, next) {
// TODO: report on statistics of earlier runs, duration, failures, warnings, etc.
});
};
@@ -8,11 +8,13 @@
* @returns {undefined}
*/
module.exports = function (app) {
const auth = app.middlewares.auth;
//
// ### /packages/search?type='any-type'&locale='en-US'
// Returns the packages matching the query string parameters
//
app.routes.post('/packages/search', function (req, res, next) {
app.routes.post('/packages/search', auth, function (req, res, next) {
if (!app.bay) return res.status(500).json({ error: 'Not configured' });
//
// Currently we only fetch by tag
//
Oops, something went wrong.

0 comments on commit 3287257

Please sign in to comment.
You can’t perform that action at this time.