Files
itworx-knowledge-hub-Public/src/backend/ItWorx.KnowledgeHub.Application/Operations/UseCases/CreateBackupUseCase.cs
T

60 lines
2.5 KiB
C#

using ItWorx.KnowledgeHub.Application.Audit;
namespace ItWorx.KnowledgeHub.Application.Operations.UseCases;
public sealed record CreateBackupCommand(Guid ActorId, string? CorrelationId);
/// <summary>Administrator-triggered full backup (docs/18-backup-restore.md). Records
/// an audit event on both success and failure — a failed backup is itself an
/// operationally significant event (docs/19-observability.md "repeated backup
/// failure" alert).</summary>
public sealed class CreateBackupUseCase(IBackupService backups, IAuditEventRecorder auditEvents, TimeProvider timeProvider, PlatformMetrics? metrics = null)
{
public async Task<BackupSummary> ExecuteAsync(CreateBackupCommand command, CancellationToken cancellationToken)
{
using var measurement = metrics?.Start("backup");
var now = timeProvider.GetUtcNow();
try
{
var summary = await backups.CreateBackupAsync(cancellationToken);
await auditEvents.RecordAsync(
new AuditEventRecord(
AuditActorKind.User,
command.ActorId,
Source: "web",
Action: "backup.created",
TargetType: "backup",
TargetId: summary.BackupId,
Summary: $"Back-up '{summary.BackupId}' aangemaakt ({summary.TableCount} tabellen, {summary.AttachmentCount} bijlagen).",
command.CorrelationId,
now),
cancellationToken);
measurement?.Complete(summary.AttachmentCount);
return summary;
}
catch (Exception exception) when (exception is not OperationCanceledException)
{
await auditEvents.RecordAsync(
new AuditEventRecord(
AuditActorKind.User,
command.ActorId,
Source: "web",
Action: "backup.failed",
TargetType: null,
TargetId: null,
// Exception messages from a controlled backup pipeline never carry
// secrets/connection strings (docs/19-observability.md "Never log
// ... connection strings"); the message itself is safe operator
// diagnostic text, not raw exception detail from user input.
Summary: $"Back-up mislukt: {exception.GetType().Name}.",
command.CorrelationId,
now),
cancellationToken);
throw;
}
}
}