From 394386385e3fa989dcc223f80c052473e8133e83 Mon Sep 17 00:00:00 2001 From: KukuruzaAndrey Date: Mon, 14 Jan 2019 15:23:25 +0200 Subject: [PATCH 1/9] feat: package version gets sent to plugins --- src/api/endpoint/api/search.js | 2 +- src/api/middleware.js | 11 +++++------ src/api/web/endpoint/package.js | 2 +- src/api/web/endpoint/search.js | 2 +- src/lib/auth.js | 10 +++++----- src/lib/utils.js | 10 ++++++++++ .../middleware/example.middleware.plugin.js | 2 +- test/unit/api/utils.spec.js | 18 +++++++++++++++++- 8 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/api/endpoint/api/search.js b/src/api/endpoint/api/search.js index c5872e4a4..0c89d2128 100644 --- a/src/api/endpoint/api/search.js +++ b/src/api/endpoint/api/search.js @@ -61,7 +61,7 @@ export default function(route, auth, storage) { stream.on('data', function each(pkg) { processing_pkgs++; - auth.allow_access(pkg.name, req.remote_user, function(err, allowed) { + auth.allow_access({ packageName: pkg.name }, req.remote_user, function(err, allowed) { processing_pkgs--; if (err) { diff --git a/src/api/middleware.js b/src/api/middleware.js index 9a474ae4e..8e24ad858 100644 --- a/src/api/middleware.js +++ b/src/api/middleware.js @@ -5,7 +5,7 @@ import _ from 'lodash'; -import { validateName as utilValidateName, validatePackage as utilValidatePackage, isObject, ErrorCode } from '../lib/utils'; +import { validateName as utilValidateName, validatePackage as utilValidatePackage, getVersionFromTarball, isObject, ErrorCode } from '../lib/utils'; import { API_ERROR, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '../lib/constants'; import { stringToMD5 } from '../lib/crypto-utils'; import type { $ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth } from '../../types'; @@ -99,12 +99,11 @@ export function allow(auth: IAuth) { return function(action: string) { return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { req.pause(); - let packageName = req.params.package; - if (req.params.scope) { - packageName = `@${req.params.scope}/${packageName}`; - } + const packageName = req.params.scope ? `@${req.params.scope}/${req.params.package}` : req.params.package; + const packageVersion = req.params.filename ? getVersionFromTarball(req.params.filename) : undefined; + // $FlowFixMe - auth['allow_' + action](packageName, req.remote_user, function(error, allowed) { + auth['allow_' + action]({ packageName, packageVersion }, req.remote_user, function(error, allowed) { req.resume(); if (error) { next(error); diff --git a/src/api/web/endpoint/package.js b/src/api/web/endpoint/package.js index 3f3a333f4..38e88e632 100644 --- a/src/api/web/endpoint/package.js +++ b/src/api/web/endpoint/package.js @@ -17,7 +17,7 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, const checkAllow = (name, remoteUser) => new Promise((resolve, reject) => { try { - auth.allow_access(name, remoteUser, (err, allowed) => { + auth.allow_access({ packageName: name }, remoteUser, (err, allowed) => { if (err) { resolve(false); } else { diff --git a/src/api/web/endpoint/search.js b/src/api/web/endpoint/search.js index b40780b56..09cdd4ed5 100644 --- a/src/api/web/endpoint/search.js +++ b/src/api/web/endpoint/search.js @@ -20,7 +20,7 @@ function addSearchWebApi(route: Router, storage: IStorageHandler, auth: IAuth) { uplinksLook: false, callback: (err, entry) => { if (!err && entry) { - auth.allow_access(entry.name, req.remote_user, function(err, allowed) { + auth.allow_access({ packageName: entry.name }, req.remote_user, function(err, allowed) { if (err || !allowed) { return; } diff --git a/src/lib/auth.js b/src/lib/auth.js index bd154f419..7694b0d4e 100644 --- a/src/lib/auth.js +++ b/src/lib/auth.js @@ -23,7 +23,7 @@ import { import { convertPayloadToBase64, ErrorCode } from './utils'; import { getMatchedPackagesSpec } from './config-utils'; -import type { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security } from '@verdaccio/types'; +import type { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage } from '@verdaccio/types'; import type { $Response, NextFunction } from 'express'; import type { $RequestExtend, IAuth } from '../../types'; @@ -160,10 +160,10 @@ class Auth implements IAuth { /** * Allow user to access a package. */ - allow_access(packageName: string, user: RemoteUser, callback: Callback) { + allow_access({ packageName, packageVersion }: AuthPluginPackage, user: RemoteUser, callback: Callback) { const plugins = this.plugins.slice(0); // $FlowFixMe - const pkg = Object.assign({ name: packageName }, getMatchedPackagesSpec(packageName, this.config.packages)); + const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages)); const self = this; this.logger.trace({ packageName }, 'allow access for @{packageName}'); @@ -193,11 +193,11 @@ class Auth implements IAuth { /** * Allow user to publish a package. */ - allow_publish(packageName: string, user: string, callback: Callback) { + allow_publish({ packageName, packageVersion }: AuthPluginPackage, user: string, callback: Callback) { const plugins = this.plugins.slice(0); const self = this; // $FlowFixMe - const pkg = Object.assign({ name: packageName }, getMatchedPackagesSpec(packageName, this.config.packages)); + const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages)); this.logger.trace({ packageName }, 'allow publish for @{packageName}'); (function next() { diff --git a/src/lib/utils.js b/src/lib/utils.js index 561a65dd4..34af6f5ed 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -502,3 +502,13 @@ export function parseReadme(packageName: string, readme: string): string { export function buildToken(type: string, token: string): string { return `${_.capitalize(type)} ${token}`; } + +/** + * return package version from tarball name + * @param {String} name + * @returns {String} + */ +export function getVersionFromTarball(name: string) { + // $FlowFixMe + return /.+-(\d.+)\.tgz/.test(name) ? name.match(/.+-(\d.+)\.tgz/)[1] : undefined; +} diff --git a/test/flow/plugins/middleware/example.middleware.plugin.js b/test/flow/plugins/middleware/example.middleware.plugin.js index 0789a0385..94a667d30 100644 --- a/test/flow/plugins/middleware/example.middleware.plugin.js +++ b/test/flow/plugins/middleware/example.middleware.plugin.js @@ -24,7 +24,7 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware { name: 'test' }; auth.authenticate('user', 'password', () => {}); - auth.allow_access('packageName', remoteUser, () => {}); + auth.allow_access({packageName: 'packageName'}, remoteUser, () => {}); auth.add_user('user', 'password', () => {}); auth.aesEncrypt(new Buffer('pass')); // storage diff --git a/test/unit/api/utils.spec.js b/test/unit/api/utils.spec.js index 4e81f1b3d..3d884389b 100644 --- a/test/unit/api/utils.spec.js +++ b/test/unit/api/utils.spec.js @@ -11,7 +11,8 @@ import { combineBaseUrl, getVersion, normalizeDistTags, - getWebProtocol + getWebProtocol, + getVersionFromTarball } from '../../../src/lib/utils'; import { DIST_TAGS } from '../../../src/lib/constants'; import Logger, { setup } from '../../../src/lib/logger'; @@ -259,6 +260,21 @@ describe('Utilities', () => { }).toThrow(expect.hasAssertions()); }); }); + + describe('getVersionFromTarball', () => { + test('should get the right version', () => { + const simpleName = 'test-name-4.2.12.tgz' + const complexName = 'test-5.6.4-beta.2.tgz' + const otherComplexName = 'test-3.5.0-6.tgz' + expect(getVersionFromTarball(simpleName)).toEqual('4.2.12') + expect(getVersionFromTarball(complexName)).toEqual('5.6.4-beta.2') + expect(getVersionFromTarball(otherComplexName)).toEqual('3.5.0-6') + }) + + test('should don\'n fall at incorrect tarball name', () => { + expect(getVersionFromTarball('incorrectName')).toBeUndefined() + }) + }); }); describe('String utilities', () => { From e9b3907859f8ded39bf22e8fbf47040771215513 Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Mon, 14 Jan 2019 19:19:56 +0100 Subject: [PATCH 2/9] fix: remove unused object (#1185) Remove unused object --- src/lib/local-storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/local-storage.js b/src/lib/local-storage.js index 323b93bdd..ffbc5d8a0 100644 --- a/src/lib/local-storage.js +++ b/src/lib/local-storage.js @@ -641,7 +641,7 @@ class LocalStorage implements IStorage { const {packages} = this.config; if (packages) { - const listPackagesConf = Object.keys(packages || {}); + const listPackagesConf = Object.keys(packages); listPackagesConf.map( (pkg) => { if (packages[pkg].storage) { From f20fefaf8732b1dbad81b106faba6da42279ead7 Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Mon, 14 Jan 2019 19:25:29 +0100 Subject: [PATCH 3/9] fix: remove use of comma separator (#1186) --- src/lib/storage.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/storage.js b/src/lib/storage.js index fdbe3b6ac..e0d7ac091 100644 --- a/src/lib/storage.js +++ b/src/lib/storage.js @@ -324,17 +324,20 @@ class Storage implements IStorageHandler { lstream.pipe(stream, {end: false}); lstream.on('error', function(err) { self.logger.error({err: err}, 'uplink error: @{err.message}'); - cb(), cb = function() {}; + cb(); + cb = function() {}; }); lstream.on('end', function() { - cb(), cb = function() {}; + cb(); + cb = function() {}; }); stream.abort = function() { if (lstream.abort) { lstream.abort(); } - cb(), cb = function() {}; + cb(); + cb = function() {}; }; }, // executed after all series From 064f7cfa5d3a0c66d956ed06561458f88c22e2ef Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Mon, 14 Jan 2019 19:34:03 +0100 Subject: [PATCH 4/9] fix: remove unused parameters from processBody method invocation (#1184) --- src/lib/up-storage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/up-storage.js b/src/lib/up-storage.js index 3fea3d657..c011698de 100644 --- a/src/lib/up-storage.js +++ b/src/lib/up-storage.js @@ -141,7 +141,7 @@ class ProxyStorage implements IProxy { let error; const responseLength = err ? 0 : body.length; // $FlowFixMe - processBody(err, body); + processBody(); logActivity(); // $FlowFixMe cb(err, res, body); From ab56d750cac0caac54a7b3d6f7c2cd8c1b3be382 Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Mon, 14 Jan 2019 19:39:59 +0100 Subject: [PATCH 5/9] fix: remove some unneeded checks (#1182) --- src/lib/storage.js | 2 +- src/lib/up-storage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/storage.js b/src/lib/storage.js index e0d7ac091..e13ac4290 100644 --- a/src/lib/storage.js +++ b/src/lib/storage.js @@ -411,7 +411,7 @@ class Storage implements IStorageHandler { const self = this; const upLinks = []; - if (!packageInfo || packageInfo === null) { + if (!packageInfo) { exists = false; packageInfo = generatePackageTemplate(name); } diff --git a/src/lib/up-storage.js b/src/lib/up-storage.js index c011698de..efd503781 100644 --- a/src/lib/up-storage.js +++ b/src/lib/up-storage.js @@ -540,7 +540,7 @@ class ProxyStorage implements IProxy { // if (this.proxy === false) { headers['X-Forwarded-For'] = ( - req && req.headers['x-forwarded-for'] + req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '' ) + req.connection.remoteAddress; From 13b8347fdd65df8754cad18c0ec0734471a29c70 Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Mon, 14 Jan 2019 20:52:04 +0100 Subject: [PATCH 6/9] fix: remove useless assignment to local variable emailCopy (#1181) --- src/utils/user.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/user.js b/src/utils/user.js index 1a751ba85..e7ea03d8d 100644 --- a/src/utils/user.js +++ b/src/utils/user.js @@ -8,10 +8,9 @@ export const GRAVATAR_DEFAULT = * Generate gravatar url from email address */ export function generateGravatarUrl(email: string = ''): string { - let emailCopy = email; if (_.isString(email) && _.size(email) > 0) { - emailCopy = email.trim().toLocaleLowerCase(); - const emailMD5 = stringToMD5(emailCopy); + email = email.trim().toLocaleLowerCase(); + const emailMD5 = stringToMD5(email); return `https://www.gravatar.com/avatar/${emailMD5}`; } return GRAVATAR_DEFAULT; From 399dc181346530328bbc73405532827466a34cae Mon Sep 17 00:00:00 2001 From: KukuruzaAndrey Date: Tue, 15 Jan 2019 10:28:02 +0200 Subject: [PATCH 7/9] chore: update @verdaccio/types version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b480472f5..485d0848a 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@commitlint/config-conventional": "7.1.2", "@material-ui/core": "3.1.0", "@material-ui/icons": "3.0.1", - "@verdaccio/types": "4.1.3", + "@verdaccio/types": "^4.1.4", "autosuggest-highlight": "3.1.1", "babel-core": "7.0.0-bridge.0", "babel-eslint": "10.0.1", From 056d396b59b3f17553e28163445129c3e275b652 Mon Sep 17 00:00:00 2001 From: Daniel Ruf Date: Tue, 15 Jan 2019 09:29:04 +0100 Subject: [PATCH 8/9] fix: add logic to catch clause (#1183) --- src/api/web/endpoint/package.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api/web/endpoint/package.js b/src/api/web/endpoint/package.js index 5ab515eb8..e1d024588 100644 --- a/src/api/web/endpoint/package.js +++ b/src/api/web/endpoint/package.js @@ -3,6 +3,7 @@ import _ from 'lodash'; import {addScope, addGravatarSupport, deleteProperties, sortByName, DIST_TAGS, parseReadme} from '../../../lib/utils'; import {allow} from '../../middleware'; +import logger from '../../../lib/logger'; import type {Router} from 'express'; import type { IAuth, @@ -45,6 +46,7 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth) permissions.push(pkg); } } catch (err) { + logger.logger.error({name: pkg.name, error: err}, 'permission process for @{name} has failed: @{error}'); throw err; } } From f147b2b131dc42c1ebb42e4c7a14757fdde59329 Mon Sep 17 00:00:00 2001 From: KukuruzaAndrey Date: Tue, 15 Jan 2019 10:49:22 +0200 Subject: [PATCH 9/9] chore: pin @verdaccio/types version --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 485d0848a..b432c6b0c 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@commitlint/config-conventional": "7.1.2", "@material-ui/core": "3.1.0", "@material-ui/icons": "3.0.1", - "@verdaccio/types": "^4.1.4", + "@verdaccio/types": "4.1.4", "autosuggest-highlight": "3.1.1", "babel-core": "7.0.0-bridge.0", "babel-eslint": "10.0.1", diff --git a/yarn.lock b/yarn.lock index f86309fb7..2003837cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1181,10 +1181,10 @@ resolved "https://registry.npmjs.org/@verdaccio/streams/-/streams-1.0.0.tgz#d5d24c6747208728b9fd16b908e3932c3fb1f864" integrity sha512-AjEo5LXk4Yf0SaXSc3y4i1t+wxY552O7WrVJPtnC6H7nUsSrygg/ODCG1RSKelskOq6b5p/LyXnsTkmCFXyjDQ== -"@verdaccio/types@4.1.3": - version "4.1.3" - resolved "https://registry.npmjs.org/@verdaccio/types/-/types-4.1.3.tgz#72881020b5f56865b32c94114fa66e9bf627f0f7" - integrity sha512-DjTlLqrtaLb9ykRYAawRflYVgUyRn1A204xEC39ucaF06kZJbNu0Awm+kBhHsM9CsgM47r3z65vRJDSJNhkzjQ== +"@verdaccio/types@4.1.4": + version "4.1.4" + resolved "https://registry.npmjs.org/@verdaccio/types/-/types-4.1.4.tgz#6144410b9fd63d916aa279378a4946c701a82586" + integrity sha512-0kNIQvMakoHIk1dpgnXVgQ5qwxJGTtMpJkLZKiN5WpLi5yuQtjc+kD/0EWDV4164pKg1KUU6YFLpbcXWxR8zvQ== "@webassemblyjs/ast@1.7.8": version "1.7.8"