mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-01-20 22:52:46 -05:00
Merge pull request #332 from devsquad-tech/feature/uplink_authorization
Feature/uplink authorization
This commit is contained in:
commit
c054682511
4 changed files with 208 additions and 0 deletions
|
@ -227,9 +227,71 @@ class ProxyStorage {
|
|||
headers[acceptEncoding] = headers[acceptEncoding] || 'gzip';
|
||||
// registry.npmjs.org will only return search result if user-agent include string 'npm'
|
||||
headers[userAgent] = headers[userAgent] || `npm (${this.userAgent})`;
|
||||
|
||||
return this._setAuth(headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate configuration auth and assign Header authorization
|
||||
* @param {Object} headers
|
||||
* @return {Object}
|
||||
* @private
|
||||
*/
|
||||
_setAuth(headers) {
|
||||
|
||||
if (_.isNil(this.config.auth) || headers['authorization']) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
if (!_.isObject(this.config.auth)) {
|
||||
this._throwErrorAuth('Auth invalid');
|
||||
}
|
||||
|
||||
// get NPM_TOKEN http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules
|
||||
// or get other variable export in env
|
||||
let token = process.env.NPM_TOKEN;
|
||||
if (this.config.auth.token) {
|
||||
token = this.config.auth.token;
|
||||
} else if (this.config.auth.token_env) {
|
||||
token = process.env[this.config.auth.token_env];
|
||||
}
|
||||
|
||||
if (_.isNil(token)) {
|
||||
this._throwErrorAuth('Token is required');
|
||||
}
|
||||
|
||||
// define type Auth allow basic and bearer
|
||||
const type = this.config.auth.type;
|
||||
this._setHeaderAuthorization(headers, type, token);
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} message
|
||||
* @throws {Error}
|
||||
* @private
|
||||
*/
|
||||
_throwErrorAuth(message) {
|
||||
this.logger.error(message);
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign Header authorization with type authentication
|
||||
* @param {Object} headers
|
||||
* @param {string} type
|
||||
* @param {string} token
|
||||
* @private
|
||||
*/
|
||||
_setHeaderAuthorization(headers, type, token) {
|
||||
if (type !== 'bearer' && type !== 'basic') {
|
||||
this._throwErrorAuth(`Auth type '${type}' not allowed`);
|
||||
}
|
||||
|
||||
type = _.upperFirst(type);
|
||||
headers['authorization'] = `${type} ${token}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* It will add or override specified headers from config file.
|
||||
*
|
||||
|
|
|
@ -77,6 +77,7 @@ describe('Create registry servers', function() {
|
|||
require('./notifications/notify')();
|
||||
// requires packages published to server1/server2
|
||||
require('./uplink.cache.spec')();
|
||||
require('./uplink.auth.spec')();
|
||||
|
||||
after(function(done) {
|
||||
const check = (server) => {
|
||||
|
|
144
test/functional/uplink.auth.spec.js
Normal file
144
test/functional/uplink.auth.spec.js
Normal file
|
@ -0,0 +1,144 @@
|
|||
'use strict';
|
||||
|
||||
const uplinkStorage = require('../../src/lib/storage/up-storage');
|
||||
const assert = require('assert');
|
||||
|
||||
function createUplink(config) {
|
||||
const defaultConfig = {
|
||||
url: 'https://registry.npmjs.org/'
|
||||
};
|
||||
let mergeConfig = Object.assign({}, defaultConfig, config);
|
||||
return new uplinkStorage(mergeConfig, {});
|
||||
}
|
||||
|
||||
function setHeaders(config, headers) {
|
||||
config = config || {};
|
||||
headers = headers || {};
|
||||
const uplink = createUplink(config);
|
||||
return uplink._setHeaders({
|
||||
headers
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
|
||||
describe('uplink auth test', function () {
|
||||
|
||||
it('if set headers empty should return default headers', function () {
|
||||
const headers = setHeaders();
|
||||
const keys = Object.keys(headers);
|
||||
const keysExpected = ['Accept', 'Accept-Encoding', 'User-Agent'];
|
||||
|
||||
assert.deepEqual(keys, keysExpected);
|
||||
assert.equal(keys.length, 3);
|
||||
});
|
||||
|
||||
it('if assigns value invalid to attribute auth', function () {
|
||||
const fnError = function () {
|
||||
setHeaders({
|
||||
auth: ''
|
||||
});
|
||||
};
|
||||
|
||||
assert.throws(fnError, 'Auth invalid');
|
||||
});
|
||||
|
||||
it('if assigns the header authorization', function () {
|
||||
const headers = setHeaders({}, {
|
||||
'authorization': 'basic Zm9vX2Jhcg=='
|
||||
});
|
||||
|
||||
assert.equal(Object.keys(headers).length, 4);
|
||||
assert.equal(headers['authorization'], 'basic Zm9vX2Jhcg==');
|
||||
});
|
||||
|
||||
it('if assigns headers authorization and token the header precedes', function () {
|
||||
const headers = setHeaders({
|
||||
auth: {
|
||||
type: 'bearer',
|
||||
token: 'tokenBearer'
|
||||
}
|
||||
}, {
|
||||
'authorization': 'basic tokenBasic'
|
||||
});
|
||||
|
||||
assert.equal(headers['authorization'], 'basic tokenBasic');
|
||||
});
|
||||
|
||||
it('set type auth basic', function () {
|
||||
const headers = setHeaders({
|
||||
auth: {
|
||||
type: 'basic',
|
||||
token: 'Zm9vX2Jhcg=='
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(Object.keys(headers).length, 4);
|
||||
assert.equal(headers['authorization'], 'Basic Zm9vX2Jhcg==');
|
||||
});
|
||||
|
||||
it('set type auth bearer', function () {
|
||||
const headers = setHeaders({
|
||||
auth: {
|
||||
type: 'bearer',
|
||||
token: 'Zm9vX2Jhcf==='
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(Object.keys(headers).length, 4);
|
||||
assert.equal(headers['authorization'], 'Bearer Zm9vX2Jhcf===');
|
||||
});
|
||||
|
||||
it('set auth type invalid', function () {
|
||||
const fnError = function() {
|
||||
setHeaders({
|
||||
auth: {
|
||||
type: 'null',
|
||||
token: 'Zm9vX2Jhcf==='
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
assert.throws(fnError, `Auth type 'null' not allowed`);
|
||||
});
|
||||
|
||||
it('set auth with NPM_TOKEN', function () {
|
||||
process.env.NPM_TOKEN = 'myToken';
|
||||
const headers = setHeaders({
|
||||
auth: {
|
||||
type: 'bearer'
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(headers['authorization'], 'Bearer myToken');
|
||||
delete process.env.NPM_TOKEN;
|
||||
});
|
||||
|
||||
it('set auth with token name and assigns in env', function () {
|
||||
process.env.NPM_TOKEN_TEST = 'myTokenTest';
|
||||
const headers = setHeaders({
|
||||
auth: {
|
||||
type: 'basic',
|
||||
token_env: 'NPM_TOKEN_TEST'
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(headers['authorization'], 'Basic myTokenTest');
|
||||
delete process.env.NPM_TOKEN_TEST;
|
||||
});
|
||||
|
||||
|
||||
it('if token not set', function () {
|
||||
const fnError = function() {
|
||||
setHeaders({
|
||||
auth: {
|
||||
type: 'basic'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
assert.throws(fnError, 'Token is required');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
@ -28,6 +28,7 @@ maxage | string | No |10m | all | limit maximun failure request | 2m
|
|||
fail_timeout | string | No |10m | all | defines max time when a request becomes a failure | 5m
|
||||
max_fails | number | No |2 | all | limit maximun failure request | 2
|
||||
cache | boolean | No |[true,false] | >= 2.1 | avoid cache tarballs | true
|
||||
auth | list | No | type: [bearer,basic], [token: "token",token_env: [true,\<get name process.env\>]] | >= 2.5 | assigns the header 'Authorization' see: http://blog.npmjs.org/post/118393368555/deploying-with-npm-private-modules |
|
||||
headers | list | No | authorization: "Basic YourBase64EncodedCredentials==" | all | list of custom headers for the uplink |
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue