From 45110ddb7b38ff106146906fe8f296aab6e46b23 Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Thu, 28 Jun 2018 18:33:37 +0200 Subject: [PATCH] refactor: migration assert to expect --- conf/default.yaml | 4 + conf/docker.yaml | 4 + conf/full.yaml | 39 ++++--- src/api/web/index.js | 4 +- src/lib/auth.js | 3 +- src/lib/constants.js | 13 ++- test/unit/api/basic_system.spec.js | 21 ++-- test/unit/api/cli.spec.js | 16 +-- test/unit/api/config.spec.js | 100 ++++++++++++------ test/unit/api/listen_addr.spec.js | 25 +++-- test/unit/partials/config/access.js | 3 +- .../webui/components/packagedetail.spec.js | 5 +- 12 files changed, 147 insertions(+), 90 deletions(-) diff --git a/conf/default.yaml b/conf/default.yaml index 2d7af82d2..a39155377 100644 --- a/conf/default.yaml +++ b/conf/default.yaml @@ -9,6 +9,10 @@ # path to a directory with all packages storage: ./storage +web: + # WebUI is enabled as default, if you want disable it, just uncomment this line + title: Verdaccio + auth: htpasswd: file: ./htpasswd diff --git a/conf/docker.yaml b/conf/docker.yaml index 4c8ace41f..483741ea2 100644 --- a/conf/docker.yaml +++ b/conf/docker.yaml @@ -13,6 +13,10 @@ # path to a directory with all packages storage: /verdaccio/storage +web: + # WebUI is enabled as default, if you want disable it, just uncomment this line + title: Verdaccio + auth: htpasswd: file: /verdaccio/conf/htpasswd diff --git a/conf/full.yaml b/conf/full.yaml index b9de76ff4..77ece316a 100644 --- a/conf/full.yaml +++ b/conf/full.yaml @@ -16,10 +16,11 @@ auth: # You can set this to -1 to disable registration. #max_users: 1000 -# Experimental built-in middlewares -#middlewares: -# audit: -# enabled: true +# Configure plugins that can register custom middlewares +# To use `npm audit` uncomment the following section +middlewares: + audit: + enabled: true # a list of other known repositories we can talk to uplinks: @@ -141,34 +142,34 @@ logs: # webhooks, but will also deliver a simple payload to # any endpoint. Currently only active for publish / create # commands. -notify: +#notify: # Choose a method. Technically this will accept any HTTP # request method, but probably stick to GET or POST - method: POST +# method: POST # Only run this notification if the package name matches the regular # expression - packagePattern: ^example-package$ +# packagePattern: ^example-package$ # Any flags to be used with the regular expression - packagePatternFlags: i +# packagePatternFlags: i # If this endpoint requires specific headers, set them here # as an array of key: value objects. - headers: [{'Content-type': 'application/x-www-form-urlencoded'}] +# headers: [{'Content-type': 'application/x-www-form-urlencoded'}] # set the URL endpoint for this call - endpoint: https://hooks.slack.com/... +# endpoint: https://hooks.slack.com/... # Finally, the content you will be sending in the body. # This data will first be run through Handlebars to parse # any Handlebar expressions. All data housed in the metadata object # is available for use within the expressions. - content: ' {{ handlebar-expression }}' +# content: ' {{ handlebar-expression }}' # For Slack, follow the following format: # content: '{ "text": "Package *{{ name }}* published to version *{{ dist-tags.latest }}*", "username": "Verdaccio", "icon_emoji": ":package:" }' # Multiple notification endpoints can be created by specifying a collection - 'example-package-1': - method: POST +# 'example-package-1': +# method: POST # Only run this notification if the package name matches the regular # expression - packagePattern: ^example-package-regex$ +# packagePattern: ^example-package-regex$ # Any flags to be used with the regular expression # since verdaccio 2.2.2 this property has been disabled read #108 # it will be re-enabled after 2.5.0 @@ -176,18 +177,14 @@ notify: # If this endpoint requires specific headers, set them here # as an array of key: value objects. # headers supports as well a literal object - headers: {'Content-type': 'application/x-www-form-urlencoded'} +# headers: {'Content-type': 'application/x-www-form-urlencoded'} # set the URL endpoint for this call - endpoint: https://hooks.slack.com/... +# endpoint: https://hooks.slack.com/... # Finally, the content you will be sending in the body. # This data will first be run through Handlebars to parse # any Handlebar expressions. All data housed in the metadata object # is available for use within the expressions. - content: ' {{ handlebar-expression }}' +# content: ' {{ handlebar-expression }}' # For Slack, follow the following format: # content: '{ "text": "Package *{{ name }}* published to version *{{ dist-tags.latest }}*", "username": "Verdaccio", "icon_emoji": ":package:" }' -# Configure plugins that can register custom middlewares -#middlewares: -# plugin-name: -# setting: true diff --git a/src/api/web/index.js b/src/api/web/index.js index 316168aee..cc37b5ca4 100644 --- a/src/api/web/index.js +++ b/src/api/web/index.js @@ -3,6 +3,7 @@ import _ from 'lodash'; import fs from 'fs'; import Search from '../../lib/search'; import * as Utils from '../../lib/utils'; +import {WEB_TITLE} from '../../lib/constants'; const {securityIframe} = require('../middleware'); /* eslint new-cap:off */ @@ -40,10 +41,9 @@ module.exports = function(config, auth, storage) { router.get('/', function(req, res) { const base = Utils.combineBaseUrl(Utils.getWebProtocol(req), req.get('host'), config.url_prefix); - const defaultTitle = 'Verdaccio'; let webPage = template .replace(/ToReplaceByVerdaccio/g, base) - .replace(/ToReplaceByTitle/g, _.get(config, 'web.title') ? config.web.title : defaultTitle); + .replace(/ToReplaceByTitle/g, _.get(config, 'web.title') ? config.web.title : WEB_TITLE); res.setHeader('Content-Type', 'text/html'); diff --git a/src/lib/auth.js b/src/lib/auth.js index a66921d67..c53af7ebc 100644 --- a/src/lib/auth.js +++ b/src/lib/auth.js @@ -8,6 +8,7 @@ import {aesDecrypt, aesEncrypt, signPayload, verifyPayload} from './crypto-utils import type {Config, Logger, Callback} from '@verdaccio/types'; import type {$Response, NextFunction} from 'express'; import type {$RequestExtend, JWTPayload} from '../../types'; +import {ROLES} from './constants'; const LoggerApi = require('./logger'); @@ -360,7 +361,7 @@ function buildAnonymousUser() { */ function authenticatedUser(name: string, pluginGroups: Array) { const isGroupValid: boolean = _.isArray(pluginGroups); - const groups = (isGroupValid ? pluginGroups : []).concat(['$all', '$authenticated', '@all', '@authenticated', 'all']); + const groups = (isGroupValid ? pluginGroups : []).concat([ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL]); return { name, diff --git a/src/lib/constants.js b/src/lib/constants.js index c00e072ec..8121a7a06 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -21,8 +21,16 @@ export const ERROR_CODE = { export const TOKEN_BASIC = 'Basic'; export const TOKEN_BEARER = 'Bearer'; -export const DEFAULT_REGISTRY = 'https://registry.npmjs.org/'; +export const DEFAULT_REGISTRY = 'https://registry.npmjs.org'; +export const DEFAULT_UPLINK = 'npmjs'; +export const ROLES = { + $ALL: '$all', + $AUTH: '$authenticated', + DEPRECATED_ALL: '@all', + DEPRECATED_AUTH: '@authenticated', + ALL: 'all', +}; export const HTTP_STATUS = { OK: 200, @@ -69,3 +77,6 @@ export const API_ERROR = { }; export const DEFAULT_NO_README = 'ERROR: No README data found!'; + + +export const WEB_TITLE = 'Verdaccio'; diff --git a/test/unit/api/basic_system.spec.js b/test/unit/api/basic_system.spec.js index 2f1f2a0f9..c969aa499 100644 --- a/test/unit/api/basic_system.spec.js +++ b/test/unit/api/basic_system.spec.js @@ -1,11 +1,10 @@ import endPointAPI from '../../../src/api/index'; +import {API_ERROR} from '../../../src/lib/constants'; -const assert = require('assert'); -const express = require('express'); -const request = require('request'); -const rimraf = require('rimraf'); - -const config = require('../partials/config/index'); +import express from 'express'; +import request from 'request'; +import rimraf from 'rimraf'; +import config from '../partials/config/index'; const app = express(); const server = require('http').createServer(app); @@ -35,18 +34,18 @@ describe('basic system test', () => { request({ url: 'http://localhost:' + port + '/', }, function(err, res, body) { - assert.equal(err, null); - assert(body.match(/Verdaccio<\/title>/)); + expect(err).toBeNull(); + expect(body).toMatch(/<title>Verdaccio<\/title>/); done(); }); }); test('server should respond on /whatever', done => { request({ - url: 'http://localhost:' + port + '/whatever', + url: `http://localhost:${port}/whatever`, }, function(err, res, body) { - assert.equal(err, null); - assert(body.match(/no such package available/)); + expect(err).toBeNull(); + expect(body).toMatch(API_ERROR.NO_PACKAGE); done(); }); }); diff --git a/test/unit/api/cli.spec.js b/test/unit/api/cli.spec.js index c39a3c7b5..891abe3df 100644 --- a/test/unit/api/cli.spec.js +++ b/test/unit/api/cli.spec.js @@ -1,8 +1,9 @@ +import path from 'path'; +import _ from 'lodash'; + import startServer from '../../../src/index'; import {getListListenAddresses} from '../../../src/lib/bootstrap'; import config from '../partials/config/index'; -import path from 'path'; -import _ from 'lodash'; require('../../../src/lib/logger').setup([]); @@ -11,18 +12,21 @@ describe('startServer via API', () => { describe('startServer launcher', () => { test('should provide all server data await/async', async (done) => { const store = path.join(__dirname, 'partials/store'); + const serverName = 'verdaccio-test'; + const version = '1.0.0'; + const port = '6000'; - await startServer(config, 6000, store, '1.0.0', 'verdaccio-test', + await startServer(config, port, store, version, serverName, (webServer, addrs, pkgName, pkgVersion) => { expect(webServer).toBeDefined(); expect(addrs).toBeDefined(); expect(addrs.proto).toBe('http'); expect(addrs.host).toBe('localhost'); - expect(addrs.port).toBe('6000'); + expect(addrs.port).toBe(port); expect(pkgName).toBeDefined(); expect(pkgVersion).toBeDefined(); - expect(pkgVersion).toBe('1.0.0'); - expect(pkgName).toBe('verdaccio-test'); + expect(pkgVersion).toBe(version); + expect(pkgName).toBe(serverName); done(); }); }); diff --git a/test/unit/api/config.spec.js b/test/unit/api/config.spec.js index 7e176404b..074c5e396 100644 --- a/test/unit/api/config.spec.js +++ b/test/unit/api/config.spec.js @@ -1,55 +1,91 @@ -const assert = require('assert'); -const Utils = require('../../../src/lib/utils'); -const Config = require('../../../src/lib/config'); -const path = require('path'); -const _ = require('lodash'); +import path from 'path'; +import _ from 'lodash'; + +import Config from '../../../src/lib/config'; +import {parseConfigFile} from '../../../src/lib/utils'; +import {DEFAULT_REGISTRY, DEFAULT_UPLINK, ROLES, WEB_TITLE} from '../../../src/lib/constants'; const resolveConf = (conf) => path.join(__dirname, `../../../conf/${conf}.yaml`); -const checkUplink = (config) => { - assert.equal(_.isObject(config.uplinks['npmjs']), true); - assert.equal(config.uplinks['npmjs'].url, 'https://registry.npmjs.org'); +const checkDefaultUplink = (config) => { + expect(_.isObject(config.uplinks[DEFAULT_UPLINK])).toBeTruthy(); + expect(config.uplinks[DEFAULT_UPLINK].url).toMatch(DEFAULT_REGISTRY); }; -const checkPackages = (config) => { - assert.equal(_.isObject(config.packages), true); - assert.equal(Object.keys(config.packages).join('|'), '@*/*|**'); - assert.equal(config.packages['@*/*'].access, '$all'); - assert.equal(config.packages['@*/*'].publish, '$authenticated'); - assert.equal(config.packages['@*/*'].proxy, 'npmjs'); - assert.equal(config.packages['**'].access, '$all'); - assert.equal(config.packages['**'].publish, '$authenticated'); - assert.equal(config.packages['**'].proxy, 'npmjs'); - assert.equal(config.uplinks['npmjs'].url, 'https://registry.npmjs.org'); +const checkDefaultConfPackages = (config) => { + //auth + expect(_.isObject(config.auth)).toBeTruthy(); + expect(_.isObject(config.auth.htpasswd)).toBeTruthy(); + expect(config.auth.htpasswd.file).toMatch(/htpasswd/); + + //web + expect(_.isObject(config.web)).toBeTruthy(); + expect(config.web.title).toBe(WEB_TITLE); + expect(config.web.enable).toBeUndefined(); + + // packages + expect(_.isObject(config.packages)).toBeTruthy(); + expect(Object.keys(config.packages).join('|')).toBe('@*/*|**'); + expect(config.packages['@*/*'].access).toBeDefined(); + expect(config.packages['@*/*'].access).toContainEqual(ROLES.$ALL); + expect(config.packages['@*/*'].publish).toBeDefined(); + expect(config.packages['@*/*'].publish).toContainEqual(ROLES.$AUTH); + expect(config.packages['@*/*'].proxy).toBeDefined(); + expect(config.packages['@*/*'].proxy).toContainEqual(DEFAULT_UPLINK); + expect(config.packages['**'].access).toBeDefined(); + expect(config.packages['**'].access).toContainEqual(ROLES.$ALL); + expect(config.packages['**'].publish).toBeDefined(); + expect(config.packages['**'].publish).toContainEqual(ROLES.$AUTH); + expect(config.packages['**'].proxy).toBeDefined(); + expect(config.packages['**'].proxy,).toContainEqual(DEFAULT_UPLINK); + // uplinks + expect(config.uplinks[DEFAULT_UPLINK]).toBeDefined(); + expect(config.uplinks[DEFAULT_UPLINK].url).toEqual(DEFAULT_REGISTRY); + // audit + expect(config.middlewares).toBeDefined(); + expect(config.middlewares.audit).toBeDefined(); + expect(config.middlewares.audit.enabled).toBeTruthy(); + // logs + expect(config.logs).toBeDefined(); + expect(config.logs[0].type).toEqual('stdout'); + expect(config.logs[0].format).toEqual('pretty'); + expect(config.logs[0].level).toEqual('http'); + //must not be enabled by default + expect(config.notify).toBeUndefined(); + expect(config.store).toBeUndefined(); + expect(config.publish).toBeUndefined(); + expect(config.url_prefix).toBeUndefined(); + expect(config.url_prefix).toBeUndefined(); }; describe('Config file', () => { beforeAll(function() { - this.config = new Config(Utils.parseConfigFile(resolveConf('full'))); + this.config = new Config(parseConfigFile(resolveConf('full'))); }); describe('Config file', () => { test('parse full.yaml', () => { - const config = new Config(Utils.parseConfigFile(resolveConf('full'))); - checkUplink(config); - assert.equal(config.storage, './storage'); - assert.equal(config.web.title, 'Verdaccio'); - checkPackages(config); + const config = new Config(parseConfigFile(resolveConf('full'))); + checkDefaultUplink(config); + expect(config.storage).toBe('./storage'); + checkDefaultConfPackages(config); }); test('parse docker.yaml', () => { - const config = new Config(Utils.parseConfigFile(resolveConf('docker'))); - checkUplink(config); - assert.equal(config.storage, '/verdaccio/storage'); - assert.equal(config.auth.htpasswd.file, '/verdaccio/conf/htpasswd'); + const config = new Config(parseConfigFile(resolveConf('docker'))); + checkDefaultUplink(config); + expect(config.storage).toBe('/verdaccio/storage'); + expect(config.auth.htpasswd.file).toBe('/verdaccio/conf/htpasswd'); + checkDefaultConfPackages(config); }); test('parse default.yaml', () => { - const config = new Config(Utils.parseConfigFile(resolveConf('default'))); - checkUplink(config); - assert.equal(config.storage, './storage'); - assert.equal(config.auth.htpasswd.file, './htpasswd'); + const config = new Config(parseConfigFile(resolveConf('default'))); + checkDefaultUplink(config); + expect(config.storage).toBe('./storage'); + expect(config.auth.htpasswd.file).toBe('./htpasswd'); + checkDefaultConfPackages(config); }); }); diff --git a/test/unit/api/listen_addr.spec.js b/test/unit/api/listen_addr.spec.js index 392e0da31..de46e0650 100644 --- a/test/unit/api/listen_addr.spec.js +++ b/test/unit/api/listen_addr.spec.js @@ -1,22 +1,21 @@ -const assert = require('assert'); -const _ = require('lodash'); -const parse = require('../../../src/lib/utils').parse_address; +import _ from 'lodash'; +import {parse_address as parse} from '../../../src/lib/utils'; describe('Parse listen address', () => { - function addTest(what, proto, host, port) { - test(what, () => { + function addTest(uri, proto, host, port) { + test(uri, () => { if (_.isNull(proto)) { - assert.strictEqual(parse(what), null); + expect(parse(uri)).toBeNull(); } else if (port) { - assert.deepEqual(parse(what), { - proto: proto, - host: host, - port: port, + expect(parse(uri)).toEqual({ + proto, + host, + port, }); } else { - assert.deepEqual(parse(what), { - proto: proto, - path: host, + expect(parse(uri)).toEqual({ + proto, + host, }); } }); diff --git a/test/unit/partials/config/access.js b/test/unit/partials/config/access.js index 3e63b08d4..480e5bdb2 100644 --- a/test/unit/partials/config/access.js +++ b/test/unit/partials/config/access.js @@ -1,10 +1,11 @@ import path from 'path'; +import {DEFAULT_REGISTRY} from '../../../../src/lib/constants'; const config = { storage: path.join(__dirname, '../store/access-storage'), uplinks: { 'npmjs': { - 'url': 'https://registry.npmjs.org/' + 'url': DEFAULT_REGISTRY } }, packages: { diff --git a/test/unit/webui/components/packagedetail.spec.js b/test/unit/webui/components/packagedetail.spec.js index 69083351c..526ff03ec 100644 --- a/test/unit/webui/components/packagedetail.spec.js +++ b/test/unit/webui/components/packagedetail.spec.js @@ -5,6 +5,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import PackageDetail from '../../../../src/webui/src/components/PackageDetail/index'; import Readme from '../../../../src/webui/src/components/Readme/index'; +import {WEB_TITLE} from '../../../../src/lib/constants'; console.error = jest.fn(); @@ -17,11 +18,11 @@ describe('<PackageDetail /> component', () => { it('should load the component', () => { const props = { readMe: 'Test readme', - package: 'Verdaccio' + package: WEB_TITLE }; const wrapper = shallow(<PackageDetail {...props} />); - expect(wrapper.find('h1').text()).toEqual('Verdaccio'); + expect(wrapper.find('h1').text()).toEqual(WEB_TITLE); expect( wrapper .find(Readme)