@@ -193,7 +193,7 @@ export class BackupService {
193
193
if ( this . configService . ui . scheduledBackupPath ) {
194
194
// If using a custom backup path, check it exists
195
195
if ( ! await pathExists ( this . configService . instanceBackupPath ) ) {
196
- throw new Error ( ` Custom instance backup path does not exist: ${ this . configService . instanceBackupPath } ` )
196
+ throw new Error ( ' Custom instance backup path does not exist' )
197
197
}
198
198
199
199
try {
@@ -308,47 +308,27 @@ export class BackupService {
308
308
* Downloads a scheduled backup .tar.gz
309
309
*/
310
310
async getScheduledBackup ( backupId : string ) : Promise < StreamableFile > {
311
- // Validate backupId to ensure it matches the expected pattern
312
- if ( ! / ^ [ 0 - 9 A - Z ] { 12 } \. \d { 9 , 15 } $ / i. test ( backupId ) ) {
313
- throw new NotFoundException ( )
314
- }
311
+ const backupPath = resolve ( this . configService . instanceBackupPath , `homebridge-backup-${ backupId } .tar.gz` )
315
312
316
- let backupPath = resolve ( this . configService . instanceBackupPath , `homebridge-backup-${ backupId } .tar.gz` )
317
- try {
318
- backupPath = await realpath ( backupPath )
319
- } catch ( e ) {
313
+ // Check the file exists
314
+ if ( ! await pathExists ( backupPath ) ) {
320
315
throw new NotFoundException ( )
321
316
}
322
317
323
- // Ensure the backupPath is within the instanceBackupPath
324
- if ( ! backupPath . startsWith ( this . configService . instanceBackupPath ) ) {
325
- throw new BadRequestException ( `Invalid backup path: ${ backupPath } does not start with ${ this . configService . instanceBackupPath } ` )
326
- }
327
-
328
318
return new StreamableFile ( createReadStream ( backupPath ) )
329
319
}
330
320
331
321
/**
332
322
* Removes a scheduled backup .tar.gz
333
323
*/
334
324
async deleteScheduledBackup ( backupId : string ) : Promise < void > {
335
- // Validate backupId to ensure it matches the expected pattern
336
- if ( ! / ^ [ 0 - 9 A - Z ] { 12 } \. \d { 9 , 15 } $ / i. test ( backupId ) ) {
337
- throw new NotFoundException ( )
338
- }
325
+ const backupPath = resolve ( this . configService . instanceBackupPath , `homebridge-backup-${ backupId } .tar.gz` )
339
326
340
- let backupPath = resolve ( this . configService . instanceBackupPath , `homebridge-backup-${ backupId } .tar.gz` )
341
- try {
342
- backupPath = await realpath ( backupPath )
343
- } catch ( e ) {
327
+ // Check the file exists
328
+ if ( ! await pathExists ( backupPath ) ) {
344
329
throw new NotFoundException ( )
345
330
}
346
331
347
- // Ensure the backupPath is within the instanceBackupPath
348
- if ( ! backupPath . startsWith ( this . configService . instanceBackupPath ) ) {
349
- throw new BadRequestException ( `Invalid backup path: ${ backupPath } does not start with ${ this . configService . instanceBackupPath } ` )
350
- }
351
-
352
332
try {
353
333
await remove ( backupPath )
354
334
this . logger . warn ( `Scheduled backup ${ backupId } deleted by request.` )
@@ -362,23 +342,13 @@ export class BackupService {
362
342
* Restore a scheduled backup .tar.gz
363
343
*/
364
344
async restoreScheduledBackup ( backupId : string ) : Promise < void > {
365
- // Validate backupId to ensure it matches the expected pattern
366
- if ( ! / ^ [ 0 - 9 A - Z ] { 12 } \. \d { 9 , 15 } $ / i. test ( backupId ) ) {
367
- throw new NotFoundException ( )
368
- }
345
+ const backupPath = resolve ( this . configService . instanceBackupPath , `homebridge-backup-${ backupId } .tar.gz` )
369
346
370
- let backupPath = resolve ( this . configService . instanceBackupPath , `homebridge-backup-${ backupId } .tar.gz` )
371
- try {
372
- backupPath = await realpath ( backupPath )
373
- } catch ( e ) {
347
+ // Check the file exists
348
+ if ( ! await pathExists ( backupPath ) ) {
374
349
throw new NotFoundException ( )
375
350
}
376
351
377
- // Ensure the backupPath is within the instanceBackupPath
378
- if ( ! backupPath . startsWith ( this . configService . instanceBackupPath ) ) {
379
- throw new BadRequestException ( `Invalid backup path: ${ backupPath } does not start with ${ this . configService . instanceBackupPath } ` )
380
- }
381
-
382
352
// Clear restore directory
383
353
this . restoreDirectory = undefined
384
354
@@ -393,18 +363,18 @@ export class BackupService {
393
363
this . restoreDirectory = restoreDir
394
364
}
395
365
396
- // Remove temp files (called when download finished)
397
- async cleanup ( backupDir : string ) {
398
- await remove ( resolve ( backupDir ) )
399
- this . logger . log ( `Backup complete, removing ${ backupDir } .` )
400
- }
401
-
402
366
/**
403
367
* Create and download backup archive of the current homebridge instance
404
368
*/
405
369
async downloadBackup ( reply : FastifyReply ) : Promise < StreamableFile > {
406
370
const { backupDir, backupPath, backupFileName } = await this . createBackup ( )
407
371
372
+ // Remove temp files (called when download finished)
373
+ async function cleanup ( ) {
374
+ await remove ( resolve ( backupDir ) )
375
+ this . logger . log ( `Backup complete, removing ${ backupDir } .` )
376
+ }
377
+
408
378
// Set download headers
409
379
reply . raw . setHeader ( 'Content-type' , 'application/octet-stream' )
410
380
reply . raw . setHeader ( 'Content-disposition' , `attachment; filename=${ backupFileName } ` )
@@ -415,10 +385,7 @@ export class BackupService {
415
385
reply . raw . setHeader ( 'access-control-allow-origin' , 'http://localhost:4200' )
416
386
}
417
387
418
- // Remove temp files (called when download finished)
419
- const cleanup = this . cleanup . bind ( this , backupDir )
420
-
421
- return new StreamableFile ( createReadStream ( backupPath ) . on ( 'close' , cleanup ) )
388
+ return new StreamableFile ( createReadStream ( backupPath ) . on ( 'close' , cleanup . bind ( this ) ) )
422
389
}
423
390
424
391
/**
0 commit comments