xref: /third_party/node/deps/npm/lib/utils/otplease.js (revision 1cb0ef41)
1const log = require('./log-shim')
2async function otplease (npm, opts, fn) {
3  try {
4    return await fn(opts)
5  } catch (err) {
6    if (!process.stdin.isTTY || !process.stdout.isTTY) {
7      throw err
8    }
9
10    if (isWebOTP(err)) {
11      log.disableProgress()
12      const webAuth = require('./web-auth')
13      const openUrlPrompt = require('./open-url-prompt')
14
15      const openerPromise = (url, emitter) =>
16        openUrlPrompt(
17          npm,
18          url,
19          'Authenticate your account at',
20          'Press ENTER to open in the browser...',
21          emitter
22        )
23      const otp = await webAuth(openerPromise, err.body.authUrl, err.body.doneUrl, opts)
24      return await fn({ ...opts, otp })
25    }
26
27    if (isClassicOTP(err)) {
28      const readUserInfo = require('./read-user-info.js')
29      const otp = await readUserInfo.otp('This operation requires a one-time password.\nEnter OTP:')
30      return await fn({ ...opts, otp })
31    }
32
33    throw err
34  }
35}
36
37function isWebOTP (err) {
38  if (err.code === 'EOTP' && err.body) {
39    return err.body.authUrl && err.body.doneUrl
40  }
41  return false
42}
43
44function isClassicOTP (err) {
45  return err.code === 'EOTP' || (err.code === 'E401' && /one-time pass/.test(err.body))
46}
47
48module.exports = otplease
49