Skip to content

Commit

Permalink
profile: update profile to support new npm-profile API (#131)
Browse files Browse the repository at this point in the history
PR-URL: #131
Credit: @zkat
Reviewed-By: @aeschright
  • Loading branch information
zkat authored Dec 21, 2018
1 parent 2401b75 commit a22e6f5
Showing 1 changed file with 65 additions and 60 deletions.
125 changes: 65 additions & 60 deletions lib/profile.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
'use strict'
const profile = require('libnpm/profile')
const npm = require('./npm.js')

const BB = require('bluebird')

const ansistyles = require('ansistyles')
const figgyPudding = require('figgy-pudding')
const inspect = require('util').inspect
const log = require('npmlog')
const npm = require('./npm.js')
const npmConfig = require('./config/figgy-config.js')
const otplease = require('./utils/otplease.js')
const output = require('./utils/output.js')
const profile = require('libnpm/profile')
const pulseTillDone = require('./utils/pulse-till-done.js')
const qrcodeTerminal = require('qrcode-terminal')
const queryString = require('query-string')
const qw = require('qw')
const Table = require('cli-table3')
const ansistyles = require('ansistyles')
const Bluebird = require('bluebird')
const readUserInfo = require('./utils/read-user-info.js')
const qrcodeTerminal = require('qrcode-terminal')
const Table = require('cli-table3')
const url = require('url')
const queryString = require('query-string')
const pulseTillDone = require('./utils/pulse-till-done.js')
const inspect = require('util').inspect

module.exports = profileCmd

Expand Down Expand Up @@ -48,6 +53,13 @@ function withCb (prom, cb) {
prom.then((value) => cb(null, value), cb)
}

const ProfileOpts = figgyPudding({
json: {},
otp: {},
parseable: {},
registry: {}
})

function profileCmd (args, cb) {
if (args.length === 0) return cb(new Error(profileCmd.usage))
log.gauge.show('profile')
Expand Down Expand Up @@ -75,36 +87,13 @@ function profileCmd (args, cb) {
}
}

function config () {
const conf = {
json: npm.config.get('json'),
parseable: npm.config.get('parseable'),
registry: npm.config.get('registry'),
otp: npm.config.get('otp')
}
const creds = npm.config.getCredentialsByURI(conf.registry)
if (creds.token) {
conf.auth = {token: creds.token}
} else if (creds.username) {
conf.auth = {basic: {username: creds.username, password: creds.password}}
} else if (creds.auth) {
const auth = Buffer.from(creds.auth, 'base64').toString().split(':', 2)
conf.auth = {basic: {username: auth[0], password: auth[1]}}
} else {
conf.auth = {}
}

if (conf.otp) conf.auth.otp = conf.otp
return conf
}

const knownProfileKeys = qw`
name email ${'two-factor auth'} fullname homepage
freenode twitter github created updated`

function get (args) {
const tfa = 'two-factor auth'
const conf = config()
const conf = ProfileOpts(npmConfig())
return pulseTillDone.withPromise(profile.get(conf)).then((info) => {
if (!info.cidr_whitelist) delete info.cidr_whitelist
if (conf.json) {
Expand Down Expand Up @@ -150,7 +139,7 @@ const writableProfileKeys = qw`
email password fullname homepage freenode twitter github`

function set (args) {
const conf = config()
let conf = ProfileOpts(npmConfig())
const prop = (args[0] || '').toLowerCase().trim()
let value = args.length > 1 ? args.slice(1).join(' ') : null
if (prop !== 'password' && value === null) {
Expand All @@ -164,7 +153,7 @@ function set (args) {
if (writableProfileKeys.indexOf(prop) === -1) {
return Promise.reject(Error(`"${prop}" is not a property we can set. Valid properties are: ` + writableProfileKeys.join(', ')))
}
return Bluebird.try(() => {
return BB.try(() => {
if (prop === 'password') {
return readUserInfo.password('Current password: ').then((current) => {
return readPasswords().then((newpassword) => {
Expand Down Expand Up @@ -193,23 +182,18 @@ function set (args) {
const newUser = {}
writableProfileKeys.forEach((k) => { newUser[k] = user[k] })
newUser[prop] = value
return profile.set(newUser, conf).catch((err) => {
if (err.code !== 'EOTP') throw err
return readUserInfo.otp().then((otp) => {
conf.auth.otp = otp
return profile.set(newUser, conf)
return otplease(conf, conf => profile.set(newUser, conf))
.then((result) => {
if (conf.json) {
output(JSON.stringify({[prop]: result[prop]}, null, 2))
} else if (conf.parseable) {
output(prop + '\t' + result[prop])
} else if (result[prop] != null) {
output('Set', prop, 'to', result[prop])
} else {
output('Set', prop)
}
})
}).then((result) => {
if (conf.json) {
output(JSON.stringify({[prop]: result[prop]}, null, 2))
} else if (conf.parseable) {
output(prop + '\t' + result[prop])
} else if (result[prop] != null) {
output('Set', prop, 'to', result[prop])
} else {
output('Set', prop)
}
})
}))
})
}
Expand All @@ -225,7 +209,7 @@ function enable2fa (args) {
' auth-only - Require two-factor authentication only when logging in\n' +
' auth-and-writes - Require two-factor authentication when logging in AND when publishing'))
}
const conf = config()
const conf = ProfileOpts(npmConfig())
if (conf.json || conf.parseable) {
return Promise.reject(new Error(
'Enabling two-factor authentication is an interactive operation and ' +
Expand All @@ -238,15 +222,18 @@ function enable2fa (args) {
}
}

return Bluebird.try(() => {
return BB.try(() => {
// if they're using legacy auth currently then we have to update them to a
// bearer token before continuing.
if (conf.auth.basic) {
const auth = getAuth(conf)
if (auth.basic) {
log.info('profile', 'Updating authentication to bearer token')
return profile.login(conf.auth.basic.username, conf.auth.basic.password, conf).then((result) => {
return profile.createToken(
auth.basic.password, false, [], conf
).then((result) => {
if (!result.token) throw new Error('Your registry ' + conf.registry + 'does not seem to support bearer tokens. Bearer tokens are required for two-factor authentication')
npm.config.setCredentialsByURI(conf.registry, {token: result.token})
return Bluebird.fromNode((cb) => npm.config.save('user', cb))
return BB.fromNode((cb) => npm.config.save('user', cb))
})
}
}).then(() => {
Expand Down Expand Up @@ -295,18 +282,36 @@ function enable2fa (args) {
})
}

function getAuth (conf) {
const creds = npm.config.getCredentialsByURI(conf.registry)
let auth
if (creds.token) {
auth = {token: creds.token}
} else if (creds.username) {
auth = {basic: {username: creds.username, password: creds.password}}
} else if (creds.auth) {
const basic = Buffer.from(creds.auth, 'base64').toString().split(':', 2)
auth = {basic: {username: basic[0], password: basic[1]}}
} else {
auth = {}
}

if (conf.otp) auth.otp = conf.otp
return auth
}

function disable2fa (args) {
const conf = config()
let conf = ProfileOpts(npmConfig())
return pulseTillDone.withPromise(profile.get(conf)).then((info) => {
if (!info.tfa || info.tfa.pending) {
output('Two factor authentication not enabled.')
return
}
return readUserInfo.password().then((password) => {
return Bluebird.try(() => {
if (conf.auth.otp) return
return BB.try(() => {
if (conf.otp) return
return readUserInfo.otp('Enter one-time password from your authenticator: ').then((otp) => {
conf.auth.otp = otp
conf = conf.concat({otp})
})
}).then(() => {
log.info('profile', 'disabling tfa')
Expand Down

0 comments on commit a22e6f5

Please sign in to comment.