using MediatR; using mws.backend.dotnet.application.Audit; using mws.backend.dotnet.application.Common; using mws.backend.dotnet.application.Permissions; namespace mws.backend.dotnet.application.Documents; public record DeleteDocumentCommand(Guid UserId, Guid DocumentId) : IRequest, IAuditableRequest { public string Action => "Document.Delete"; public string EntityType => "Document"; public Guid? EntityId => DocumentId; } public class DeleteDocumentHandler(IUnitOfWork uow, IDocumentContentStore contentStore, IAuditContext auditContext) : IRequestHandler { public async Task Handle(DeleteDocumentCommand command, CancellationToken ct) { var doc = await DocumentAccess.GetDocumentForUserAsync(uow, command.UserId, command.DocumentId, ct); await DocumentAccess.EnsureDocumentPermissionAsync(uow, command.UserId, doc.ProjectId, PermissionAction.Delete, ct); var keys = new List(); await CollectDescendants(uow, command.DocumentId, keys, ct); if (!string.IsNullOrEmpty(doc.StorageKey)) { keys.Add(doc.StorageKey); } await DocumentAccess.DeleteDescendantsAsync(uow, command.DocumentId, ct); uow.Documents.Remove(doc); await uow.SaveChangesAsync(ct); auditContext.EntityName = doc.Title; foreach (var key in keys) { await contentStore.DeleteAsync(key, ct); } } private static async Task CollectDescendants( IUnitOfWork uow, Guid parentId, List keys, CancellationToken ct) { var children = await uow.Documents.GetChildrenAsync(parentId, ct); foreach (var child in children) { if (!string.IsNullOrEmpty(child.StorageKey)) { keys.Add(child.StorageKey); } await CollectDescendants(uow, child.Id, keys, ct); } } }