@@ -13,6 +13,8 @@ const internalHost = require('./host');
13
13
const letsencryptStaging = process . env . NODE_ENV !== 'production' ;
14
14
const letsencryptConfig = '/etc/letsencrypt.ini' ;
15
15
const certbotCommand = 'certbot' ;
16
+ const archiver = require ( 'archiver' ) ;
17
+ const path = require ( 'path' ) ;
16
18
17
19
function omissions ( ) {
18
20
return [ 'is_deleted' ] ;
@@ -335,6 +337,71 @@ const internalCertificate = {
335
337
} ) ;
336
338
} ,
337
339
340
+ /**
341
+ * @param {Access } access
342
+ * @param {Object } data
343
+ * @param {Number } data.id
344
+ * @returns {Promise }
345
+ */
346
+ download : ( access , data ) => {
347
+ return new Promise ( ( resolve , reject ) => {
348
+ access . can ( 'certificates:get' , data )
349
+ . then ( ( ) => {
350
+ return internalCertificate . get ( access , data ) ;
351
+ } )
352
+ . then ( ( certificate ) => {
353
+ if ( certificate . provider === 'letsencrypt' ) {
354
+ const zipDirectory = '/etc/letsencrypt/live/npm-' + data . id ;
355
+
356
+ if ( ! fs . existsSync ( zipDirectory ) ) {
357
+ throw new error . ItemNotFoundError ( 'Certificate ' + certificate . nice_name + ' does not exists' ) ;
358
+ }
359
+
360
+ let certFiles = fs . readdirSync ( zipDirectory )
361
+ . filter ( ( fn ) => fn . endsWith ( '.pem' ) )
362
+ . map ( ( fn ) => fs . realpathSync ( path . join ( zipDirectory , fn ) ) ) ;
363
+ const downloadName = 'npm-' + data . id + '-' + `${ Date . now ( ) } .zip` ;
364
+ const opName = '/tmp/' + downloadName ;
365
+ internalCertificate . zipFiles ( certFiles , opName )
366
+ . then ( ( ) => {
367
+ logger . debug ( 'zip completed : ' , opName ) ;
368
+ const resp = {
369
+ fileName : opName
370
+ } ;
371
+ resolve ( resp ) ;
372
+ } ) . catch ( ( err ) => reject ( err ) ) ;
373
+ } else {
374
+ throw new error . ValidationError ( 'Only Let\'sEncrypt certificates can be downloaded' ) ;
375
+ }
376
+ } ) . catch ( ( err ) => reject ( err ) ) ;
377
+ } ) ;
378
+ } ,
379
+
380
+ /**
381
+ * @param {String } source
382
+ * @param {String } out
383
+ * @returns {Promise }
384
+ */
385
+ zipFiles ( source , out ) {
386
+ const archive = archiver ( 'zip' , { zlib : { level : 9 } } ) ;
387
+ const stream = fs . createWriteStream ( out ) ;
388
+
389
+ return new Promise ( ( resolve , reject ) => {
390
+ source
391
+ . map ( ( fl ) => {
392
+ let fileName = path . basename ( fl ) ;
393
+ logger . debug ( fl , 'added to certificate zip' ) ;
394
+ archive . file ( fl , { name : fileName } ) ;
395
+ } ) ;
396
+ archive
397
+ . on ( 'error' , ( err ) => reject ( err ) )
398
+ . pipe ( stream ) ;
399
+
400
+ stream . on ( 'close' , ( ) => resolve ( ) ) ;
401
+ archive . finalize ( ) ;
402
+ } ) ;
403
+ } ,
404
+
338
405
/**
339
406
* @param {Access } access
340
407
* @param {Object } data
0 commit comments