Skip to content

Commit 53f75a4

Browse files
authored
fix: gracefully fallback from auth-type=web (#6158)
Originally `auth-type=web` would gracefully fallback to `auth-type=legacy` if a registry had not yet implemented web. This brings back that behavior.
1 parent 8800138 commit 53f75a4

File tree

3 files changed

+126
-20
lines changed

3 files changed

+126
-20
lines changed

lib/utils/auth.js

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,27 @@ const adduser = async (npm, { creds, ...opts }) => {
88
const authType = npm.config.get('auth-type')
99
let res
1010
if (authType === 'web') {
11-
res = await profile.adduserWeb((url, emitter) => {
12-
openUrlPrompt(
13-
npm,
14-
url,
15-
'Create your account at',
16-
'Press ENTER to open in the browser...',
17-
emitter
18-
)
19-
}, opts)
20-
} else {
11+
try {
12+
res = await profile.adduserWeb((url, emitter) => {
13+
openUrlPrompt(
14+
npm,
15+
url,
16+
'Create your account at',
17+
'Press ENTER to open in the browser...',
18+
emitter
19+
)
20+
}, opts)
21+
} catch (err) {
22+
if (err.code === 'ENYI') {
23+
log.verbose('web add user not supported, trying couch')
24+
} else {
25+
throw err
26+
}
27+
}
28+
}
29+
30+
// auth type !== web or ENYI error w/ web adduser
31+
if (!res) {
2132
const username = await read.username('Username:', creds.username)
2233
const password = await read.password('Password:', creds.password)
2334
const email = await read.email('Email: (this IS public) ', creds.email)
@@ -44,16 +55,27 @@ const login = async (npm, { creds, ...opts }) => {
4455
const authType = npm.config.get('auth-type')
4556
let res
4657
if (authType === 'web') {
47-
res = await profile.loginWeb((url, emitter) => {
48-
openUrlPrompt(
49-
npm,
50-
url,
51-
'Login at',
52-
'Press ENTER to open in the browser...',
53-
emitter
54-
)
55-
}, opts)
56-
} else {
58+
try {
59+
res = await profile.loginWeb((url, emitter) => {
60+
openUrlPrompt(
61+
npm,
62+
url,
63+
'Login at',
64+
'Press ENTER to open in the browser...',
65+
emitter
66+
)
67+
}, opts)
68+
} catch (err) {
69+
if (err.code === 'ENYI') {
70+
log.verbose('web login not supported, trying couch')
71+
} else {
72+
throw err
73+
}
74+
}
75+
}
76+
77+
// auth type !== web or ENYI error w/ web login
78+
if (!res) {
5779
const username = await read.username('Username:', creds.username)
5880
const password = await read.password('Password:', creds.password)
5981
res = await otplease(npm, opts, (reqOpts) =>

test/lib/commands/adduser.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,5 +174,49 @@ t.test('web', t => {
174174
'//registry.npmjs.org/:_authToken': 'npm_test-token',
175175
})
176176
})
177+
178+
t.test('server error', async t => {
179+
const { npm } = await loadMockNpm(t, {
180+
config: { 'auth-type': 'web' },
181+
})
182+
const registry = new MockRegistry({
183+
tap: t,
184+
registry: npm.config.get('registry'),
185+
})
186+
registry.nock.post(registry.fullPath('/-/v1/login'))
187+
.reply(503, {})
188+
await t.rejects(
189+
npm.exec('adduser', []),
190+
{ message: /503/ }
191+
)
192+
})
193+
194+
t.test('fallback', async t => {
195+
const stdin = new stream.PassThrough()
196+
stdin.write('test-user\n')
197+
stdin.write('test-password\n')
198+
stdin.write('test-email@npmjs.org\n')
199+
mockGlobals(t, {
200+
'process.stdin': stdin,
201+
'process.stdout': new stream.PassThrough(), // to quiet readline
202+
}, { replace: true })
203+
const { npm } = await loadMockNpm(t, {
204+
config: { 'auth-type': 'web' },
205+
})
206+
const registry = new MockRegistry({
207+
tap: t,
208+
registry: npm.config.get('registry'),
209+
})
210+
registry.nock.post(registry.fullPath('/-/v1/login'))
211+
.reply(404, {})
212+
registry.couchadduser({
213+
username: 'test-user',
214+
password: 'test-password',
215+
email: 'test-email@npmjs.org',
216+
token: 'npm_test-token',
217+
})
218+
await npm.exec('adduser', [])
219+
t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
220+
})
177221
t.end()
178222
})

test/lib/commands/login.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,45 @@ t.test('web', t => {
139139
'//registry.npmjs.org/:_authToken': 'npm_test-token',
140140
})
141141
})
142+
t.test('server error', async t => {
143+
const { npm } = await loadMockNpm(t, {
144+
config: { 'auth-type': 'web' },
145+
})
146+
const registry = new MockRegistry({
147+
tap: t,
148+
registry: npm.config.get('registry'),
149+
})
150+
registry.nock.post(registry.fullPath('/-/v1/login'))
151+
.reply(503, {})
152+
await t.rejects(
153+
npm.exec('login', []),
154+
{ message: /503/ }
155+
)
156+
})
157+
t.test('fallback', async t => {
158+
const stdin = new stream.PassThrough()
159+
stdin.write('test-user\n')
160+
stdin.write('test-password\n')
161+
mockGlobals(t, {
162+
'process.stdin': stdin,
163+
'process.stdout': new stream.PassThrough(), // to quiet readline
164+
}, { replace: true })
165+
const { npm } = await loadMockNpm(t, {
166+
config: { 'auth-type': 'web' },
167+
})
168+
const registry = new MockRegistry({
169+
tap: t,
170+
registry: npm.config.get('registry'),
171+
})
172+
registry.nock.post(registry.fullPath('/-/v1/login'))
173+
.reply(404, {})
174+
registry.couchlogin({
175+
username: 'test-user',
176+
password: 'test-password',
177+
token: 'npm_test-token',
178+
})
179+
await npm.exec('login', [])
180+
t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token')
181+
})
142182
t.end()
143183
})

0 commit comments

Comments
 (0)