fix(backup): keep GUI backup paths under BACKUP_ROOT and limit the schedule
backup:configure could point automatic backups at any writable directory (e.g. a statically served one) and set a cron of every second; an invalid expression deleted the running job before failing, silently ending backups. - A path entered in the UI is resolved under BACKUP_ROOT (default ./backups) and refused if it leaves it; env values stay unrestricted. - The schedule must be a five-field cron that runs at most hourly. - reload() validates before replacing the running job. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
bd592adf66
commit
ebeb499a18
6 files changed
+148
-3
No files matched your search
@@ -3,6 +3,7 @@ import { PrismaService } from '../prisma/prisma.service';
|
||||
import { AuditLogService } from '../audit/audit-log.service';
|
||||
import { BackupSettings } from '../../generated/prisma';
|
||||
import { UpdateBackupSettingsDto } from './dto/update-backup-settings.dto';
|
||||
import { assertBackupCron, assertGuiBackupPath } from './backup-schedule-rules';
|
||||
|
||||
const SINGLETON_ID = 'singleton';
|
||||
|
||||
@@ -31,6 +32,12 @@ export class BackupSettingsService {
|
||||
dto: UpdateBackupSettingsDto,
|
||||
actingUserId: string,
|
||||
): Promise<BackupSettings> {
|
||||
if (dto.storagePath) {
|
||||
assertGuiBackupPath(dto.storagePath);
|
||||
}
|
||||
if (dto.cronSchedule) {
|
||||
assertBackupCron(dto.cronSchedule);
|
||||
}
|
||||
const before = await this.get();
|
||||
const settings = await this.prisma.backupSettings.update({
|
||||
where: { id: SINGLETON_ID },
|
||||
|
||||
Reference in new issue
Block a user