11cb0ef41Sopenharmony_ciconst t = require('tap') 21cb0ef41Sopenharmony_ciconst mockNpm = require('../../fixtures/mock-npm') 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciconst mockProfile = async (t, { npmProfile, readUserInfo, qrcode, config, ...opts } = {}) => { 51cb0ef41Sopenharmony_ci const mocks = { 61cb0ef41Sopenharmony_ci 'npm-profile': npmProfile || { 71cb0ef41Sopenharmony_ci async get () {}, 81cb0ef41Sopenharmony_ci async set () {}, 91cb0ef41Sopenharmony_ci async createToken () {}, 101cb0ef41Sopenharmony_ci }, 111cb0ef41Sopenharmony_ci 'qrcode-terminal': qrcode || { generate: (url, cb) => cb() }, 121cb0ef41Sopenharmony_ci 'cli-table3': class extends Array { 131cb0ef41Sopenharmony_ci toString () { 141cb0ef41Sopenharmony_ci return this.filter(Boolean) 151cb0ef41Sopenharmony_ci .map(i => [...Object.entries(i)].map(v => v.join(': '))) 161cb0ef41Sopenharmony_ci .join('\n') 171cb0ef41Sopenharmony_ci } 181cb0ef41Sopenharmony_ci }, 191cb0ef41Sopenharmony_ci '{LIB}/utils/read-user-info.js': readUserInfo || { 201cb0ef41Sopenharmony_ci async password () {}, 211cb0ef41Sopenharmony_ci async otp () {}, 221cb0ef41Sopenharmony_ci }, 231cb0ef41Sopenharmony_ci } 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci const mock = await mockNpm(t, { 261cb0ef41Sopenharmony_ci ...opts, 271cb0ef41Sopenharmony_ci command: 'profile', 281cb0ef41Sopenharmony_ci config: { 291cb0ef41Sopenharmony_ci color: false, 301cb0ef41Sopenharmony_ci ...config, 311cb0ef41Sopenharmony_ci }, 321cb0ef41Sopenharmony_ci mocks: { 331cb0ef41Sopenharmony_ci ...mocks, 341cb0ef41Sopenharmony_ci ...opts.mocks, 351cb0ef41Sopenharmony_ci }, 361cb0ef41Sopenharmony_ci }) 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci return { 391cb0ef41Sopenharmony_ci ...mock, 401cb0ef41Sopenharmony_ci result: () => mock.joinedOutput(), 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ciconst userProfile = { 451cb0ef41Sopenharmony_ci tfa: { pending: false, mode: 'auth-and-writes' }, 461cb0ef41Sopenharmony_ci name: 'foo', 471cb0ef41Sopenharmony_ci email: 'foo@github.com', 481cb0ef41Sopenharmony_ci email_verified: true, 491cb0ef41Sopenharmony_ci created: '2015-02-26T01:26:37.384Z', 501cb0ef41Sopenharmony_ci updated: '2020-08-12T16:19:35.326Z', 511cb0ef41Sopenharmony_ci cidr_whitelist: null, 521cb0ef41Sopenharmony_ci fullname: 'Foo Bar', 531cb0ef41Sopenharmony_ci homepage: 'https://github.com', 541cb0ef41Sopenharmony_ci freenode: 'foobar', 551cb0ef41Sopenharmony_ci twitter: 'https://twitter.com/npmjs', 561cb0ef41Sopenharmony_ci github: 'https://github.com/npm', 571cb0ef41Sopenharmony_ci} 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_cit.test('no args', async t => { 601cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 611cb0ef41Sopenharmony_ci await t.rejects(profile.exec([]), await profile.usage) 621cb0ef41Sopenharmony_ci}) 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_cit.test('profile get no args', async t => { 651cb0ef41Sopenharmony_ci const defaultNpmProfile = { 661cb0ef41Sopenharmony_ci async get () { 671cb0ef41Sopenharmony_ci return userProfile 681cb0ef41Sopenharmony_ci }, 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci t.test('default output', async t => { 721cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { npmProfile: defaultNpmProfile }) 731cb0ef41Sopenharmony_ci await profile.exec(['get']) 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output table with contents') 761cb0ef41Sopenharmony_ci }) 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci t.test('--json', async t => { 791cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 801cb0ef41Sopenharmony_ci npmProfile: defaultNpmProfile, 811cb0ef41Sopenharmony_ci config: { json: true }, 821cb0ef41Sopenharmony_ci }) 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci await profile.exec(['get']) 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci t.same(JSON.parse(result()), userProfile, 'should output json profile result') 871cb0ef41Sopenharmony_ci }) 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci t.test('--parseable', async t => { 901cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 911cb0ef41Sopenharmony_ci npmProfile: defaultNpmProfile, 921cb0ef41Sopenharmony_ci config: { parseable: true }, 931cb0ef41Sopenharmony_ci }) 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci await profile.exec(['get']) 961cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output all profile info as parseable result') 971cb0ef41Sopenharmony_ci }) 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci t.test('--color', async t => { 1001cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 1011cb0ef41Sopenharmony_ci npmProfile: defaultNpmProfile, 1021cb0ef41Sopenharmony_ci config: { color: 'always' }, 1031cb0ef41Sopenharmony_ci }) 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci await profile.exec(['get']) 1061cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output all profile info with color result') 1071cb0ef41Sopenharmony_ci }) 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci t.test('no tfa enabled', async t => { 1101cb0ef41Sopenharmony_ci const npmProfile = { 1111cb0ef41Sopenharmony_ci async get () { 1121cb0ef41Sopenharmony_ci return { 1131cb0ef41Sopenharmony_ci ...userProfile, 1141cb0ef41Sopenharmony_ci tfa: null, 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci }, 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { npmProfile }) 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci await profile.exec(['get']) 1211cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output expected profile values') 1221cb0ef41Sopenharmony_ci }) 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci t.test('unverified email', async t => { 1251cb0ef41Sopenharmony_ci const npmProfile = { 1261cb0ef41Sopenharmony_ci async get () { 1271cb0ef41Sopenharmony_ci return { 1281cb0ef41Sopenharmony_ci ...userProfile, 1291cb0ef41Sopenharmony_ci email_verified: false, 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci }, 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { npmProfile }) 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci await profile.exec(['get']) 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output table with contents') 1391cb0ef41Sopenharmony_ci }) 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci t.test('profile has cidr_whitelist item', async t => { 1421cb0ef41Sopenharmony_ci const npmProfile = { 1431cb0ef41Sopenharmony_ci async get () { 1441cb0ef41Sopenharmony_ci return { 1451cb0ef41Sopenharmony_ci ...userProfile, 1461cb0ef41Sopenharmony_ci cidr_whitelist: ['192.168.1.1'], 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci }, 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { npmProfile }) 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci await profile.exec(['get']) 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output table with contents') 1561cb0ef41Sopenharmony_ci }) 1571cb0ef41Sopenharmony_ci}) 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_cit.test('profile get <key>', async t => { 1601cb0ef41Sopenharmony_ci const npmProfile = { 1611cb0ef41Sopenharmony_ci async get () { 1621cb0ef41Sopenharmony_ci return userProfile 1631cb0ef41Sopenharmony_ci }, 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci t.test('default output', async t => { 1671cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { npmProfile }) 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci await profile.exec(['get', 'name']) 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci t.equal(result(), 'foo', 'should output value result') 1721cb0ef41Sopenharmony_ci }) 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci t.test('--json', async t => { 1751cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 1761cb0ef41Sopenharmony_ci npmProfile, 1771cb0ef41Sopenharmony_ci config: { json: true }, 1781cb0ef41Sopenharmony_ci }) 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci await profile.exec(['get', 'name']) 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci t.same( 1831cb0ef41Sopenharmony_ci JSON.parse(result()), 1841cb0ef41Sopenharmony_ci userProfile, 1851cb0ef41Sopenharmony_ci 'should output json profile result ignoring args filter' 1861cb0ef41Sopenharmony_ci ) 1871cb0ef41Sopenharmony_ci }) 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci t.test('--parseable', async t => { 1901cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 1911cb0ef41Sopenharmony_ci npmProfile, 1921cb0ef41Sopenharmony_ci config: { parseable: true }, 1931cb0ef41Sopenharmony_ci }) 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci await profile.exec(['get', 'name']) 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output parseable result value') 1981cb0ef41Sopenharmony_ci }) 1991cb0ef41Sopenharmony_ci}) 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_cit.test('profile get multiple args', async t => { 2021cb0ef41Sopenharmony_ci const npmProfile = { 2031cb0ef41Sopenharmony_ci async get () { 2041cb0ef41Sopenharmony_ci return userProfile 2051cb0ef41Sopenharmony_ci }, 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci t.test('default output', async t => { 2091cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 2101cb0ef41Sopenharmony_ci npmProfile, 2111cb0ef41Sopenharmony_ci }) 2121cb0ef41Sopenharmony_ci await profile.exec(['get', 'name', 'email', 'github']) 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output all keys') 2151cb0ef41Sopenharmony_ci }) 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci t.test('--json', async t => { 2181cb0ef41Sopenharmony_ci const config = { json: true } 2191cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 2201cb0ef41Sopenharmony_ci npmProfile, 2211cb0ef41Sopenharmony_ci config, 2221cb0ef41Sopenharmony_ci }) 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci await profile.exec(['get', 'name', 'email', 'github']) 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci t.same(JSON.parse(result()), userProfile, 'should output json profile result and ignore args') 2271cb0ef41Sopenharmony_ci }) 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci t.test('--parseable', async t => { 2301cb0ef41Sopenharmony_ci const config = { parseable: true } 2311cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 2321cb0ef41Sopenharmony_ci npmProfile, 2331cb0ef41Sopenharmony_ci config, 2341cb0ef41Sopenharmony_ci }) 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci await profile.exec(['get', 'name', 'email', 'github']) 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output parseable profile value results') 2391cb0ef41Sopenharmony_ci }) 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci t.test('comma separated', async t => { 2421cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 2431cb0ef41Sopenharmony_ci npmProfile, 2441cb0ef41Sopenharmony_ci }) 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci await profile.exec(['get', 'name,email,github']) 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output all keys') 2491cb0ef41Sopenharmony_ci }) 2501cb0ef41Sopenharmony_ci}) 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_cit.test('profile set <key> <value>', async t => { 2531cb0ef41Sopenharmony_ci t.test('no key', async t => { 2541cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci await t.rejects( 2571cb0ef41Sopenharmony_ci profile.exec(['set']), 2581cb0ef41Sopenharmony_ci /npm profile set <prop> <value>/, 2591cb0ef41Sopenharmony_ci 'should throw proper usage message' 2601cb0ef41Sopenharmony_ci ) 2611cb0ef41Sopenharmony_ci }) 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci t.test('no value', async t => { 2641cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 2651cb0ef41Sopenharmony_ci await t.rejects( 2661cb0ef41Sopenharmony_ci profile.exec(['set', 'email']), 2671cb0ef41Sopenharmony_ci /npm profile set <prop> <value>/, 2681cb0ef41Sopenharmony_ci 'should throw proper usage message' 2691cb0ef41Sopenharmony_ci ) 2701cb0ef41Sopenharmony_ci }) 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci t.test('set password', async t => { 2731cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 2741cb0ef41Sopenharmony_ci await t.rejects( 2751cb0ef41Sopenharmony_ci profile.exec(['set', 'password', '1234']), 2761cb0ef41Sopenharmony_ci /Do not include your current or new passwords on the command line./, 2771cb0ef41Sopenharmony_ci 'should throw an error refusing to set password from args' 2781cb0ef41Sopenharmony_ci ) 2791cb0ef41Sopenharmony_ci }) 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci t.test('unwritable key', async t => { 2821cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 2831cb0ef41Sopenharmony_ci await await t.rejects( 2841cb0ef41Sopenharmony_ci profile.exec(['set', 'name', 'foo']), 2851cb0ef41Sopenharmony_ci /"name" is not a property we can set./, 2861cb0ef41Sopenharmony_ci 'should throw the unwritable key error' 2871cb0ef41Sopenharmony_ci ) 2881cb0ef41Sopenharmony_ci }) 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci const defaultNpmProfile = t => ({ 2911cb0ef41Sopenharmony_ci async get () { 2921cb0ef41Sopenharmony_ci return userProfile 2931cb0ef41Sopenharmony_ci }, 2941cb0ef41Sopenharmony_ci async set (newUser) { 2951cb0ef41Sopenharmony_ci t.match( 2961cb0ef41Sopenharmony_ci newUser, 2971cb0ef41Sopenharmony_ci { 2981cb0ef41Sopenharmony_ci fullname: 'Lorem Ipsum', 2991cb0ef41Sopenharmony_ci }, 3001cb0ef41Sopenharmony_ci 'should set new value to key' 3011cb0ef41Sopenharmony_ci ) 3021cb0ef41Sopenharmony_ci return { 3031cb0ef41Sopenharmony_ci ...userProfile, 3041cb0ef41Sopenharmony_ci ...newUser, 3051cb0ef41Sopenharmony_ci } 3061cb0ef41Sopenharmony_ci }, 3071cb0ef41Sopenharmony_ci }) 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci t.test('writable key', async t => { 3101cb0ef41Sopenharmony_ci t.test('default output', async t => { 3111cb0ef41Sopenharmony_ci t.plan(2) 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 3141cb0ef41Sopenharmony_ci npmProfile: defaultNpmProfile(t), 3151cb0ef41Sopenharmony_ci }) 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci await profile.exec(['set', 'fullname', 'Lorem Ipsum']) 3181cb0ef41Sopenharmony_ci t.equal(result(), 'Set fullname to Lorem Ipsum', 'should output set key success msg') 3191cb0ef41Sopenharmony_ci }) 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci t.test('--json', async t => { 3221cb0ef41Sopenharmony_ci t.plan(2) 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci const config = { json: true } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 3271cb0ef41Sopenharmony_ci npmProfile: defaultNpmProfile(t), 3281cb0ef41Sopenharmony_ci config, 3291cb0ef41Sopenharmony_ci }) 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci await profile.exec(['set', 'fullname', 'Lorem Ipsum']) 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci t.same( 3341cb0ef41Sopenharmony_ci JSON.parse(result()), 3351cb0ef41Sopenharmony_ci { 3361cb0ef41Sopenharmony_ci fullname: 'Lorem Ipsum', 3371cb0ef41Sopenharmony_ci }, 3381cb0ef41Sopenharmony_ci 'should output json set key success msg' 3391cb0ef41Sopenharmony_ci ) 3401cb0ef41Sopenharmony_ci }) 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci t.test('--parseable', async t => { 3431cb0ef41Sopenharmony_ci t.plan(2) 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci const config = { parseable: true } 3461cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 3471cb0ef41Sopenharmony_ci npmProfile: defaultNpmProfile(t), 3481cb0ef41Sopenharmony_ci config, 3491cb0ef41Sopenharmony_ci }) 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci await profile.exec(['set', 'fullname', 'Lorem Ipsum']) 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output parseable set key success msg') 3541cb0ef41Sopenharmony_ci }) 3551cb0ef41Sopenharmony_ci }) 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci t.test('write new email', async t => { 3581cb0ef41Sopenharmony_ci t.plan(2) 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci const npmProfile = { 3611cb0ef41Sopenharmony_ci async get () { 3621cb0ef41Sopenharmony_ci return userProfile 3631cb0ef41Sopenharmony_ci }, 3641cb0ef41Sopenharmony_ci async set (newUser) { 3651cb0ef41Sopenharmony_ci t.match( 3661cb0ef41Sopenharmony_ci newUser, 3671cb0ef41Sopenharmony_ci { 3681cb0ef41Sopenharmony_ci email: 'foo@npmjs.com', 3691cb0ef41Sopenharmony_ci }, 3701cb0ef41Sopenharmony_ci 'should set new value to email' 3711cb0ef41Sopenharmony_ci ) 3721cb0ef41Sopenharmony_ci return { 3731cb0ef41Sopenharmony_ci ...userProfile, 3741cb0ef41Sopenharmony_ci ...newUser, 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci }, 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 3801cb0ef41Sopenharmony_ci npmProfile, 3811cb0ef41Sopenharmony_ci }) 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci await profile.exec(['set', 'email', 'foo@npmjs.com']) 3841cb0ef41Sopenharmony_ci t.equal(result(), 'Set email to foo@npmjs.com', 'should output set key success msg') 3851cb0ef41Sopenharmony_ci }) 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci t.test('change password', async t => { 3881cb0ef41Sopenharmony_ci t.plan(5) 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci const npmProfile = { 3911cb0ef41Sopenharmony_ci async get () { 3921cb0ef41Sopenharmony_ci return userProfile 3931cb0ef41Sopenharmony_ci }, 3941cb0ef41Sopenharmony_ci async set (newUser) { 3951cb0ef41Sopenharmony_ci t.match( 3961cb0ef41Sopenharmony_ci newUser, 3971cb0ef41Sopenharmony_ci { 3981cb0ef41Sopenharmony_ci password: { 3991cb0ef41Sopenharmony_ci old: 'currentpassword1234', 4001cb0ef41Sopenharmony_ci new: 'newpassword1234', 4011cb0ef41Sopenharmony_ci }, 4021cb0ef41Sopenharmony_ci }, 4031cb0ef41Sopenharmony_ci 'should set new password' 4041cb0ef41Sopenharmony_ci ) 4051cb0ef41Sopenharmony_ci return { 4061cb0ef41Sopenharmony_ci ...userProfile, 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci }, 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci const readUserInfo = { 4121cb0ef41Sopenharmony_ci async password (label) { 4131cb0ef41Sopenharmony_ci if (label === 'Current password: ') { 4141cb0ef41Sopenharmony_ci t.ok('should interactively ask for password confirmation') 4151cb0ef41Sopenharmony_ci } else if (label === 'New password: ') { 4161cb0ef41Sopenharmony_ci t.ok('should interactively ask for new password') 4171cb0ef41Sopenharmony_ci } else if (label === ' Again: ') { 4181cb0ef41Sopenharmony_ci t.ok('should interactively ask for new password confirmation') 4191cb0ef41Sopenharmony_ci } else { 4201cb0ef41Sopenharmony_ci throw new Error('Unexpected label: ' + label) 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci return label === 'Current password: ' ? 'currentpassword1234' : 'newpassword1234' 4241cb0ef41Sopenharmony_ci }, 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 4281cb0ef41Sopenharmony_ci npmProfile, 4291cb0ef41Sopenharmony_ci readUserInfo, 4301cb0ef41Sopenharmony_ci }) 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci await profile.exec(['set', 'password']) 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci t.equal(result(), 'Set password', 'should output set password success msg') 4351cb0ef41Sopenharmony_ci }) 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci t.test('password confirmation mismatch', async t => { 4381cb0ef41Sopenharmony_ci t.plan(2) 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_ci let passwordPromptCount = 0 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci const npmProfile = { 4431cb0ef41Sopenharmony_ci async get () { 4441cb0ef41Sopenharmony_ci return userProfile 4451cb0ef41Sopenharmony_ci }, 4461cb0ef41Sopenharmony_ci async set () { 4471cb0ef41Sopenharmony_ci return { ...userProfile } 4481cb0ef41Sopenharmony_ci }, 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci const readUserInfo = { 4521cb0ef41Sopenharmony_ci async password (label) { 4531cb0ef41Sopenharmony_ci passwordPromptCount++ 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci switch (label) { 4561cb0ef41Sopenharmony_ci case 'Current password: ': 4571cb0ef41Sopenharmony_ci return 'currentpassword1234' 4581cb0ef41Sopenharmony_ci case 'New password: ': 4591cb0ef41Sopenharmony_ci return passwordPromptCount < 3 ? 'password-that-will-not-be-confirmed' : 'newpassword' 4601cb0ef41Sopenharmony_ci case ' Again: ': 4611cb0ef41Sopenharmony_ci return 'newpassword' 4621cb0ef41Sopenharmony_ci default: 4631cb0ef41Sopenharmony_ci return 'password1234' 4641cb0ef41Sopenharmony_ci } 4651cb0ef41Sopenharmony_ci }, 4661cb0ef41Sopenharmony_ci } 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci const { profile, result, logs } = await mockProfile(t, { 4691cb0ef41Sopenharmony_ci npmProfile, 4701cb0ef41Sopenharmony_ci readUserInfo, 4711cb0ef41Sopenharmony_ci }) 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci await profile.exec(['set', 'password']) 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci t.equal( 4761cb0ef41Sopenharmony_ci logs.warn[0][1], 4771cb0ef41Sopenharmony_ci 'Passwords do not match, please try again.', 4781cb0ef41Sopenharmony_ci 'should log password mismatch message' 4791cb0ef41Sopenharmony_ci ) 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ci t.equal(result(), 'Set password', 'should output set password success msg') 4821cb0ef41Sopenharmony_ci }) 4831cb0ef41Sopenharmony_ci}) 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_cit.test('enable-2fa', async t => { 4861cb0ef41Sopenharmony_ci t.test('invalid args', async t => { 4871cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 4881cb0ef41Sopenharmony_ci await t.rejects( 4891cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'foo', 'bar']), 4901cb0ef41Sopenharmony_ci /npm profile enable-2fa \[auth-and-writes|auth-only\]/, 4911cb0ef41Sopenharmony_ci 'should throw usage error' 4921cb0ef41Sopenharmony_ci ) 4931cb0ef41Sopenharmony_ci }) 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci t.test('invalid two factor auth mode', async t => { 4961cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 4971cb0ef41Sopenharmony_ci await t.rejects( 4981cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'foo']), 4991cb0ef41Sopenharmony_ci /Invalid two-factor authentication mode "foo"/, 5001cb0ef41Sopenharmony_ci 'should throw invalid auth mode error' 5011cb0ef41Sopenharmony_ci ) 5021cb0ef41Sopenharmony_ci }) 5031cb0ef41Sopenharmony_ci 5041cb0ef41Sopenharmony_ci t.test('no support for --json output', async t => { 5051cb0ef41Sopenharmony_ci const config = { json: true } 5061cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t, { config }) 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci await t.rejects( 5091cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'auth-only']), 5101cb0ef41Sopenharmony_ci 'Enabling two-factor authentication is an interactive ' + 5111cb0ef41Sopenharmony_ci 'operation and JSON output mode is not available', 5121cb0ef41Sopenharmony_ci 'should throw no support msg' 5131cb0ef41Sopenharmony_ci ) 5141cb0ef41Sopenharmony_ci }) 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_ci t.test('no support for --parseable output', async t => { 5171cb0ef41Sopenharmony_ci const config = { parseable: true } 5181cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t, { config }) 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_ci await t.rejects( 5211cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'auth-only']), 5221cb0ef41Sopenharmony_ci 'Enabling two-factor authentication is an interactive ' + 5231cb0ef41Sopenharmony_ci 'operation and parseable output mode is not available', 5241cb0ef41Sopenharmony_ci 'should throw no support msg' 5251cb0ef41Sopenharmony_ci ) 5261cb0ef41Sopenharmony_ci }) 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci t.test('no bearer tokens returned by registry', async t => { 5291cb0ef41Sopenharmony_ci t.plan(3) 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci const npmProfile = { 5321cb0ef41Sopenharmony_ci async createToken (pass) { 5331cb0ef41Sopenharmony_ci t.match(pass, 'bar', 'should use password for basic auth') 5341cb0ef41Sopenharmony_ci return {} 5351cb0ef41Sopenharmony_ci }, 5361cb0ef41Sopenharmony_ci } 5371cb0ef41Sopenharmony_ci 5381cb0ef41Sopenharmony_ci const { npm, profile } = await mockProfile(t, { 5391cb0ef41Sopenharmony_ci npmProfile, 5401cb0ef41Sopenharmony_ci }) 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci // mock legacy basic auth style 5431cb0ef41Sopenharmony_ci // XXX: use mock registry 5441cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = reg => { 5451cb0ef41Sopenharmony_ci t.equal(reg, npm.flatOptions.registry, 'should use expected registry') 5461cb0ef41Sopenharmony_ci return { auth: Buffer.from('foo:bar').toString('base64') } 5471cb0ef41Sopenharmony_ci } 5481cb0ef41Sopenharmony_ci 5491cb0ef41Sopenharmony_ci await t.rejects( 5501cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'auth-only']), 5511cb0ef41Sopenharmony_ci 'Your registry https://registry.npmjs.org/ does ' + 5521cb0ef41Sopenharmony_ci 'not seem to support bearer tokens. Bearer tokens ' + 5531cb0ef41Sopenharmony_ci 'are required for two-factor authentication', 5541cb0ef41Sopenharmony_ci 'should throw no support msg' 5551cb0ef41Sopenharmony_ci ) 5561cb0ef41Sopenharmony_ci }) 5571cb0ef41Sopenharmony_ci 5581cb0ef41Sopenharmony_ci t.test('from basic username/password auth', async t => { 5591cb0ef41Sopenharmony_ci const npmProfile = { 5601cb0ef41Sopenharmony_ci async createToken (pass) { 5611cb0ef41Sopenharmony_ci return {} 5621cb0ef41Sopenharmony_ci }, 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci const { npm, profile } = await mockProfile(t, { 5661cb0ef41Sopenharmony_ci npmProfile, 5671cb0ef41Sopenharmony_ci }) 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci // mock legacy basic auth style with user/pass 5701cb0ef41Sopenharmony_ci // XXX: use mock registry 5711cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = () => { 5721cb0ef41Sopenharmony_ci return { username: 'foo', password: 'bar' } 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci await t.rejects( 5761cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'auth-only']), 5771cb0ef41Sopenharmony_ci 'Your registry https://registry.npmjs.org/ does ' + 5781cb0ef41Sopenharmony_ci 'not seem to support bearer tokens. Bearer tokens ' + 5791cb0ef41Sopenharmony_ci 'are required for two-factor authentication', 5801cb0ef41Sopenharmony_ci 'should throw no support msg' 5811cb0ef41Sopenharmony_ci ) 5821cb0ef41Sopenharmony_ci }) 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ci t.test('no auth found', async t => { 5851cb0ef41Sopenharmony_ci const { npm, profile } = await mockProfile(t) 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci // XXX: use mock registry 5881cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = () => ({}) 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci await t.rejects( 5911cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'auth-only']), 5921cb0ef41Sopenharmony_ci 'You need to be logged in to registry ' + 'https://registry.npmjs.org/ in order to enable 2fa' 5931cb0ef41Sopenharmony_ci ) 5941cb0ef41Sopenharmony_ci }) 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_ci t.test('from basic auth, asks for otp', async t => { 5971cb0ef41Sopenharmony_ci t.plan(9) 5981cb0ef41Sopenharmony_ci 5991cb0ef41Sopenharmony_ci const npmProfile = { 6001cb0ef41Sopenharmony_ci async createToken (pass) { 6011cb0ef41Sopenharmony_ci t.match(pass, 'bar', 'should use password for basic auth') 6021cb0ef41Sopenharmony_ci return { token: 'token' } 6031cb0ef41Sopenharmony_ci }, 6041cb0ef41Sopenharmony_ci async get () { 6051cb0ef41Sopenharmony_ci return userProfile 6061cb0ef41Sopenharmony_ci }, 6071cb0ef41Sopenharmony_ci async set (newProfile, conf) { 6081cb0ef41Sopenharmony_ci t.match( 6091cb0ef41Sopenharmony_ci newProfile, 6101cb0ef41Sopenharmony_ci { 6111cb0ef41Sopenharmony_ci tfa: { 6121cb0ef41Sopenharmony_ci mode: 'auth-only', 6131cb0ef41Sopenharmony_ci }, 6141cb0ef41Sopenharmony_ci }, 6151cb0ef41Sopenharmony_ci 'should set tfa mode' 6161cb0ef41Sopenharmony_ci ) 6171cb0ef41Sopenharmony_ci return { 6181cb0ef41Sopenharmony_ci ...userProfile, 6191cb0ef41Sopenharmony_ci tfa: null, 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci }, 6221cb0ef41Sopenharmony_ci } 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci const readUserInfo = { 6251cb0ef41Sopenharmony_ci async password () { 6261cb0ef41Sopenharmony_ci t.ok('should interactively ask for password confirmation') 6271cb0ef41Sopenharmony_ci return 'password1234' 6281cb0ef41Sopenharmony_ci }, 6291cb0ef41Sopenharmony_ci async otp (label) { 6301cb0ef41Sopenharmony_ci t.equal( 6311cb0ef41Sopenharmony_ci label, 6321cb0ef41Sopenharmony_ci 'Enter one-time password: ', 6331cb0ef41Sopenharmony_ci 'should ask for otp confirmation' 6341cb0ef41Sopenharmony_ci ) 6351cb0ef41Sopenharmony_ci return '123456' 6361cb0ef41Sopenharmony_ci }, 6371cb0ef41Sopenharmony_ci } 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci const { npm, profile, result } = await mockProfile(t, { 6401cb0ef41Sopenharmony_ci npmProfile, 6411cb0ef41Sopenharmony_ci readUserInfo, 6421cb0ef41Sopenharmony_ci }) 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci // mock legacy basic auth style 6451cb0ef41Sopenharmony_ci // XXX: use mock registry 6461cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = reg => { 6471cb0ef41Sopenharmony_ci t.equal(reg, npm.flatOptions.registry, 'should use expected registry') 6481cb0ef41Sopenharmony_ci return { auth: Buffer.from('foo:bar').toString('base64') } 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci npm.config.setCredentialsByURI = (registry, { token }) => { 6511cb0ef41Sopenharmony_ci t.equal(registry, npm.flatOptions.registry, 'should set expected registry') 6521cb0ef41Sopenharmony_ci t.equal(token, 'token', 'should set expected token') 6531cb0ef41Sopenharmony_ci } 6541cb0ef41Sopenharmony_ci npm.config.save = type => { 6551cb0ef41Sopenharmony_ci t.equal(type, 'user', 'should save to user config') 6561cb0ef41Sopenharmony_ci } 6571cb0ef41Sopenharmony_ci 6581cb0ef41Sopenharmony_ci await profile.exec(['enable-2fa', 'auth-only']) 6591cb0ef41Sopenharmony_ci t.equal( 6601cb0ef41Sopenharmony_ci result(), 6611cb0ef41Sopenharmony_ci 'Two factor authentication mode changed to: auth-only', 6621cb0ef41Sopenharmony_ci 'should output success msg' 6631cb0ef41Sopenharmony_ci ) 6641cb0ef41Sopenharmony_ci }) 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_ci t.test('from token and set otp, retries on pending and verifies with qrcode', async t => { 6671cb0ef41Sopenharmony_ci t.plan(4) 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ci let setCount = 0 6701cb0ef41Sopenharmony_ci const npmProfile = { 6711cb0ef41Sopenharmony_ci async get () { 6721cb0ef41Sopenharmony_ci return { 6731cb0ef41Sopenharmony_ci ...userProfile, 6741cb0ef41Sopenharmony_ci tfa: { 6751cb0ef41Sopenharmony_ci pending: true, 6761cb0ef41Sopenharmony_ci }, 6771cb0ef41Sopenharmony_ci } 6781cb0ef41Sopenharmony_ci }, 6791cb0ef41Sopenharmony_ci async set (newProfile, conf) { 6801cb0ef41Sopenharmony_ci setCount++ 6811cb0ef41Sopenharmony_ci 6821cb0ef41Sopenharmony_ci // when profile response shows that 2fa is pending the 6831cb0ef41Sopenharmony_ci // first time calling npm-profile.set should reset 2fa 6841cb0ef41Sopenharmony_ci if (setCount === 1) { 6851cb0ef41Sopenharmony_ci t.match( 6861cb0ef41Sopenharmony_ci newProfile, 6871cb0ef41Sopenharmony_ci { 6881cb0ef41Sopenharmony_ci tfa: { 6891cb0ef41Sopenharmony_ci password: 'password1234', 6901cb0ef41Sopenharmony_ci mode: 'disable', 6911cb0ef41Sopenharmony_ci }, 6921cb0ef41Sopenharmony_ci }, 6931cb0ef41Sopenharmony_ci 'should reset 2fa' 6941cb0ef41Sopenharmony_ci ) 6951cb0ef41Sopenharmony_ci } else if (setCount === 2) { 6961cb0ef41Sopenharmony_ci t.match( 6971cb0ef41Sopenharmony_ci newProfile, 6981cb0ef41Sopenharmony_ci { 6991cb0ef41Sopenharmony_ci tfa: { 7001cb0ef41Sopenharmony_ci mode: 'auth-only', 7011cb0ef41Sopenharmony_ci }, 7021cb0ef41Sopenharmony_ci }, 7031cb0ef41Sopenharmony_ci 'should set tfa mode approprietly in follow-up call' 7041cb0ef41Sopenharmony_ci ) 7051cb0ef41Sopenharmony_ci } else if (setCount === 3) { 7061cb0ef41Sopenharmony_ci t.match( 7071cb0ef41Sopenharmony_ci newProfile, 7081cb0ef41Sopenharmony_ci { 7091cb0ef41Sopenharmony_ci tfa: ['123456'], 7101cb0ef41Sopenharmony_ci }, 7111cb0ef41Sopenharmony_ci 'should set tfa as otp code?' 7121cb0ef41Sopenharmony_ci ) 7131cb0ef41Sopenharmony_ci return { 7141cb0ef41Sopenharmony_ci ...userProfile, 7151cb0ef41Sopenharmony_ci tfa: ['123456', '789101'], 7161cb0ef41Sopenharmony_ci } 7171cb0ef41Sopenharmony_ci } 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_ci return { 7201cb0ef41Sopenharmony_ci ...userProfile, 7211cb0ef41Sopenharmony_ci tfa: 'otpauth://foo?secret=1234', 7221cb0ef41Sopenharmony_ci } 7231cb0ef41Sopenharmony_ci }, 7241cb0ef41Sopenharmony_ci } 7251cb0ef41Sopenharmony_ci 7261cb0ef41Sopenharmony_ci const readUserInfo = { 7271cb0ef41Sopenharmony_ci async password () { 7281cb0ef41Sopenharmony_ci return 'password1234' 7291cb0ef41Sopenharmony_ci }, 7301cb0ef41Sopenharmony_ci async otp () { 7311cb0ef41Sopenharmony_ci return '123456' 7321cb0ef41Sopenharmony_ci }, 7331cb0ef41Sopenharmony_ci } 7341cb0ef41Sopenharmony_ci 7351cb0ef41Sopenharmony_ci const qrcode = { 7361cb0ef41Sopenharmony_ci /* eslint-disable-next-line node/no-callback-literal */ 7371cb0ef41Sopenharmony_ci generate: (url, cb) => cb('qrcode'), 7381cb0ef41Sopenharmony_ci } 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_ci const { npm, profile, result } = await mockProfile(t, { 7411cb0ef41Sopenharmony_ci npmProfile, 7421cb0ef41Sopenharmony_ci qrcode, 7431cb0ef41Sopenharmony_ci readUserInfo, 7441cb0ef41Sopenharmony_ci config: { otp: '1234' }, 7451cb0ef41Sopenharmony_ci }) 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_ci // XXX: use mock registry 7481cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = () => { 7491cb0ef41Sopenharmony_ci return { token: 'token' } 7501cb0ef41Sopenharmony_ci } 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci await profile.exec(['enable-2fa', 'auth-only']) 7531cb0ef41Sopenharmony_ci 7541cb0ef41Sopenharmony_ci t.matchSnapshot(result(), 'should output 2fa enablement success msgs') 7551cb0ef41Sopenharmony_ci }) 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ci t.test('from token and set otp, retrieves invalid otp', async t => { 7581cb0ef41Sopenharmony_ci const npmProfile = { 7591cb0ef41Sopenharmony_ci async get () { 7601cb0ef41Sopenharmony_ci return { 7611cb0ef41Sopenharmony_ci ...userProfile, 7621cb0ef41Sopenharmony_ci tfa: { 7631cb0ef41Sopenharmony_ci pending: true, 7641cb0ef41Sopenharmony_ci }, 7651cb0ef41Sopenharmony_ci } 7661cb0ef41Sopenharmony_ci }, 7671cb0ef41Sopenharmony_ci async set (newProfile, conf) { 7681cb0ef41Sopenharmony_ci return { 7691cb0ef41Sopenharmony_ci ...userProfile, 7701cb0ef41Sopenharmony_ci tfa: 'http://foo?secret=1234', 7711cb0ef41Sopenharmony_ci } 7721cb0ef41Sopenharmony_ci }, 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ci const readUserInfo = { 7761cb0ef41Sopenharmony_ci async password () { 7771cb0ef41Sopenharmony_ci return 'password1234' 7781cb0ef41Sopenharmony_ci }, 7791cb0ef41Sopenharmony_ci async otp (label) { 7801cb0ef41Sopenharmony_ci return '123456' 7811cb0ef41Sopenharmony_ci }, 7821cb0ef41Sopenharmony_ci } 7831cb0ef41Sopenharmony_ci 7841cb0ef41Sopenharmony_ci const { npm, profile } = await mockProfile(t, { 7851cb0ef41Sopenharmony_ci npmProfile, 7861cb0ef41Sopenharmony_ci readUserInfo, 7871cb0ef41Sopenharmony_ci config: { otp: '1234' }, 7881cb0ef41Sopenharmony_ci }) 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = () => { 7911cb0ef41Sopenharmony_ci return { token: 'token' } 7921cb0ef41Sopenharmony_ci } 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ci await t.rejects( 7951cb0ef41Sopenharmony_ci profile.exec(['enable-2fa', 'auth-only']), 7961cb0ef41Sopenharmony_ci /Unknown error enabling two-factor authentication./, 7971cb0ef41Sopenharmony_ci 'should throw invalid 2fa auth url error' 7981cb0ef41Sopenharmony_ci ) 7991cb0ef41Sopenharmony_ci }) 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ci t.test('from token auth provides --otp config arg', async t => { 8021cb0ef41Sopenharmony_ci const npmProfile = { 8031cb0ef41Sopenharmony_ci async get () { 8041cb0ef41Sopenharmony_ci return userProfile 8051cb0ef41Sopenharmony_ci }, 8061cb0ef41Sopenharmony_ci async set (newProfile, conf) { 8071cb0ef41Sopenharmony_ci return { 8081cb0ef41Sopenharmony_ci ...userProfile, 8091cb0ef41Sopenharmony_ci tfa: null, 8101cb0ef41Sopenharmony_ci } 8111cb0ef41Sopenharmony_ci }, 8121cb0ef41Sopenharmony_ci } 8131cb0ef41Sopenharmony_ci 8141cb0ef41Sopenharmony_ci const readUserInfo = { 8151cb0ef41Sopenharmony_ci async password () { 8161cb0ef41Sopenharmony_ci return 'password1234' 8171cb0ef41Sopenharmony_ci }, 8181cb0ef41Sopenharmony_ci async otp () { 8191cb0ef41Sopenharmony_ci throw new Error('should not ask for otp') 8201cb0ef41Sopenharmony_ci }, 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci 8231cb0ef41Sopenharmony_ci const { npm, profile, result } = await mockProfile(t, { 8241cb0ef41Sopenharmony_ci npmProfile, 8251cb0ef41Sopenharmony_ci readUserInfo, 8261cb0ef41Sopenharmony_ci config: { otp: '123456' }, 8271cb0ef41Sopenharmony_ci }) 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = reg => { 8301cb0ef41Sopenharmony_ci return { token: 'token' } 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci 8331cb0ef41Sopenharmony_ci await profile.exec(['enable-2fa', 'auth-and-writes']) 8341cb0ef41Sopenharmony_ci 8351cb0ef41Sopenharmony_ci t.equal( 8361cb0ef41Sopenharmony_ci result(), 8371cb0ef41Sopenharmony_ci 'Two factor authentication mode changed to: auth-and-writes', 8381cb0ef41Sopenharmony_ci 'should output success msg' 8391cb0ef41Sopenharmony_ci ) 8401cb0ef41Sopenharmony_ci }) 8411cb0ef41Sopenharmony_ci 8421cb0ef41Sopenharmony_ci t.test('missing tfa from user profile', async t => { 8431cb0ef41Sopenharmony_ci const npmProfile = { 8441cb0ef41Sopenharmony_ci async get () { 8451cb0ef41Sopenharmony_ci return { 8461cb0ef41Sopenharmony_ci ...userProfile, 8471cb0ef41Sopenharmony_ci tfa: undefined, 8481cb0ef41Sopenharmony_ci } 8491cb0ef41Sopenharmony_ci }, 8501cb0ef41Sopenharmony_ci async set (newProfile, conf) { 8511cb0ef41Sopenharmony_ci return { 8521cb0ef41Sopenharmony_ci ...userProfile, 8531cb0ef41Sopenharmony_ci tfa: null, 8541cb0ef41Sopenharmony_ci } 8551cb0ef41Sopenharmony_ci }, 8561cb0ef41Sopenharmony_ci } 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci const readUserInfo = { 8591cb0ef41Sopenharmony_ci async password () { 8601cb0ef41Sopenharmony_ci return 'password1234' 8611cb0ef41Sopenharmony_ci }, 8621cb0ef41Sopenharmony_ci async otp () { 8631cb0ef41Sopenharmony_ci return '123456' 8641cb0ef41Sopenharmony_ci }, 8651cb0ef41Sopenharmony_ci } 8661cb0ef41Sopenharmony_ci 8671cb0ef41Sopenharmony_ci const { npm, profile, result } = await mockProfile(t, { 8681cb0ef41Sopenharmony_ci npmProfile, 8691cb0ef41Sopenharmony_ci readUserInfo, 8701cb0ef41Sopenharmony_ci }) 8711cb0ef41Sopenharmony_ci 8721cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = reg => { 8731cb0ef41Sopenharmony_ci return { token: 'token' } 8741cb0ef41Sopenharmony_ci } 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_ci await profile.exec(['enable-2fa', 'auth-only']) 8771cb0ef41Sopenharmony_ci 8781cb0ef41Sopenharmony_ci t.equal( 8791cb0ef41Sopenharmony_ci result(), 8801cb0ef41Sopenharmony_ci 'Two factor authentication mode changed to: auth-only', 8811cb0ef41Sopenharmony_ci 'should output success msg' 8821cb0ef41Sopenharmony_ci ) 8831cb0ef41Sopenharmony_ci }) 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ci t.test('defaults to auth-and-writes permission if no mode specified', async t => { 8861cb0ef41Sopenharmony_ci const npmProfile = { 8871cb0ef41Sopenharmony_ci async get () { 8881cb0ef41Sopenharmony_ci return { 8891cb0ef41Sopenharmony_ci ...userProfile, 8901cb0ef41Sopenharmony_ci tfa: undefined, 8911cb0ef41Sopenharmony_ci } 8921cb0ef41Sopenharmony_ci }, 8931cb0ef41Sopenharmony_ci async set (newProfile, conf) { 8941cb0ef41Sopenharmony_ci return { 8951cb0ef41Sopenharmony_ci ...userProfile, 8961cb0ef41Sopenharmony_ci tfa: null, 8971cb0ef41Sopenharmony_ci } 8981cb0ef41Sopenharmony_ci }, 8991cb0ef41Sopenharmony_ci } 9001cb0ef41Sopenharmony_ci 9011cb0ef41Sopenharmony_ci const readUserInfo = { 9021cb0ef41Sopenharmony_ci async password () { 9031cb0ef41Sopenharmony_ci return 'password1234' 9041cb0ef41Sopenharmony_ci }, 9051cb0ef41Sopenharmony_ci async otp () { 9061cb0ef41Sopenharmony_ci return '123456' 9071cb0ef41Sopenharmony_ci }, 9081cb0ef41Sopenharmony_ci } 9091cb0ef41Sopenharmony_ci 9101cb0ef41Sopenharmony_ci const { npm, profile, result } = await mockProfile(t, { 9111cb0ef41Sopenharmony_ci npmProfile, 9121cb0ef41Sopenharmony_ci readUserInfo, 9131cb0ef41Sopenharmony_ci }) 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_ci npm.config.getCredentialsByURI = reg => { 9161cb0ef41Sopenharmony_ci return { token: 'token' } 9171cb0ef41Sopenharmony_ci } 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_ci await profile.exec(['enable-2fa']) 9201cb0ef41Sopenharmony_ci t.equal( 9211cb0ef41Sopenharmony_ci result(), 9221cb0ef41Sopenharmony_ci 'Two factor authentication mode changed to: auth-and-writes', 9231cb0ef41Sopenharmony_ci 'should enable 2fa with auth-and-writes permission' 9241cb0ef41Sopenharmony_ci ) 9251cb0ef41Sopenharmony_ci }) 9261cb0ef41Sopenharmony_ci}) 9271cb0ef41Sopenharmony_ci 9281cb0ef41Sopenharmony_cit.test('disable-2fa', async t => { 9291cb0ef41Sopenharmony_ci t.test('no tfa enabled', async t => { 9301cb0ef41Sopenharmony_ci const npmProfile = { 9311cb0ef41Sopenharmony_ci async get () { 9321cb0ef41Sopenharmony_ci return { 9331cb0ef41Sopenharmony_ci ...userProfile, 9341cb0ef41Sopenharmony_ci tfa: null, 9351cb0ef41Sopenharmony_ci } 9361cb0ef41Sopenharmony_ci }, 9371cb0ef41Sopenharmony_ci } 9381cb0ef41Sopenharmony_ci 9391cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 9401cb0ef41Sopenharmony_ci npmProfile, 9411cb0ef41Sopenharmony_ci }) 9421cb0ef41Sopenharmony_ci 9431cb0ef41Sopenharmony_ci await profile.exec(['disable-2fa']) 9441cb0ef41Sopenharmony_ci t.equal(result(), 'Two factor authentication not enabled.', 9451cb0ef41Sopenharmony_ci 'should output already disalbed msg') 9461cb0ef41Sopenharmony_ci }) 9471cb0ef41Sopenharmony_ci 9481cb0ef41Sopenharmony_ci t.test('requests otp', async t => { 9491cb0ef41Sopenharmony_ci const npmProfile = t => ({ 9501cb0ef41Sopenharmony_ci async get () { 9511cb0ef41Sopenharmony_ci return userProfile 9521cb0ef41Sopenharmony_ci }, 9531cb0ef41Sopenharmony_ci async set (newProfile, conf) { 9541cb0ef41Sopenharmony_ci t.same( 9551cb0ef41Sopenharmony_ci newProfile, 9561cb0ef41Sopenharmony_ci { 9571cb0ef41Sopenharmony_ci tfa: { 9581cb0ef41Sopenharmony_ci password: 'password1234', 9591cb0ef41Sopenharmony_ci mode: 'disable', 9601cb0ef41Sopenharmony_ci }, 9611cb0ef41Sopenharmony_ci }, 9621cb0ef41Sopenharmony_ci 'should send the new info for setting in profile' 9631cb0ef41Sopenharmony_ci ) 9641cb0ef41Sopenharmony_ci }, 9651cb0ef41Sopenharmony_ci }) 9661cb0ef41Sopenharmony_ci 9671cb0ef41Sopenharmony_ci const readUserInfo = t => ({ 9681cb0ef41Sopenharmony_ci async password () { 9691cb0ef41Sopenharmony_ci t.ok('should interactively ask for password confirmation') 9701cb0ef41Sopenharmony_ci return 'password1234' 9711cb0ef41Sopenharmony_ci }, 9721cb0ef41Sopenharmony_ci async otp (label) { 9731cb0ef41Sopenharmony_ci t.equal( 9741cb0ef41Sopenharmony_ci label, 9751cb0ef41Sopenharmony_ci 'Enter one-time password: ', 9761cb0ef41Sopenharmony_ci 'should ask for otp confirmation' 9771cb0ef41Sopenharmony_ci ) 9781cb0ef41Sopenharmony_ci return '1234' 9791cb0ef41Sopenharmony_ci }, 9801cb0ef41Sopenharmony_ci }) 9811cb0ef41Sopenharmony_ci 9821cb0ef41Sopenharmony_ci t.test('default output', async t => { 9831cb0ef41Sopenharmony_ci t.plan(4) 9841cb0ef41Sopenharmony_ci 9851cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 9861cb0ef41Sopenharmony_ci npmProfile: npmProfile(t), 9871cb0ef41Sopenharmony_ci readUserInfo: readUserInfo(t), 9881cb0ef41Sopenharmony_ci }) 9891cb0ef41Sopenharmony_ci 9901cb0ef41Sopenharmony_ci await profile.exec(['disable-2fa']) 9911cb0ef41Sopenharmony_ci t.equal(result(), 'Two factor authentication disabled.', 'should output already disabled msg') 9921cb0ef41Sopenharmony_ci }) 9931cb0ef41Sopenharmony_ci 9941cb0ef41Sopenharmony_ci t.test('--json', async t => { 9951cb0ef41Sopenharmony_ci t.plan(4) 9961cb0ef41Sopenharmony_ci 9971cb0ef41Sopenharmony_ci const config = { json: true } 9981cb0ef41Sopenharmony_ci 9991cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 10001cb0ef41Sopenharmony_ci npmProfile: npmProfile(t), 10011cb0ef41Sopenharmony_ci readUserInfo: readUserInfo(t), 10021cb0ef41Sopenharmony_ci config, 10031cb0ef41Sopenharmony_ci }) 10041cb0ef41Sopenharmony_ci 10051cb0ef41Sopenharmony_ci await profile.exec(['disable-2fa']) 10061cb0ef41Sopenharmony_ci 10071cb0ef41Sopenharmony_ci t.same(JSON.parse(result()), { tfa: false }, 'should output json already disabled msg') 10081cb0ef41Sopenharmony_ci }) 10091cb0ef41Sopenharmony_ci 10101cb0ef41Sopenharmony_ci t.test('--parseable', async t => { 10111cb0ef41Sopenharmony_ci t.plan(4) 10121cb0ef41Sopenharmony_ci 10131cb0ef41Sopenharmony_ci const config = { parseable: true } 10141cb0ef41Sopenharmony_ci 10151cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 10161cb0ef41Sopenharmony_ci npmProfile: npmProfile(t), 10171cb0ef41Sopenharmony_ci readUserInfo: readUserInfo(t), 10181cb0ef41Sopenharmony_ci config, 10191cb0ef41Sopenharmony_ci }) 10201cb0ef41Sopenharmony_ci 10211cb0ef41Sopenharmony_ci await profile.exec(['disable-2fa']) 10221cb0ef41Sopenharmony_ci 10231cb0ef41Sopenharmony_ci t.equal(result(), 'tfa\tfalse', 'should output parseable already disabled msg') 10241cb0ef41Sopenharmony_ci }) 10251cb0ef41Sopenharmony_ci }) 10261cb0ef41Sopenharmony_ci 10271cb0ef41Sopenharmony_ci t.test('--otp config already set', async t => { 10281cb0ef41Sopenharmony_ci t.plan(2) 10291cb0ef41Sopenharmony_ci 10301cb0ef41Sopenharmony_ci const npmProfile = { 10311cb0ef41Sopenharmony_ci async get () { 10321cb0ef41Sopenharmony_ci return userProfile 10331cb0ef41Sopenharmony_ci }, 10341cb0ef41Sopenharmony_ci async set (newProfile, conf) { 10351cb0ef41Sopenharmony_ci t.same( 10361cb0ef41Sopenharmony_ci newProfile, 10371cb0ef41Sopenharmony_ci { 10381cb0ef41Sopenharmony_ci tfa: { 10391cb0ef41Sopenharmony_ci password: 'password1234', 10401cb0ef41Sopenharmony_ci mode: 'disable', 10411cb0ef41Sopenharmony_ci }, 10421cb0ef41Sopenharmony_ci }, 10431cb0ef41Sopenharmony_ci 'should send the new info for setting in profile' 10441cb0ef41Sopenharmony_ci ) 10451cb0ef41Sopenharmony_ci }, 10461cb0ef41Sopenharmony_ci } 10471cb0ef41Sopenharmony_ci 10481cb0ef41Sopenharmony_ci const readUserInfo = { 10491cb0ef41Sopenharmony_ci async password () { 10501cb0ef41Sopenharmony_ci return 'password1234' 10511cb0ef41Sopenharmony_ci }, 10521cb0ef41Sopenharmony_ci async otp (label) { 10531cb0ef41Sopenharmony_ci throw new Error('should not ask for otp') 10541cb0ef41Sopenharmony_ci }, 10551cb0ef41Sopenharmony_ci } 10561cb0ef41Sopenharmony_ci 10571cb0ef41Sopenharmony_ci const { profile, result } = await mockProfile(t, { 10581cb0ef41Sopenharmony_ci npmProfile, 10591cb0ef41Sopenharmony_ci readUserInfo, 10601cb0ef41Sopenharmony_ci config: { otp: '123456' }, 10611cb0ef41Sopenharmony_ci }) 10621cb0ef41Sopenharmony_ci 10631cb0ef41Sopenharmony_ci await profile.exec(['disable-2fa']) 10641cb0ef41Sopenharmony_ci 10651cb0ef41Sopenharmony_ci t.equal(result(), 'Two factor authentication disabled.', 'should output already disalbed msg') 10661cb0ef41Sopenharmony_ci }) 10671cb0ef41Sopenharmony_ci}) 10681cb0ef41Sopenharmony_ci 10691cb0ef41Sopenharmony_cit.test('unknown subcommand', async t => { 10701cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 10711cb0ef41Sopenharmony_ci 10721cb0ef41Sopenharmony_ci await t.rejects( 10731cb0ef41Sopenharmony_ci profile.exec(['asfd']), 10741cb0ef41Sopenharmony_ci /Unknown profile command: asfd/, 10751cb0ef41Sopenharmony_ci 'should throw unknown cmd error' 10761cb0ef41Sopenharmony_ci ) 10771cb0ef41Sopenharmony_ci}) 10781cb0ef41Sopenharmony_ci 10791cb0ef41Sopenharmony_cit.test('completion', async t => { 10801cb0ef41Sopenharmony_ci const testComp = async (t, { argv, expect, title } = {}) => { 10811cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 10821cb0ef41Sopenharmony_ci t.resolveMatch(profile.completion({ conf: { argv: { remain: argv } } }), expect, title) 10831cb0ef41Sopenharmony_ci } 10841cb0ef41Sopenharmony_ci 10851cb0ef41Sopenharmony_ci t.test('npm profile autocomplete', async t => { 10861cb0ef41Sopenharmony_ci await testComp(t, { 10871cb0ef41Sopenharmony_ci argv: ['npm', 'profile'], 10881cb0ef41Sopenharmony_ci expect: ['enable-2fa', 'disable-2fa', 'get', 'set'], 10891cb0ef41Sopenharmony_ci title: 'should auto complete with subcommands', 10901cb0ef41Sopenharmony_ci }) 10911cb0ef41Sopenharmony_ci }) 10921cb0ef41Sopenharmony_ci 10931cb0ef41Sopenharmony_ci t.test('npm profile enable autocomplete', async t => { 10941cb0ef41Sopenharmony_ci await testComp(t, { 10951cb0ef41Sopenharmony_ci argv: ['npm', 'profile', 'enable-2fa'], 10961cb0ef41Sopenharmony_ci expect: ['auth-and-writes', 'auth-only'], 10971cb0ef41Sopenharmony_ci title: 'should auto complete with auth types', 10981cb0ef41Sopenharmony_ci }) 10991cb0ef41Sopenharmony_ci }) 11001cb0ef41Sopenharmony_ci 11011cb0ef41Sopenharmony_ci t.test('npm profile <subcmd> no autocomplete', async t => { 11021cb0ef41Sopenharmony_ci const noAutocompleteCmds = ['disable-2fa', 'disable-tfa', 'get', 'set'] 11031cb0ef41Sopenharmony_ci for (const subcmd of noAutocompleteCmds) { 11041cb0ef41Sopenharmony_ci await t.test(subcmd, t => testComp(t, { 11051cb0ef41Sopenharmony_ci argv: ['npm', 'profile', subcmd], 11061cb0ef41Sopenharmony_ci expect: [], 11071cb0ef41Sopenharmony_ci title: `${subcmd} should have no autocomplete`, 11081cb0ef41Sopenharmony_ci })) 11091cb0ef41Sopenharmony_ci } 11101cb0ef41Sopenharmony_ci }) 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci t.test('npm profile unknown subcommand autocomplete', async t => { 11131cb0ef41Sopenharmony_ci const { profile } = await mockProfile(t) 11141cb0ef41Sopenharmony_ci t.rejects( 11151cb0ef41Sopenharmony_ci profile.completion({ conf: { argv: { remain: ['npm', 'profile', 'asdf'] } } }), 11161cb0ef41Sopenharmony_ci { message: 'asdf not recognized' }, 11171cb0ef41Sopenharmony_ci 'should throw unknown cmd error' 11181cb0ef41Sopenharmony_ci ) 11191cb0ef41Sopenharmony_ci }) 11201cb0ef41Sopenharmony_ci}) 1121