@@ -6,12 +6,14 @@ const fetch = require('npm-registry-fetch')
66const localeCompare = require ( '@isaacs/string-locale-compare' ) ( 'en' )
77const npa = require ( 'npm-package-arg' )
88const pacote = require ( 'pacote' )
9- const pickManifest = require ( 'npm-pick-manifest' )
10- const table = require ( 'text-table' )
9+ // const pickManifest = require('npm-pick-manifest')
1110
1211const ArboristWorkspaceCmd = require ( '../arborist-cmd.js' )
13- const ansiTrim = require ( '../utils/ansi-trim.js' )
1412const auditError = require ( '../utils/audit-error.js' )
13+ const {
14+ registry : { default : defaultRegistry } ,
15+ } = require ( '../utils/config/definitions.js' )
16+ // const log = require('../utils/log-shim.js')
1517const reifyFinish = require ( '../utils/reify-finish.js' )
1618
1719const validateSignature = async ( { message, signature, publicKey } ) => {
@@ -37,27 +39,26 @@ class VerifySignatures {
3739 }
3840
3941 async run ( ) {
42+ const start = process . hrtime . bigint ( )
43+
4044 // Find all deps in tree
4145 const nodes = this . tree . inventory . values ( )
4246 this . getEdges ( nodes , 'edgesOut' )
43-
4447 const edges = Array . from ( this . edges )
45- const start = process . hrtime . bigint ( )
46- const registries = this . findAllRegistryUrls ( edges , this . npm . flatOptions )
4748
48- // Prefetch and cache public keys from the used registries
49+ // QUESTION: Do we need to get the registry host from the resolved url to handle proxies?
50+ // Prefetch and cache public keys from used registries
51+ const registries = this . findAllRegistryUrls ( edges , this . npm . flatOptions )
4952 for ( const registry of registries ) {
5053 const keys = await this . getKeys ( { registry } )
5154 if ( keys ) {
5255 this . keys . set ( registry , keys )
5356 }
5457 }
55- await Promise . all ( edges . map ( ( edge ) => this . getVerifiedInfo ( edge ) ) )
5658
57- const end = process . hrtime . bigint ( )
58- const elapsed = end - start
59+ await Promise . all ( edges . map ( ( edge ) => this . getVerifiedInfo ( edge ) ) )
5960
60- // sort alphabetically
61+ // Sort alphabetically
6162 const invalid = Array . from ( this . invalid ) . sort ( ( a , b ) => localeCompare ( a . name , b . name ) )
6263 const missing = Array . from ( this . missing ) . sort ( ( a , b ) => localeCompare ( a . name , b . name ) )
6364
@@ -67,13 +68,20 @@ class VerifySignatures {
6768 this . exitCode = 1
6869 }
6970
71+ const end = process . hrtime . bigint ( )
72+ const elapsed = end - start
73+
7074 if ( this . npm . config . get ( 'json' ) ) {
7175 this . appendOutput ( this . makeJSON ( { invalid, missing } ) )
7276 } else {
7377 const timing = `audited ${ edges . length } packages in ${ Math . floor ( Number ( elapsed ) / 1e9 ) } s`
7478 const verifiedPrefix = verified ? 'verified signatures, ' : ''
7579 this . appendOutput ( `${ verifiedPrefix } ${ timing } \n` )
7680
81+ if ( this . verified && ! verified ) {
82+ this . appendOutput ( `${ this . verified } ${ chalk . bold ( 'verified' ) } packages\n` )
83+ }
84+
7785 if ( missing . length ) {
7886 const msg = missing . length === 1 ?
7987 `package has a ${ chalk . bold ( chalk . magenta ( 'missing' ) ) } registry signature` :
@@ -183,6 +191,7 @@ class VerifySignatures {
183191 }
184192 }
185193
194+ // TODO: Remove this once we can get time from pacote.manifest
186195 async getPackument ( spec ) {
187196 const packument = await pacote . packument ( spec , {
188197 ...this . npm . flatOptions ,
@@ -218,6 +227,7 @@ class VerifySignatures {
218227 const node = edge . to || edge
219228 const { path, location } = node
220229 const { version } = node . package || { }
230+ // QUESTION: Do we need to handle `latest`?
221231 if ( ! version ) {
222232 return
223233 }
@@ -232,51 +242,56 @@ class VerifySignatures {
232242 }
233243 }
234244
245+ // QUESTION: Confirm, is this the right thing to do here?
246+ //
235247 // deps different from prod not currently
236248 // on disk are not included in the output
237249 if ( edge . error === 'MISSING' && type !== 'dependencies' ) {
238250 return
239251 }
240252
253+ // QUESTION: Confirm, is this the right thing to do here?
254+ //
255+ // if it's not a range, version, or tag, skip it
241256 try {
242- const packument = await this . getPackument ( spec )
243- // if it's not a range, version, or tag, skip it
244- try {
245- if ( ! npa ( `${ edge . name } @${ edge . spec } ` ) . registry ) {
246- return null
247- }
248- } catch ( err ) {
257+ if ( ! npa ( `${ edge . name } @${ edge . spec } ` ) . registry ) {
249258 return null
250259 }
260+ } catch ( err ) {
261+ return null
262+ }
251263
264+ try {
252265 const name = alias ? edge . spec . replace ( 'npm' , edge . name ) : edge . name
253- const { homepage } = packument
254-
266+ // QUESTION: Is name @version the right way to get the manifest?
267+ const manifest = await pacote . manifest ( ` ${ name } @ ${ version } ` , this . npm . flatOptions )
255268 const registry = fetch . pickRegistry ( spec , this . npm . flatOptions )
256269
257- const versionPackument = pickManifest ( packument , version , this . npm . flatOptions )
258- const versionCreated = packument . time && packument . time [ version ]
259- const dist = versionPackument . dist || { }
260- const { integrity } = dist
270+ const { _integrity : integrity , _signatures } = manifest
261271 const message = `${ name } @${ version } :${ integrity } `
262- const signatures = dist . signatures || [ ]
272+ const signatures = _signatures || [ ]
273+
274+ // TODO: Get version created time from manifest
275+ //
276+ // const packument = await this.getPackument(spec)
277+ // const versionCreated = packument.time && packument.time[version]
263278 const keys = this . keys . get ( registry ) || [ ]
264279 const validKeys = keys . filter ( ( publicKey ) => {
265280 if ( ! publicKey . expires ) {
266281 return true
267282 }
268- return Date . parse ( versionCreated ) < Date . parse ( publicKey . expires )
283+ // return Date.parse(versionCreated) < Date.parse(publicKey.expires)
284+ return Date . parse ( publicKey . expires ) > Date . now ( )
269285 } )
270286
271287 // Currently we only care about missing signatures on registries that provide a public key
272- // Note: we could make this configurable in the future with a strict/paranoid mode
288+ // We could make this configurable in the future with a strict/paranoid mode
273289 if ( ! signatures . length && validKeys . length ) {
274290 this . missing . add ( {
275291 name,
276292 path,
277293 version,
278294 location,
279- homepage,
280295 registry,
281296 } )
282297
@@ -313,7 +328,6 @@ class VerifySignatures {
313328 type,
314329 version,
315330 location,
316- homepage,
317331 registry,
318332 integrity,
319333 signature : signature . sig ,
@@ -324,6 +338,8 @@ class VerifySignatures {
324338 }
325339 } ) )
326340 } catch ( err ) {
341+ // QUESTION: Is this the right way to handle these errors?
342+ //
327343 // silently catch and ignore ETARGET, E403 &
328344 // E404 errors, deps are just skipped
329345 if ( ! (
@@ -337,52 +353,18 @@ class VerifySignatures {
337353 }
338354
339355 humanOutput ( list ) {
340- const invalidList = list . map ( x => this . makePretty ( x ) )
341- const outHead = [ 'Package' ,
342- 'Version' ,
343- 'Location' ,
344- 'Registry' ,
345- ]
346-
347- if ( this . npm . config . get ( 'long' ) ) {
348- outHead [ 4 ] = 'Homepage'
349- }
350-
351- const outTable = [ outHead ] . concat ( invalidList )
352-
353- if ( this . npm . color ) {
354- outTable [ 0 ] = outTable [ 0 ] . map ( heading => chalk . underline ( heading ) )
355- }
356-
357- const tableOpts = {
358- align : [ 'l' , 'r' , 'r' , 'r' , 'l' ] ,
359- stringLength : s => ansiTrim ( s ) . length ,
360- }
361-
362- return table ( outTable , tableOpts )
363- }
364-
365- // formatting functions
366- makePretty ( dep ) {
367- const {
368- version = 'MISSING' ,
369- homepage = '' ,
370- name,
371- location,
372- registry,
373- } = dep
374-
375- const columns = [ name , version , location , registry ]
376-
377- if ( this . npm . config . get ( 'long' ) ) {
378- columns [ 4 ] = homepage
379- }
380-
381- if ( this . npm . color ) {
382- columns [ 0 ] = chalk . red ( columns [ 0 ] )
383- }
356+ const uniquePackages = Array . from ( list . reduce ( ( set , v ) => {
357+ let nameVersion = `${ v . name } @${ v . version } `
358+ if ( this . npm . color ) {
359+ nameVersion = chalk . red ( nameVersion )
360+ }
361+ const registry = v . registry
362+ const suffix = registry !== defaultRegistry ? ` (${ registry } )` : ''
363+ set . add ( `${ nameVersion } ${ suffix } ` )
364+ return set
365+ } , new Set ( ) ) )
384366
385- return columns
367+ return uniquePackages . join ( '\n' )
386368 }
387369
388370 makeJSON ( { invalid, missing } ) {
@@ -396,7 +378,6 @@ class VerifySignatures {
396378 integrity,
397379 signature,
398380 keyid,
399- homepage,
400381 } = dep
401382 out . invalid = out . invalid || { }
402383 out . invalid [ name ] = {
@@ -406,7 +387,6 @@ class VerifySignatures {
406387 signature,
407388 integrity,
408389 keyid,
409- homepage,
410390 }
411391 } )
412392 missing . forEach ( dep => {
@@ -415,14 +395,12 @@ class VerifySignatures {
415395 version,
416396 path,
417397 registry,
418- homepage,
419398 } = dep
420399 out . missing = out . invalid || { }
421400 out . missing [ name ] = {
422401 version,
423402 location : path ,
424403 registry,
425- homepage,
426404 }
427405 } )
428406 return JSON . stringify ( out , null , 2 )
0 commit comments