Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auth breaking changes #5696

Merged
merged 3 commits into from Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/base-command.js
Expand Up @@ -11,6 +11,10 @@ class BaseCommand {
constructor (npm) {
this.wrapWidth = 80
this.npm = npm

if (!this.skipConfigValidation) {
this.npm.config.validate()
}
}

get name () {
Expand All @@ -25,6 +29,10 @@ class BaseCommand {
return this.constructor.ignoreImplicitWorkspace
}

get skipConfigValidation () {
return this.constructor.skipConfigValidation
}

get usage () {
const usage = [
`${this.constructor.description}`,
Expand Down
52 changes: 51 additions & 1 deletion lib/commands/config.js
Expand Up @@ -51,6 +51,7 @@ class Config extends BaseCommand {
'delete <key> [<key> ...]',
'list [--json]',
'edit',
'fix',
]

static params = [
Expand All @@ -63,14 +64,16 @@ class Config extends BaseCommand {

static ignoreImplicitWorkspace = false

static skipConfigValidation = true

async completion (opts) {
const argv = opts.conf.argv.remain
if (argv[1] !== 'config') {
argv.unshift('config')
}

if (argv.length === 2) {
const cmds = ['get', 'set', 'delete', 'ls', 'rm', 'edit']
const cmds = ['get', 'set', 'delete', 'ls', 'rm', 'edit', 'fix']
if (opts.partialWord !== 'l') {
cmds.push('list')
}
Expand All @@ -95,6 +98,7 @@ class Config extends BaseCommand {
case 'edit':
case 'list':
case 'ls':
case 'fix':
default:
return []
}
Expand Down Expand Up @@ -127,6 +131,9 @@ class Config extends BaseCommand {
case 'edit':
await this.edit()
break
case 'fix':
await this.fix()
break
default:
throw this.usageError()
}
Expand Down Expand Up @@ -238,6 +245,49 @@ ${defData}
})
}

async fix () {
let problems

try {
this.npm.config.validate()
return // if validate doesn't throw we have nothing to do
} catch (err) {
// coverage skipped because we don't need to test rethrowing errors
// istanbul ignore next
if (err.code !== 'ERR_INVALID_AUTH') {
throw err
}

problems = err.problems
}

if (!this.npm.config.isDefault('location')) {
problems = problems.filter((problem) => {
return problem.where === this.npm.config.get('location')
})
}

this.npm.config.repair(problems)
const locations = []

this.npm.output('The following configuration problems have been repaired:\n')
const summary = problems.map(({ action, from, to, key, where }) => {
// coverage disabled for else branch because it is intentionally omitted
// istanbul ignore else
if (action === 'rename') {
// we keep track of which configs were modified here so we know what to save later
locations.push(where)
return `~ \`${from}\` renamed to \`${to}\` in ${where} config`
} else if (action === 'delete') {
locations.push(where)
return `- \`${key}\` deleted from ${where} config`
}
}).join('\n')
this.npm.output(summary)

return await Promise.all(locations.map((location) => this.npm.config.save(location)))
}

async list () {
const msg = []
// long does not have a flattener
Expand Down
22 changes: 22 additions & 0 deletions node_modules/@npmcli/config/lib/errors.js
@@ -0,0 +1,22 @@
'use strict'

class ErrInvalidAuth extends Error {
constructor (problems) {
let message = 'Invalid auth configuration found: '
message += problems.map((problem) => {
if (problem.action === 'delete') {
return `\`${problem.key}\` is not allowed in ${problem.where} config`
} else if (problem.action === 'rename') {
return `\`${problem.from}\` must be renamed to \`${problem.to}\` in ${problem.where} config`
}
}).join(', ')
message += '\nPlease run `npm config fix` to repair your configuration.`'
super(message)
this.code = 'ERR_INVALID_AUTH'
this.problems = problems
}
}

module.exports = {
ErrInvalidAuth,
}