import { Injectable } from '@nestjs/common'; 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'; function emptyToNull(value: string | undefined): string | null { return value === '' ? null : (value ?? null); } @Injectable() export class BackupSettingsService { constructor( private readonly prisma: PrismaService, private readonly auditLog: AuditLogService, ) {} async get(): Promise { const existing = await this.prisma.backupSettings.findUnique({ where: { id: SINGLETON_ID }, }); if (existing) { return existing; } return this.prisma.backupSettings.create({ data: { id: SINGLETON_ID } }); } async update( dto: UpdateBackupSettingsDto, actingUserId: string, ): Promise { 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 }, data: { storagePath: dto.storagePath !== undefined ? emptyToNull(dto.storagePath) : undefined, cronSchedule: dto.cronSchedule !== undefined ? emptyToNull(dto.cronSchedule) : undefined, retentionCount: dto.retentionCount !== undefined ? dto.retentionCount : undefined, }, }); await this.auditLog.record({ entityType: 'BackupSettings', entityId: SINGLETON_ID, action: 'UPDATE', userId: actingUserId, beforeData: before, afterData: settings, }); return settings; } }