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

npm-profile, npm-registry-fetch, emit input.start #7457

Merged
merged 4 commits into from
May 2, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/commands/access.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const npa = require('npm-package-arg')
const { output } = require('proc-log')
const pkgJson = require('@npmcli/package-json')
const localeCompare = require('@isaacs/string-locale-compare')('en')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const getIdentity = require('../utils/get-identity.js')
const BaseCommand = require('../base-cmd.js')

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/deprecate.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const fetch = require('npm-registry-fetch')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const npa = require('npm-package-arg')
const semver = require('semver')
const getIdentity = require('../utils/get-identity.js')
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/dist-tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const npa = require('npm-package-arg')
const regFetch = require('npm-registry-fetch')
const semver = require('semver')
const { log, output } = require('proc-log')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const pkgJson = require('@npmcli/package-json')
const BaseCommand = require('../base-cmd.js')

Expand Down
3 changes: 1 addition & 2 deletions lib/commands/fund.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const { output } = require('proc-log')
const npa = require('npm-package-arg')
const { depth } = require('treeverse')
const { readTree: getFundingInfo, normalizeFunding, isValidFunding } = require('libnpmfund')

const openUrl = require('../utils/open-url.js')
const { openUrl } = require('../utils/open-url.js')
const ArboristWorkspaceCmd = require('../arborist-cmd.js')

const getPrintableName = ({ name, version }) => {
Expand Down
10 changes: 6 additions & 4 deletions lib/commands/help.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const spawn = require('@npmcli/promise-spawn')
const path = require('path')
const openUrl = require('../utils/open-url.js')
const { openUrl } = require('../utils/open-url.js')
const { glob } = require('glob')
const { output } = require('proc-log')
const { output, input } = require('proc-log')
const localeCompare = require('@isaacs/string-locale-compare')('en')
const { deref } = require('../utils/cmd-list.js')
const BaseCommand = require('../base-cmd.js')
Expand Down Expand Up @@ -95,13 +95,15 @@ class Help extends BaseCommand {
args = ['emacsclient', ['-e', `(woman-find-file '${man}')`]]
}

return spawn(...args, { stdio: 'inherit' }).catch(err => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm was not using the return data from promise-spawn here so this is ok

https://github.com/npm/promise-spawn/blob/0aaf6f0f37e5b468277c8a4d8200b5ab18a4b387/lib/index.js#L27-L33

try {
await input.start(() => spawn(...args, { stdio: 'inherit' }))
} catch (err) {
if (err.code) {
throw new Error(`help process exited with code: ${err.code}`)
} else {
throw err
}
})
}
}

// Returns the path to the html version of the man page
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/hook.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const hookApi = require('libnpmhook')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const relativeDate = require('tiny-relative-date')
const { output } = require('proc-log')
const BaseCommand = require('../base-cmd.js')
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/org.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const liborg = require('libnpmorg')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const BaseCommand = require('../base-cmd.js')
const { output } = require('proc-log')

Expand Down
2 changes: 1 addition & 1 deletion lib/commands/owner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const npa = require('npm-package-arg')
const npmFetch = require('npm-registry-fetch')
const pacote = require('pacote')
const { log, output } = require('proc-log')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const pkgJson = require('@npmcli/package-json')
const BaseCommand = require('../base-cmd.js')
const { redact } = require('@npmcli/redact')
Expand Down
24 changes: 12 additions & 12 deletions lib/commands/profile.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { inspect } = require('util')
const { URL } = require('url')
const { log, output } = require('proc-log')
const npmProfile = require('npm-profile')
const { get, set, createToken } = require('npm-profile')
const qrcodeTerminal = require('qrcode-terminal')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const readUserInfo = require('../utils/read-user-info.js')
const BaseCommand = require('../base-cmd.js')

Expand Down Expand Up @@ -101,7 +101,7 @@ class Profile extends BaseCommand {

async get (args) {
const tfa = 'two-factor auth'
const info = await npmProfile.get({ ...this.npm.flatOptions })
const info = await get({ ...this.npm.flatOptions })

if (!info.cidr_whitelist) {
delete info.cidr_whitelist
Expand Down Expand Up @@ -199,7 +199,7 @@ class Profile extends BaseCommand {
}

// FIXME: Work around to not clear everything other than what we're setting
const user = await npmProfile.get(conf)
const user = await get(conf)
const newUser = {}

for (const key of writableProfileKeys) {
Expand All @@ -208,7 +208,7 @@ class Profile extends BaseCommand {

newUser[prop] = value

const result = await otplease(this.npm, conf, c => npmProfile.set(newUser, c))
const result = await otplease(this.npm, conf, c => set(newUser, c))

if (this.npm.config.get('json')) {
output.standard(JSON.stringify({ [prop]: result[prop] }, null, 2))
Expand Down Expand Up @@ -273,7 +273,7 @@ class Profile extends BaseCommand {

if (auth.basic) {
log.info('profile', 'Updating authentication to bearer token')
const result = await npmProfile.createToken(
const result = await createToken(
auth.basic.password, false, [], { ...this.npm.flatOptions }
)

Expand All @@ -297,12 +297,12 @@ class Profile extends BaseCommand {
info.tfa.password = password

log.info('profile', 'Determine if tfa is pending')
const userInfo = await npmProfile.get({ ...this.npm.flatOptions })
const userInfo = await get({ ...this.npm.flatOptions })

const conf = { ...this.npm.flatOptions }
if (userInfo && userInfo.tfa && userInfo.tfa.pending) {
log.info('profile', 'Resetting two-factor authentication')
await npmProfile.set({ tfa: { password, mode: 'disable' } }, conf)
await set({ tfa: { password, mode: 'disable' } }, conf)
} else if (userInfo && userInfo.tfa) {
if (!conf.otp) {
conf.otp = await readUserInfo.otp(
Expand All @@ -312,7 +312,7 @@ class Profile extends BaseCommand {
}

log.info('profile', 'Setting two-factor authentication to ' + mode)
const challenge = await npmProfile.set(info, conf)
const challenge = await set(info, conf)

if (challenge.tfa === null) {
output.standard('Two factor authentication mode changed to: ' + mode)
Expand Down Expand Up @@ -341,7 +341,7 @@ class Profile extends BaseCommand {

log.info('profile', 'Finalizing two-factor authentication')

const result = await npmProfile.set({ tfa: [interactiveOTP] }, conf)
const result = await set({ tfa: [interactiveOTP] }, conf)

output.standard(
'2FA successfully enabled. Below are your recovery codes, ' +
Expand All @@ -359,7 +359,7 @@ class Profile extends BaseCommand {

async disable2fa () {
const conf = { ...this.npm.flatOptions }
const info = await npmProfile.get(conf)
const info = await get(conf)

if (!info.tfa || info.tfa.pending) {
output.standard('Two factor authentication not enabled.')
Expand All @@ -375,7 +375,7 @@ class Profile extends BaseCommand {

log.info('profile', 'disabling tfa')

await npmProfile.set({ tfa: { password: password, mode: 'disable' } }, conf)
await set({ tfa: { password: password, mode: 'disable' } }, conf)

if (this.npm.config.get('json')) {
output.standard(JSON.stringify({ tfa: false }, null, 2))
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const pacote = require('pacote')
const npa = require('npm-package-arg')
const npmFetch = require('npm-registry-fetch')
const { redactLog: replaceInfo } = require('@npmcli/redact')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const { getContents, logTar } = require('../utils/tar.js')
// for historical reasons, publishConfig in package.json can contain ANY config
// keys that npm supports in .npmrc files and elsewhere. We *may* want to
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/team.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const columns = require('cli-columns')
const libteam = require('libnpmteam')
const { output } = require('proc-log')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')

const BaseCommand = require('../base-cmd.js')
class Team extends BaseCommand {
Expand Down
12 changes: 6 additions & 6 deletions lib/commands/token.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { log, output } = require('proc-log')
const profile = require('npm-profile')
const otplease = require('../utils/otplease.js')
const { listTokens, createToken, removeToken } = require('npm-profile')
const { otplease } = require('../utils/auth.js')
const readUserInfo = require('../utils/read-user-info.js')
const BaseCommand = require('../base-cmd.js')

Expand Down Expand Up @@ -48,7 +48,7 @@ class Token extends BaseCommand {
const json = this.npm.config.get('json')
const parseable = this.npm.config.get('parseable')
log.info('token', 'getting list')
const tokens = await profile.listTokens(this.npm.flatOptions)
const tokens = await listTokens(this.npm.flatOptions)
if (json) {
output.standard(JSON.stringify(tokens, null, 2))
return
Expand Down Expand Up @@ -92,7 +92,7 @@ class Token extends BaseCommand {
const toRemove = []
const opts = { ...this.npm.flatOptions }
log.info('token', `removing ${toRemove.length} tokens`)
const tokens = await profile.listTokens(opts)
const tokens = await listTokens(opts)
args.forEach(id => {
const matches = tokens.filter(token => token.key.indexOf(id) === 0)
if (matches.length === 1) {
Expand All @@ -113,7 +113,7 @@ class Token extends BaseCommand {
})
await Promise.all(
toRemove.map(key => {
return otplease(this.npm, opts, c => profile.removeToken(key, c))
return otplease(this.npm, opts, c => removeToken(key, c))
})
)
if (json) {
Expand All @@ -137,7 +137,7 @@ class Token extends BaseCommand {
const result = await otplease(
this.npm,
{ ...this.npm.flatOptions },
c => profile.createToken(password, readonly, validCIDR, c)
c => createToken(password, readonly, validCIDR, c)
)
delete result.key
delete result.updated
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/unpublish.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { output, log } = require('proc-log')
const pkgJson = require('@npmcli/package-json')
const { flatten } = require('@npmcli/config/lib/definitions')
const getIdentity = require('../utils/get-identity.js')
const otplease = require('../utils/otplease.js')
const { otplease } = require('../utils/auth.js')
const BaseCommand = require('../base-cmd.js')

const LAST_REMAINING_VERSION_ERROR = 'Refusing to delete the last version of the package. ' +
Expand Down
2 changes: 1 addition & 1 deletion lib/package-url-cmd.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const pacote = require('pacote')
const openUrl = require('./utils/open-url.js')
const { openUrl } = require('./utils/open-url.js')
const { log } = require('proc-log')
const BaseCommand = require('./base-cmd.js')

Expand Down
63 changes: 36 additions & 27 deletions lib/utils/auth.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
const profile = require('npm-profile')
const { webAuthOpener, adduserWeb, loginWeb, loginCouch, adduserCouch } = require('npm-profile')
const { log } = require('proc-log')
const openUrlPrompt = require('../utils/open-url-prompt.js')
const { createOpener } = require('../utils/open-url.js')
const read = require('../utils/read-user-info.js')
const otplease = require('../utils/otplease.js')

const otplease = async (npm, opts, fn) => {
try {
return await fn(opts)
} catch (err) {
if (!process.stdin.isTTY || !process.stdout.isTTY) {
throw err
}

// web otp
if (err.code === 'EOTP' && err.body?.authUrl && err.body?.doneUrl) {
const otp = await webAuthOpener(
createOpener(npm, 'Authenticate your account at'),
err.body.authUrl,
err.body.doneUrl,
opts
)
return await fn({ ...opts, otp })
}

// classic otp
if (err.code === 'EOTP' || (err.code === 'E401' && /one-time pass/.test(err.body))) {
const otp = await read.otp('This operation requires a one-time password.\nEnter OTP:')
return await fn({ ...opts, otp })
}

throw err
}
}

const adduser = async (npm, { creds, ...opts }) => {
const authType = npm.config.get('auth-type')
let res
if (authType === 'web') {
try {
res = await profile.adduserWeb((url, emitter) => {
openUrlPrompt(
npm,
url,
'Create your account at',
'Press ENTER to open in the browser...',
emitter
)
}, opts)
res = await adduserWeb(createOpener(npm, 'Create your account at'), opts)
} catch (err) {
if (err.code === 'ENYI') {
log.verbose('web add user not supported, trying couch')
Expand All @@ -35,9 +55,7 @@ const adduser = async (npm, { creds, ...opts }) => {
// npm registry quirk: If you "add" an existing user with their current
// password, it's effectively a login, and if that account has otp you'll
// be prompted for it.
res = await otplease(npm, opts, (reqOpts) =>
profile.adduserCouch(username, email, password, reqOpts)
)
res = await otplease(npm, opts, (reqOpts) => adduserCouch(username, email, password, reqOpts))
}

// We don't know the username if it was a web login, all we can reliably log is scope and registry
Expand All @@ -56,15 +74,7 @@ const login = async (npm, { creds, ...opts }) => {
let res
if (authType === 'web') {
try {
res = await profile.loginWeb((url, emitter) => {
openUrlPrompt(
npm,
url,
'Login at',
'Press ENTER to open in the browser...',
emitter
)
}, opts)
res = await loginWeb(createOpener(npm, 'Login at'), opts)
} catch (err) {
if (err.code === 'ENYI') {
log.verbose('web login not supported, trying couch')
Expand All @@ -78,9 +88,7 @@ const login = async (npm, { creds, ...opts }) => {
if (!res) {
const username = await read.username('Username:', creds.username)
const password = await read.password('Password:', creds.password)
res = await otplease(npm, opts, (reqOpts) =>
profile.loginCouch(username, password, reqOpts)
)
res = await otplease(npm, opts, (reqOpts) => loginCouch(username, password, reqOpts))
}

// We don't know the username if it was a web login, all we can reliably log is scope and registry
Expand All @@ -97,4 +105,5 @@ const login = async (npm, { creds, ...opts }) => {
module.exports = {
adduser,
login,
otplease,
}
Loading
Loading