From b61eac693df82c52b955e6c18ec4dcf4cedea8a3 Mon Sep 17 00:00:00 2001 From: isaacs Date: Fri, 23 Apr 2021 14:45:07 -0700 Subject: [PATCH] @npmcli/config@2.2.0 Partially fixes https://github.com/npm/cli/issues/3130 --- node_modules/@npmcli/config/lib/index.js | 92 ++++++++++++++---------- node_modules/@npmcli/config/package.json | 4 +- package-lock.json | 44 ++---------- package.json | 2 +- test/lib/adduser.js | 11 +-- 5 files changed, 69 insertions(+), 84 deletions(-) diff --git a/node_modules/@npmcli/config/lib/index.js b/node_modules/@npmcli/config/lib/index.js index 21a37ded48e7c..f947896f0ba34 100644 --- a/node_modules/@npmcli/config/lib/index.js +++ b/node_modules/@npmcli/config/lib/index.js @@ -197,11 +197,6 @@ class Config { throw new Error('call config.load() before setting values') if (!confTypes.has(where)) throw new Error('invalid config location param: ' + where) - if (key === '_auth') { - const { email } = this.getCredentialsByURI(this.get('registry')) - if (!email) - throw new Error('Cannot set _auth without first setting email') - } this[_checkDeprecated](key) const { data } = this.data.get(where) data[key] = val @@ -282,6 +277,14 @@ class Config { // symbols, as that module also does a bunch of get operations this[_loaded] = true + process.emit('time', 'config:load:credentials') + const reg = this.get('registry') + const creds = this.getCredentialsByURI(reg) + // ignore this error because a failed set will strip out anything that + // might be a security hazard, which was the intention. + try { this.setCredentialsByURI(reg, creds) } catch (_) {} + process.emit('timeEnd', 'config:load:credentials') + // set proper globalPrefix now that everything is loaded this.globalPrefix = this.get('prefix') @@ -588,14 +591,17 @@ class Config { const nerfed = nerfDart(uri) const def = nerfDart(this.get('registry')) if (def === nerfed) { + // do not delete email, that shouldn't be nerfed any more. + // just delete the nerfed copy, if one exists. this.delete(`-authtoken`, 'user') this.delete(`_authToken`, 'user') + this.delete(`_authtoken`, 'user') this.delete(`_auth`, 'user') this.delete(`_password`, 'user') this.delete(`username`, 'user') - this.delete(`email`, 'user') } this.delete(`${nerfed}:-authtoken`, 'user') + this.delete(`${nerfed}:_authtoken`, 'user') this.delete(`${nerfed}:_authToken`, 'user') this.delete(`${nerfed}:_auth`, 'user') this.delete(`${nerfed}:_password`, 'user') @@ -603,7 +609,7 @@ class Config { this.delete(`${nerfed}:email`, 'user') } - setCredentialsByURI (uri, { token, username, password, email, alwaysAuth }) { + setCredentialsByURI (uri, { token, username, password, email }) { const nerfed = nerfDart(uri) const def = nerfDart(this.get('registry')) @@ -611,41 +617,45 @@ class Config { // remove old style auth info not limited to a single registry this.delete('_password', 'user') this.delete('username', 'user') - this.delete('email', 'user') this.delete('_auth', 'user') this.delete('_authtoken', 'user') + this.delete('-authtoken', 'user') this.delete('_authToken', 'user') } - this.delete(`${nerfed}:-authtoken`) + // email used to be nerfed always. if we're using the default + // registry, de-nerf it. + if (nerfed === def) { + email = email || + this.get('email', 'user') || + this.get(`${nerfed}:email`, 'user') + if (email) + this.set('email', email, 'user') + } + + // field that hasn't been used as documented for a LONG time, + // and as of npm 7.10.0, isn't used at all. We just always + // send auth if we have it, only to the URIs under the nerf dart. + this.delete(`${nerfed}:always-auth`, 'user') + + this.delete(`${nerfed}:-authtoken`, 'user') + this.delete(`${nerfed}:_authtoken`, 'user') + this.delete(`${nerfed}:email`, 'user') if (token) { this.set(`${nerfed}:_authToken`, token, 'user') this.delete(`${nerfed}:_password`, 'user') this.delete(`${nerfed}:username`, 'user') - this.delete(`${nerfed}:email`, 'user') - this.delete(`${nerfed}:always-auth`, 'user') - } else if (username || password || email) { - if (username || password) { - if (!username) - throw new Error('must include username') - if (!password) - throw new Error('must include password') - } - if (!email) - throw new Error('must include email') + } else if (username || password) { + if (!username) + throw new Error('must include username') + if (!password) + throw new Error('must include password') this.delete(`${nerfed}:_authToken`, 'user') - if (username || password) { - this.set(`${nerfed}:username`, username, 'user') - // note: not encrypted, no idea why we bothered to do this, but oh well - // protects against shoulder-hacks if password is memorable, I guess? - const encoded = Buffer.from(password, 'utf8').toString('base64') - this.set(`${nerfed}:_password`, encoded, 'user') - } - this.set(`${nerfed}:email`, email, 'user') - if (alwaysAuth !== undefined) - this.set(`${nerfed}:always-auth`, alwaysAuth, 'user') - else - this.delete(`${nerfed}:always-auth`, 'user') + this.set(`${nerfed}:username`, username, 'user') + // note: not encrypted, no idea why we bothered to do this, but oh well + // protects against shoulder-hacks if password is memorable, I guess? + const encoded = Buffer.from(password, 'utf8').toString('base64') + this.set(`${nerfed}:_password`, encoded, 'user') } else { throw new Error('No credentials to set.') } @@ -656,18 +666,12 @@ class Config { const nerfed = nerfDart(uri) const creds = {} - // you can set always-auth for a single registry, or as a default - const alwaysAuthReg = this.get(`${nerfed}:always-auth`) - if (alwaysAuthReg !== undefined) - creds.alwaysAuth = !!alwaysAuthReg - else - creds.alwaysAuth = this.get('always-auth') - const email = this.get(`${nerfed}:email`) || this.get('email') if (email) creds.email = email const tokenReg = this.get(`${nerfed}:_authToken`) || + this.get(`${nerfed}:_authtoken`) || this.get(`${nerfed}:-authtoken`) || nerfed === nerfDart(this.get('registry')) && this.get('_authToken') @@ -686,6 +690,16 @@ class Config { return creds } + const authReg = this.get(`${nerfed}:_auth`) + if (authReg) { + const authDecode = Buffer.from(authReg, 'base64').toString('utf8') + const authSplit = authDecode.split(':') + creds.username = authSplit.shift() + creds.password = authSplit.join(':') + creds.auth = authReg + return creds + } + // at this point, we can only use the values if the URI is the // default registry. const defaultNerf = nerfDart(this.get('registry')) diff --git a/node_modules/@npmcli/config/package.json b/node_modules/@npmcli/config/package.json index 767718a9d61c7..f80669640ebd4 100644 --- a/node_modules/@npmcli/config/package.json +++ b/node_modules/@npmcli/config/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/config", - "version": "2.1.0", + "version": "2.2.0", "files": [ "lib" ], @@ -24,7 +24,7 @@ "coverage-map": "map.js" }, "devDependencies": { - "tap": "^14.10.8" + "tap": "^15.0.4" }, "dependencies": { "ini": "^2.0.0", diff --git a/package-lock.json b/package-lock.json index 1bc46772c11e1..3bf4c736e4b10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,7 +80,7 @@ "dependencies": { "@npmcli/arborist": "^2.4.0", "@npmcli/ci-detect": "^1.2.0", - "@npmcli/config": "^2.1.0", + "@npmcli/config": "^2.2.0", "@npmcli/run-script": "^1.8.5", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", @@ -756,9 +756,9 @@ "inBundle": true }, "node_modules/@npmcli/config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-2.1.0.tgz", - "integrity": "sha512-vYTUs6b1ORqWgWFrLkyscdhyhtB1YhbtEM2iaH5rM5Bv1/tWqZEpspGLh+Re6YuPRUmXulzkf3iWhu9ntz8cVw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-2.2.0.tgz", + "integrity": "sha512-y0V3F7RCWXy8kBOvKvKSRUNKRobLB6vL/UNchy/6+IUNIqu+UyrY3Z7jvj1ZA/AkYc/0WkCUtppCo+bPhMU8Aw==", "inBundle": true, "dependencies": { "ini": "^2.0.0", @@ -7868,14 +7868,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tap/node_modules/ansi-regex": { - "version": "3.0.0", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/tap/node_modules/ansi-styles": { "version": "3.2.1", "dev": true, @@ -9047,17 +9039,6 @@ "node": ">=8" } }, - "node_modules/tap/node_modules/strip-ansi": { - "version": "4.0.0", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/tap/node_modules/supports-color": { "version": "5.5.0", "dev": true, @@ -10884,9 +10865,9 @@ "integrity": "sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q==" }, "@npmcli/config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-2.1.0.tgz", - "integrity": "sha512-vYTUs6b1ORqWgWFrLkyscdhyhtB1YhbtEM2iaH5rM5Bv1/tWqZEpspGLh+Re6YuPRUmXulzkf3iWhu9ntz8cVw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-2.2.0.tgz", + "integrity": "sha512-y0V3F7RCWXy8kBOvKvKSRUNKRobLB6vL/UNchy/6+IUNIqu+UyrY3Z7jvj1ZA/AkYc/0WkCUtppCo+bPhMU8Aw==", "requires": { "ini": "^2.0.0", "mkdirp-infer-owner": "^2.0.0", @@ -16110,10 +16091,6 @@ "type-fest": "^0.21.3" } }, - "ansi-regex": { - "version": "3.0.0", - "extraneous": true - }, "ansi-styles": { "version": "3.2.1", "bundled": true, @@ -16894,13 +16871,6 @@ } } }, - "strip-ansi": { - "version": "4.0.0", - "extraneous": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, "supports-color": { "version": "5.5.0", "bundled": true, diff --git a/package.json b/package.json index dea9ab965a721..7ee440d911a95 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "dependencies": { "@npmcli/arborist": "^2.4.0", "@npmcli/ci-detect": "^1.2.0", - "@npmcli/config": "^2.1.0", + "@npmcli/config": "^2.2.0", "@npmcli/run-script": "^1.8.5", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", diff --git a/test/lib/adduser.js b/test/lib/adduser.js index 5ce61e12755dc..a66623e668282 100644 --- a/test/lib/adduser.js +++ b/test/lib/adduser.js @@ -25,7 +25,6 @@ const authDummy = (npm, options) => { username: 'u', password: 'p', email: 'u@npmjs.org', - alwaysAuth: false, }, }) } @@ -97,12 +96,15 @@ t.test('simple login', (t) => { _token: 'user', _password: 'user', username: 'user', - email: 'user', _auth: 'user', _authtoken: 'user', + '-authtoken': 'user', _authToken: 'user', - '//registry.npmjs.org/:-authtoken': undefined, + '//registry.npmjs.org/:-authtoken': 'user', '//registry.npmjs.org/:_authToken': 'user', + '//registry.npmjs.org/:_authtoken': 'user', + '//registry.npmjs.org/:always-auth': 'user', + '//registry.npmjs.org/:email': 'user', }, 'should delete token in user config' ) @@ -112,8 +114,7 @@ t.test('simple login', (t) => { { '//registry.npmjs.org/:_password': { value: 'cA==', where: 'user' }, '//registry.npmjs.org/:username': { value: 'u', where: 'user' }, - '//registry.npmjs.org/:email': { value: 'u@npmjs.org', where: 'user' }, - '//registry.npmjs.org/:always-auth': { value: false, where: 'user' }, + email: { value: 'u@npmjs.org', where: 'user' }, }, 'should set expected user configs' )