All files / lib/auth legacy.js

100% Statements 47/47
100% Branches 23/23
100% Functions 7/7
100% Lines 45/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101    1x 1x   1x 1x     2x 2x     1x 1x   1x 1x 1x   1x     1x     11x 2x       2x             11x     3x 3x             2x 1x   1x     2x     11x 11x   6x         6x 1x 5x 2x     3x       8x 8x 6x   2x 2x 2x 2x     8x 8x 8x 8x   8x   8x           1x  
'use strict'
 
const log = require('npmlog')
const profile = require('npm-profile')
 
const openUrl = require('../utils/open-url.js')
const read = require('../utils/read-user-info.js')
 
// TODO: refactor lib/utils/open-url and its usages
const openerPromise = (url) => new Promise((resolve, reject) => {
  openUrl(url, 'to complete your login please visit', (er) => er ? reject(er) : resolve())
})
 
const loginPrompter = async (creds) => {
  const opts = { log: log }
 
  creds.username = await read.username('Username:', creds.username, opts)
  creds.password = await read.password('Password:', creds.password)
  creds.email = await read.email('Email: (this IS public) ', creds.email, opts)
 
  return creds
}
 
const login = async (opts) => {
  let res
 
  const requestOTP = async () => {
    const otp = await read.otp(
      'Enter one-time password from your authenticator app: '
    )
 
    return profile.loginCouch(
      opts.creds.username,
      opts.creds.password,
      { ...opts, otp }
    )
  }
 
  const addNewUser = async () => {
    let newUser
 
    try {
      newUser = await profile.adduserCouch(
        opts.creds.username,
        opts.creds.email,
        opts.creds.password,
        opts
      )
    } catch (err) {
      if (err.code === 'EOTP')
        newUser = await requestOTP()
      else
        throw err
    }
 
    return newUser
  }
 
  try {
    res = await profile.login(openerPromise, loginPrompter, opts)
  } catch (err) {
    const needsMoreInfo = !(opts &&
      opts.creds &&
      opts.creds.username &&
      opts.creds.password &&
      opts.creds.email)
    if (err.code === 'EOTP')
      res = await requestOTP()
    else if (needsMoreInfo)
      throw err
    else {
      // TODO: maybe this needs to check for err.code === 'E400' instead?
      res = await addNewUser()
    }
  }
 
  const newCreds = {}
  if (res && res.token)
    newCreds.token = res.token
  else {
    newCreds.username = opts.creds.username
    newCreds.password = opts.creds.password
    newCreds.email = opts.creds.email
    newCreds.alwaysAuth = opts.creds.alwaysAuth
  }
 
  const usermsg = opts.creds.username ? ` user ${opts.creds.username}` : ''
  const scopeMessage = opts.scope ? ` to scope ${opts.scope}` : ''
  const userout = opts.creds.username ? ` as ${opts.creds.username}` : ''
  const message = `Logged in${userout}${scopeMessage} on ${opts.registry}.`
 
  log.info('login', `Authorized${usermsg}`)
 
  return {
    message,
    newCreds,
  }
}
 
module.exports = login