11'use strict'
2+
23const profile = require ( 'libnpm/profile' )
4+ const npmConfig = require ( './config/figgy-config.js' )
5+ const figgyPudding = require ( 'figgy-pudding' )
6+ const otplease = require ( './utils/otplease.js' )
37const npm = require ( './npm.js' )
48const log = require ( 'npmlog' )
59const output = require ( './utils/output.js' )
@@ -48,6 +52,13 @@ function withCb (prom, cb) {
4852 prom . then ( ( value ) => cb ( null , value ) , cb )
4953}
5054
55+ const ProfileOpts = figgyPudding ( {
56+ json : { } ,
57+ otp : { } ,
58+ parseable : { } ,
59+ registry : { }
60+ } )
61+
5162function profileCmd ( args , cb ) {
5263 if ( args . length === 0 ) return cb ( new Error ( profileCmd . usage ) )
5364 log . gauge . show ( 'profile' )
@@ -75,36 +86,13 @@ function profileCmd (args, cb) {
7586 }
7687}
7788
78- function config ( ) {
79- const conf = {
80- json : npm . config . get ( 'json' ) ,
81- parseable : npm . config . get ( 'parseable' ) ,
82- registry : npm . config . get ( 'registry' ) ,
83- otp : npm . config . get ( 'otp' )
84- }
85- const creds = npm . config . getCredentialsByURI ( conf . registry )
86- if ( creds . token ) {
87- conf . auth = { token : creds . token }
88- } else if ( creds . username ) {
89- conf . auth = { basic : { username : creds . username , password : creds . password } }
90- } else if ( creds . auth ) {
91- const auth = Buffer . from ( creds . auth , 'base64' ) . toString ( ) . split ( ':' , 2 )
92- conf . auth = { basic : { username : auth [ 0 ] , password : auth [ 1 ] } }
93- } else {
94- conf . auth = { }
95- }
96-
97- if ( conf . otp ) conf . auth . otp = conf . otp
98- return conf
99- }
100-
10189const knownProfileKeys = qw `
10290 name email ${ 'two-factor auth' } fullname homepage
10391 freenode twitter github created updated`
10492
10593function get ( args ) {
10694 const tfa = 'two-factor auth'
107- const conf = config ( )
95+ const conf = ProfileOpts ( npmConfig ( ) )
10896 return pulseTillDone . withPromise ( profile . get ( conf ) ) . then ( ( info ) => {
10997 if ( ! info . cidr_whitelist ) delete info . cidr_whitelist
11098 if ( conf . json ) {
@@ -150,7 +138,7 @@ const writableProfileKeys = qw`
150138 email password fullname homepage freenode twitter github`
151139
152140function set ( args ) {
153- const conf = config ( )
141+ let conf = ProfileOpts ( npmConfig ( ) )
154142 const prop = ( args [ 0 ] || '' ) . toLowerCase ( ) . trim ( )
155143 let value = args . length > 1 ? args . slice ( 1 ) . join ( ' ' ) : null
156144 if ( prop !== 'password' && value === null ) {
@@ -193,23 +181,18 @@ function set (args) {
193181 const newUser = { }
194182 writableProfileKeys . forEach ( ( k ) => { newUser [ k ] = user [ k ] } )
195183 newUser [ prop ] = value
196- return profile . set ( newUser , conf ) . catch ( ( err ) => {
197- if ( err . code !== 'EOTP' ) throw err
198- return readUserInfo . otp ( ) . then ( ( otp ) => {
199- conf . auth . otp = otp
200- return profile . set ( newUser , conf )
184+ return otplease ( conf , conf => profile . set ( newUser , conf ) )
185+ . then ( ( result ) => {
186+ if ( conf . json ) {
187+ output ( JSON . stringify ( { [ prop ] : result [ prop ] } , null , 2 ) )
188+ } else if ( conf . parseable ) {
189+ output ( prop + '\t' + result [ prop ] )
190+ } else if ( result [ prop ] != null ) {
191+ output ( 'Set' , prop , 'to' , result [ prop ] )
192+ } else {
193+ output ( 'Set' , prop )
194+ }
201195 } )
202- } ) . then ( ( result ) => {
203- if ( conf . json ) {
204- output ( JSON . stringify ( { [ prop ] : result [ prop ] } , null , 2 ) )
205- } else if ( conf . parseable ) {
206- output ( prop + '\t' + result [ prop ] )
207- } else if ( result [ prop ] != null ) {
208- output ( 'Set' , prop , 'to' , result [ prop ] )
209- } else {
210- output ( 'Set' , prop )
211- }
212- } )
213196 } ) )
214197 } )
215198}
@@ -225,7 +208,7 @@ function enable2fa (args) {
225208 ' auth-only - Require two-factor authentication only when logging in\n' +
226209 ' auth-and-writes - Require two-factor authentication when logging in AND when publishing' ) )
227210 }
228- const conf = config ( )
211+ const conf = ProfileOpts ( npmConfig ( ) )
229212 if ( conf . json || conf . parseable ) {
230213 return Promise . reject ( new Error (
231214 'Enabling two-factor authentication is an interactive operation and ' +
@@ -241,9 +224,12 @@ function enable2fa (args) {
241224 return Bluebird . try ( ( ) => {
242225 // if they're using legacy auth currently then we have to update them to a
243226 // bearer token before continuing.
244- if ( conf . auth . basic ) {
227+ const auth = getAuth ( conf )
228+ if ( auth . basic ) {
245229 log . info ( 'profile' , 'Updating authentication to bearer token' )
246- return profile . login ( conf . auth . basic . username , conf . auth . basic . password , conf ) . then ( ( result ) => {
230+ return profile . createToken (
231+ auth . basic . password , false , [ ] , conf
232+ ) . then ( ( result ) => {
247233 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' )
248234 npm . config . setCredentialsByURI ( conf . registry , { token : result . token } )
249235 return Bluebird . fromNode ( ( cb ) => npm . config . save ( 'user' , cb ) )
@@ -295,18 +281,36 @@ function enable2fa (args) {
295281 } )
296282}
297283
284+ function getAuth ( conf ) {
285+ const creds = npm . config . getCredentialsByURI ( conf . registry )
286+ let auth
287+ if ( creds . token ) {
288+ auth = { token : creds . token }
289+ } else if ( creds . username ) {
290+ auth = { basic : { username : creds . username , password : creds . password } }
291+ } else if ( creds . auth ) {
292+ const basic = Buffer . from ( creds . auth , 'base64' ) . toString ( ) . split ( ':' , 2 )
293+ auth = { basic : { username : basic [ 0 ] , password : basic [ 1 ] } }
294+ } else {
295+ auth = { }
296+ }
297+
298+ if ( conf . otp ) auth . otp = conf . otp
299+ return auth
300+ }
301+
298302function disable2fa ( args ) {
299- const conf = config ( )
303+ let conf = ProfileOpts ( npmConfig ( ) )
300304 return pulseTillDone . withPromise ( profile . get ( conf ) ) . then ( ( info ) => {
301305 if ( ! info . tfa || info . tfa . pending ) {
302306 output ( 'Two factor authentication not enabled.' )
303307 return
304308 }
305309 return readUserInfo . password ( ) . then ( ( password ) => {
306310 return Bluebird . try ( ( ) => {
307- if ( conf . auth . otp ) return
311+ if ( conf . otp ) return
308312 return readUserInfo . otp ( 'Enter one-time password from your authenticator: ' ) . then ( ( otp ) => {
309- conf . auth . otp = otp
313+ conf = conf . concat ( { otp} )
310314 } )
311315 } ) . then ( ( ) => {
312316 log . info ( 'profile' , 'disabling tfa' )
0 commit comments