diff --git a/src/lib/constants.js b/src/lib/constants.js index 688a6a20d..c0273c7a0 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -13,3 +13,13 @@ export const ERROR_CODE = { export const TOKEN_BASIC = 'Basic'; export const TOKEN_BEARER = 'Bearer'; export const DEFAULT_REGISTRY = 'https://registry.npmjs.org/'; + + +export const HTTP_STATUS = { + INTERNAL_ERROR: 500, + OK: 200, + CREATED: 201, + NOT_FOUND: 404, + BAD_REQUEST: 400, + UNAUTHORIZED: 401, +}; diff --git a/test/functional/index.spec.js b/test/functional/index.spec.js index 326f49756..c505d2318 100644 --- a/test/functional/index.spec.js +++ b/test/functional/index.spec.js @@ -19,14 +19,13 @@ import notify from './notifications/notify'; import incomplete from './sanity/incomplete'; import mirror from './sanity/mirror'; import readme from './readme/readme'; -import gh29 from './gh29'; +import gh29 from './scenarios/gh29'; import nullstorage from './sanity/nullstorage'; import racycrash from './sanity/racycrash'; import security from './sanity/security'; import race from './performance/race'; import pluginsAuth from './plugins/auth'; -import upLinkCache from './uplink.cache'; -import upLinkAuth from './uplink.auth'; +import upLinkCache from './uplinks/cache'; describe('functional test verdaccio', function() { jest.setTimeout(10000); @@ -55,7 +54,6 @@ describe('functional test verdaccio', function() { notify(app); // requires packages published to server1/server2 upLinkCache(server1, server2, server3); - upLinkAuth(); adduser(server1); logout(server1); basic(server1, server2); diff --git a/test/functional/gh29.js b/test/functional/scenarios/gh29.js similarity index 66% rename from test/functional/gh29.js rename to test/functional/scenarios/gh29.js index 13b2191cd..87dd6ba34 100644 --- a/test/functional/gh29.js +++ b/test/functional/scenarios/gh29.js @@ -1,10 +1,15 @@ -import {createTarballHash} from "../../src/lib/crypto-utils"; +import {createTarballHash} from "../../../src/lib/crypto-utils"; +import {HTTP_STATUS} from "../../../src/lib/constants"; +import fs from 'fs'; +import path from 'path'; -function readfile(x) { - return require('fs').readFileSync(__dirname + '/' + x); +function readfile(filePath) { + const folder = path.join(__dirname , filePath); + + return fs.readFileSync(folder); } -const binary = 'fixtures/binary'; +const binary = '../fixtures/binary'; const pkgName = 'testpkg-gh29'; const pkgContent = 'blahblah'; @@ -12,7 +17,7 @@ export default function (server, server2) { test('downloading non-existent tarball #1 / srv2', () => { return server2.getTarball(pkgName, pkgContent) - .status(404) + .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such package/); }); @@ -20,8 +25,8 @@ export default function (server, server2) { beforeAll(function() { - return server.putPackage(pkgName, require('./fixtures/package')(pkgName)) - .status(201) + return server.putPackage(pkgName, require('../fixtures/package')(pkgName)) + .status(HTTP_STATUS.CREATED) .body_ok(/created new package/); }); @@ -29,14 +34,14 @@ export default function (server, server2) { test('downloading non-existent tarball #2 / srv2', () => { return server2.getTarball(pkgName, pkgContent) - .status(404) + .status(HTTP_STATUS.NOT_FOUND) .body_error(/no such file available/); }); describe('tarball', () => { beforeAll(function() { return server.putTarball(pkgName, pkgContent, readfile(binary)) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok(/.*/); }); @@ -44,10 +49,10 @@ export default function (server, server2) { describe('pkg version', () => { beforeAll(function() { - const pkg = require('./fixtures/package')(pkgName); + const pkg = require('../fixtures/package')(pkgName); pkg.dist.shasum = createTarballHash().update(readfile(binary)).digest('hex'); return server.putVersion(pkgName, '0.0.1', pkg) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); @@ -55,7 +60,7 @@ export default function (server, server2) { test('downloading newly created tarball / srv2', () => { return server2.getTarball(pkgName, pkgContent) - .status(200) + .status(HTTP_STATUS.OK) .then(function(body) { expect(body).toEqual(readfile(binary)); }); diff --git a/test/functional/uplink.auth.js b/test/functional/uplink.auth.js deleted file mode 100644 index 2a15817b2..000000000 --- a/test/functional/uplink.auth.js +++ /dev/null @@ -1,151 +0,0 @@ -import ProxyStorage from '../../src/lib/up-storage'; -import {ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_REGISTRY} from "../../src/lib/constants"; -import {buildToken} from "../../src/lib/utils"; - -function createUplink(config) { - const defaultConfig = { - url: DEFAULT_REGISTRY - }; - let mergeConfig = Object.assign({}, defaultConfig, config); - return new ProxyStorage(mergeConfig, {}); -} - -function setHeaders(config, headers) { - config = config || {}; - headers = headers || {}; - const uplink = createUplink(config); - return uplink._setHeaders({ - headers - }); -} - -export default function () { - - describe('uplink auth test', () => { - - test('if set headers empty should return default headers', () => { - const headers = setHeaders(); - const keys = Object.keys(headers); - const keysExpected = ['Accept', 'Accept-Encoding', 'User-Agent']; - - expect(keys).toEqual(keysExpected); - expect(keys).toHaveLength(3); - }); - - test('if assigns value invalid to attribute auth', () => { - const fnError = function () { - setHeaders({ - auth: '' - }); - }; - - expect(function ( ) { - fnError(); - }).toThrow(Error('Auth invalid')); - }); - - test('if assigns the header authorization', () => { - const headers = setHeaders({}, { - 'authorization': buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==') - }); - - expect(Object.keys(headers)).toHaveLength(4); - expect(headers['authorization']).toEqual(buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==')); - }); - - test( - 'if assigns headers authorization and token the header precedes', - () => { - const headers = setHeaders({ - auth: { - type: TOKEN_BEARER, - token: 'tokenBearer' - } - }, { - 'authorization': buildToken(TOKEN_BASIC, 'tokenBasic') - }); - - expect(headers['authorization']).toEqual(buildToken(TOKEN_BASIC, 'tokenBasic')); - } - ); - - test('set type auth basic', () => { - const headers = setHeaders({ - auth: { - type: TOKEN_BASIC, - token: 'Zm9vX2Jhcg==' - } - }); - - expect(Object.keys(headers)).toHaveLength(4); - expect(headers['authorization']).toEqual(buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==')); - }); - - test('set type auth bearer', () => { - const headers = setHeaders({ - auth: { - type: TOKEN_BEARER, - token: 'Zm9vX2Jhcf===' - } - }); - - expect(Object.keys(headers)).toHaveLength(4); - expect(headers['authorization']).toEqual(buildToken(TOKEN_BEARER, 'Zm9vX2Jhcf===')); - }); - - test('set auth type invalid', () => { - const fnError = function() { - setHeaders({ - auth: { - type: 'null', - token: 'Zm9vX2Jhcf===' - } - }) - }; - - expect(function ( ) { - fnError(); - }).toThrow(Error(`Auth type 'null' not allowed`)); - }); - - test('set auth with NPM_TOKEN', () => { - process.env.NPM_TOKEN = 'myToken'; - const headers = setHeaders({ - auth: { - type: TOKEN_BEARER - } - }); - - expect(headers['authorization']).toBe(`${TOKEN_BEARER} myToken`); - delete process.env.NPM_TOKEN; - }); - - test('set auth with token name and assigns in env', () => { - process.env.NPM_TOKEN_TEST = 'myTokenTest'; - const headers = setHeaders({ - auth: { - type: TOKEN_BASIC, - token_env: 'NPM_TOKEN_TEST' - } - }); - - expect(headers['authorization']).toBe(buildToken(TOKEN_BASIC, 'myTokenTest')); - delete process.env.NPM_TOKEN_TEST; - }); - - - test('if token not set', () => { - const fnError = function() { - setHeaders({ - auth: { - type: TOKEN_BASIC - } - }); - }; - - expect(function( ) { - fnError(); - }).toThrow(ERROR_CODE.token_required); - }); - }); -} diff --git a/test/functional/uplink.cache.js b/test/functional/uplinks/cache.js similarity index 76% rename from test/functional/uplink.cache.js rename to test/functional/uplinks/cache.js index 4ae51568b..d1484729c 100644 --- a/test/functional/uplink.cache.js +++ b/test/functional/uplinks/cache.js @@ -2,13 +2,14 @@ import fs from 'fs'; import path from 'path'; import assert from 'assert'; import crypto from 'crypto'; -import {readFile} from './lib/test.utils'; +import {readFile} from '../lib/test.utils'; +import {HTTP_STATUS} from "../../../src/lib/constants"; function getBinary() { return readFile('../fixtures/binary'); } -const STORAGE = 'store/test-storage3'; +const STORAGE = '../store/test-storage3'; const TARBALL = 'blahblah'; const PKG_GH131 = 'pkg-gh131'; const PKG_GH1312 = 'pkg-gh1312'; @@ -22,33 +23,32 @@ export default function (server, server2, server3) { describe('storage tarball cache test', () => { //more info #131 - beforeAll(function () { return server.addPackage(PKG_GH131); }); beforeAll(function () { return server.putTarball(PKG_GH131, TARBALL, getBinary()) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok(/.*/); }); beforeAll(function () { - const pkg = require('./fixtures/package')(PKG_GH131); + const pkg = require('../fixtures/package')(PKG_GH131); pkg.dist.shasum = crypto.createHash('sha1').update(getBinary()).digest('hex'); return server.putVersion(PKG_GH131, '0.0.1', pkg) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); beforeAll(function () { - return server3.getPackage(PKG_GH131).status(200); + return server3.getPackage(PKG_GH131).status(HTTP_STATUS.OK); }); beforeAll(function () { return server3.getTarball(PKG_GH131, TARBALL) - .status(200); + .status(HTTP_STATUS.OK); }); test('should be caching packages from uplink server1', () => { @@ -61,27 +61,27 @@ export default function (server, server2, server3) { beforeAll(function () { return server2.putTarball(PKG_GH1312, TARBALL, getBinary()) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok(/.*/); }); beforeAll(function () { - const pkg = require('./fixtures/package')(PKG_GH1312); + const pkg = require('../fixtures/package')(PKG_GH1312); pkg.dist.shasum = crypto.createHash('sha1').update(getBinary()).digest('hex'); return server2.putVersion(PKG_GH1312, '0.0.1', pkg) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok(/published/); }); beforeAll(function () { return server3.getPackage(PKG_GH1312) - .status(200); + .status(HTTP_STATUS.OK); }); beforeAll(function () { return server3.getTarball(PKG_GH1312, TARBALL) - .status(200); + .status(HTTP_STATUS.OK); }); test('must not be caching packages from uplink server2', () => { diff --git a/test/lib/server.js b/test/lib/server.js index 7822bda31..c84babd00 100644 --- a/test/lib/server.js +++ b/test/lib/server.js @@ -4,10 +4,11 @@ import _ from 'lodash'; import assert from 'assert'; import smartRequest from './request'; import type {IServerBridge} from '../types'; -import {HEADERS} from '../../src/lib/constants'; +import {HEADERS, HTTP_STATUS, TOKEN_BASIC} from '../../src/lib/constants'; +import {buildToken} from "../../src/lib/utils"; const buildAuthHeader = (user, pass): string => { - return `Basic ${(new Buffer(`${user}:${pass}`)).toString('base64')}`; + return buildToken(TOKEN_BASIC, new Buffer(`${user}:${pass}`).toString('base64')); }; export default class Server implements IServerBridge { @@ -22,7 +23,6 @@ export default class Server implements IServerBridge { } request(options: any): any { - // console.log("--->$$$$ REQUEST", options); assert(options.uri); const headers = options.headers || {}; @@ -182,14 +182,14 @@ export default class Server implements IServerBridge { addPackage(name: string) { return this.putPackage(name, require('../functional/fixtures/package')(name)) - .status(201) + .status(HTTP_STATUS.CREATED) .body_ok('created new package'); } whoami() { return this.request({ uri: '/-/whoami' - }).status(200) + }).status(HTTP_STATUS.OK) .then(function(body) { return body.username; }); @@ -198,7 +198,7 @@ export default class Server implements IServerBridge { ping() { return this.request({ uri: '/-/ping' - }).status(200) + }).status(HTTP_STATUS.OK) .then(function(body) { return body; }); diff --git a/test/unit/api/uplink.auth.spec.js b/test/unit/api/uplink.auth.spec.js new file mode 100644 index 000000000..c78ec41f0 --- /dev/null +++ b/test/unit/api/uplink.auth.spec.js @@ -0,0 +1,151 @@ +import ProxyStorage from '../../../src/lib/up-storage'; +import {ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_REGISTRY} from "../../../src/lib/constants"; +import {buildToken} from "../../../src/lib/utils"; +import {setup} from '../../../src/lib/logger'; + +setup([]); + +function createUplink(config) { + const defaultConfig = { + url: DEFAULT_REGISTRY + }; + let mergeConfig = Object.assign({}, defaultConfig, config); + return new ProxyStorage(mergeConfig, {}); +} + +function setHeaders(config, headers) { + config = config || {}; + headers = headers || {}; + const uplink = createUplink(config); + return uplink._setHeaders({ + headers + }); +} + +describe('uplink auth test', () => { + + test('if set headers empty should return default headers', () => { + const headers = setHeaders(); + const keys = Object.keys(headers); + const keysExpected = ['Accept', 'Accept-Encoding', 'User-Agent']; + + expect(keys).toEqual(keysExpected); + expect(keys).toHaveLength(3); + }); + + test('if assigns value invalid to attribute auth', () => { + const fnError = function () { + setHeaders({ + auth: '' + }); + }; + + expect(function ( ) { + fnError(); + }).toThrow(Error('Auth invalid')); + }); + + test('if assigns the header authorization', () => { + const headers = setHeaders({}, { + 'authorization': buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==') + }); + + expect(Object.keys(headers)).toHaveLength(4); + expect(headers['authorization']).toEqual(buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==')); + }); + + test( + 'if assigns headers authorization and token the header precedes', + () => { + const headers = setHeaders({ + auth: { + type: TOKEN_BEARER, + token: 'tokenBearer' + } + }, { + 'authorization': buildToken(TOKEN_BASIC, 'tokenBasic') + }); + + expect(headers['authorization']).toEqual(buildToken(TOKEN_BASIC, 'tokenBasic')); + } + ); + + test('set type auth basic', () => { + const headers = setHeaders({ + auth: { + type: TOKEN_BASIC, + token: 'Zm9vX2Jhcg==' + } + }); + + expect(Object.keys(headers)).toHaveLength(4); + expect(headers['authorization']).toEqual(buildToken(TOKEN_BASIC, 'Zm9vX2Jhcg==')); + }); + + test('set type auth bearer', () => { + const headers = setHeaders({ + auth: { + type: TOKEN_BEARER, + token: 'Zm9vX2Jhcf===' + } + }); + + expect(Object.keys(headers)).toHaveLength(4); + expect(headers['authorization']).toEqual(buildToken(TOKEN_BEARER, 'Zm9vX2Jhcf===')); + }); + + test('set auth type invalid', () => { + const fnError = function() { + setHeaders({ + auth: { + type: 'null', + token: 'Zm9vX2Jhcf===' + } + }) + }; + + expect(function ( ) { + fnError(); + }).toThrow(Error(`Auth type 'null' not allowed`)); + }); + + test('set auth with NPM_TOKEN', () => { + process.env.NPM_TOKEN = 'myToken'; + const headers = setHeaders({ + auth: { + type: TOKEN_BEARER + } + }); + + expect(headers['authorization']).toBe(`${TOKEN_BEARER} myToken`); + delete process.env.NPM_TOKEN; + }); + + test('set auth with token name and assigns in env', () => { + process.env.NPM_TOKEN_TEST = 'myTokenTest'; + const headers = setHeaders({ + auth: { + type: TOKEN_BASIC, + token_env: 'NPM_TOKEN_TEST' + } + }); + + expect(headers['authorization']).toBe(buildToken(TOKEN_BASIC, 'myTokenTest')); + delete process.env.NPM_TOKEN_TEST; + }); + + + test('if token not set', () => { + const fnError = function() { + setHeaders({ + auth: { + type: TOKEN_BASIC + } + }); + }; + + expect(function( ) { + fnError(); + }).toThrow(ERROR_CODE.token_required); + }); +});