From c1384a50ebf31a1edf7f5e812ecdf4b72795e124 Mon Sep 17 00:00:00 2001 From: Roar Mjelde <36594318+Ceredron@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:34:09 +0200 Subject: [PATCH] ReadyForPublish should be set after virus scan (#212) * We should do the check for related correspondences related to an attachment being ready for publish after the virus scan when running remotely. * We can avoid having to inject so many dependencies in application handler by also injecting the helpers through DI and having their dependencies resolved automatically. * Correspondences with malware attachments should fail * Fix injection --- .../DependencyInjection.cs | 4 +++ .../Helpers/InitializeCorrespondenceHelper.cs | 19 ++++------ .../Helpers/UploadHelper.cs | 35 +++++++++++++------ .../InitializeCorrespondenceHandler.cs | 29 ++++++--------- ...nitializeMultipleCorrespondencesHandler.cs | 29 ++++++--------- .../MalwareScanResultHandler.cs | 9 +++-- .../UploadAttachmentHandler.cs | 5 ++- 7 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/Altinn.Correspondence.Application/DependencyInjection.cs b/src/Altinn.Correspondence.Application/DependencyInjection.cs index 26b44df1..8893850b 100644 --- a/src/Altinn.Correspondence.Application/DependencyInjection.cs +++ b/src/Altinn.Correspondence.Application/DependencyInjection.cs @@ -4,6 +4,7 @@ using Altinn.Correspondence.Application.GetCorrespondenceDetails; using Altinn.Correspondence.Application.GetCorrespondenceOverview; using Altinn.Correspondence.Application.GetCorrespondences; +using Altinn.Correspondence.Application.Helpers; using Altinn.Correspondence.Application.InitializeAttachment; using Altinn.Correspondence.Application.InitializeCorrespondence; using Altinn.Correspondence.Application.InitializeMultipleCorrespondences; @@ -35,5 +36,8 @@ public static void AddApplicationHandlers(this IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); } } diff --git a/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs b/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs index c75930b6..d7304c96 100644 --- a/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs +++ b/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs @@ -12,21 +12,15 @@ namespace Altinn.Correspondence.Application.Helpers { public class InitializeCorrespondenceHelper { - private readonly ICorrespondenceRepository _correspondenceRepository; - private readonly ICorrespondenceStatusRepository _correspondenceStatusRepository; - private readonly IAttachmentStatusRepository _attachmentStatusRepository; private readonly IAttachmentRepository _attachmentRepository; - private readonly IStorageRepository _storageRepository; private readonly IHostEnvironment _hostEnvironment; + private readonly UploadHelper _uploadHelper; - public InitializeCorrespondenceHelper(ICorrespondenceRepository correspondenceRepository, ICorrespondenceStatusRepository correspondenceStatusRepositor, IAttachmentStatusRepository attachmentStatusRepository, IAttachmentRepository attachmentRepository, IStorageRepository storageRepository, IHostEnvironment hostEnvironment) + public InitializeCorrespondenceHelper(IAttachmentRepository attachmentRepository, IHostEnvironment hostEnvironment, UploadHelper uploadHelper) { - _correspondenceRepository = correspondenceRepository; - _correspondenceStatusRepository = correspondenceStatusRepositor; - _attachmentStatusRepository = attachmentStatusRepository; _attachmentRepository = attachmentRepository; _hostEnvironment = hostEnvironment; - _storageRepository = storageRepository; + _uploadHelper = uploadHelper; } public Error? ValidateCorrespondenceContent(CorrespondenceContentEntity content) @@ -93,7 +87,6 @@ public CorrespondenceStatus GetInitializeCorrespondenceStatus(CorrespondenceEnti public async Task UploadAttachments(List correspondenceAttachments, List files, CancellationToken cancellationToken) { - UploadHelper uploadHelper = new UploadHelper(_correspondenceRepository, _correspondenceStatusRepository, _attachmentStatusRepository, _attachmentRepository, _storageRepository, _hostEnvironment); foreach (var file in files) { var attachment = correspondenceAttachments.FirstOrDefault(a => a.FileName.ToLower() == file.FileName.ToLower()); @@ -105,7 +98,7 @@ public CorrespondenceStatus GetInitializeCorrespondenceStatus(CorrespondenceEnti OneOf uploadResponse; await using (var f = file.OpenReadStream()) { - uploadResponse = await uploadHelper.UploadAttachment(f, attachment.Id, cancellationToken); + uploadResponse = await _uploadHelper.UploadAttachment(f, attachment.Id, cancellationToken); } var error = uploadResponse.Match( _ => { return null; }, @@ -116,9 +109,9 @@ public CorrespondenceStatus GetInitializeCorrespondenceStatus(CorrespondenceEnti return null; } - public async Task ProcessAttachment(CorrespondenceAttachmentEntity correspondenceAttachment, bool shouldSave, CancellationToken cancellationToken) + public async Task ProcessAttachment(CorrespondenceAttachmentEntity correspondenceAttachment, CancellationToken cancellationToken) { - if (!String.IsNullOrEmpty(correspondenceAttachment.Attachment?.DataLocationUrl)) + if (!string.IsNullOrEmpty(correspondenceAttachment.Attachment?.DataLocationUrl)) { var existingAttachment = await _attachmentRepository.GetAttachmentByUrl(correspondenceAttachment.Attachment.DataLocationUrl, cancellationToken); if (existingAttachment != null) diff --git a/src/Altinn.Correspondence.Application/Helpers/UploadHelper.cs b/src/Altinn.Correspondence.Application/Helpers/UploadHelper.cs index ec06f1be..6e1aa627 100644 --- a/src/Altinn.Correspondence.Application/Helpers/UploadHelper.cs +++ b/src/Altinn.Correspondence.Application/Helpers/UploadHelper.cs @@ -34,6 +34,7 @@ public async Task> UploadAttachment(Strea var attachment = await _attachmentRepository.GetAttachmentById(attachmentId, true, cancellationToken); if (attachment == null) { + return Errors.AttachmentNotFound; } var currentStatus = await SetAttachmentStatus(attachmentId, AttachmentStatus.UploadProcessing, cancellationToken); @@ -96,7 +97,7 @@ private async Task SetAttachmentStatus(Guid attachmentId await _attachmentStatusRepository.AddAttachmentStatus(currentStatus, cancellationToken); return currentStatus; } - public async Task CheckCorrespondenceStatusesAfterUploadAndPublish(Guid attachmentId, CancellationToken cancellationToken) + public async Task CheckCorrespondenceStatusesAfterUploadAndPublish(Guid attachmentId, bool uploadSuccessful, CancellationToken cancellationToken) { var attachment = await _attachmentRepository.GetAttachmentById(attachmentId, true, cancellationToken); if (attachment == null) @@ -113,15 +114,29 @@ public async Task CheckCorrespondenceStatusesAfterUploadAndPublish(Guid attachme var list = new List(); foreach (var correspondenceId in correspondences) { - list.Add( - new CorrespondenceStatusEntity - { - CorrespondenceId = correspondenceId, - Status = CorrespondenceStatus.ReadyForPublish, - StatusChanged = DateTime.UtcNow, - StatusText = CorrespondenceStatus.ReadyForPublish.ToString() - } - ); + if (uploadSuccessful) + { + list.Add( + new CorrespondenceStatusEntity + { + CorrespondenceId = correspondenceId, + Status = CorrespondenceStatus.ReadyForPublish, + StatusChanged = DateTime.UtcNow, + StatusText = CorrespondenceStatus.ReadyForPublish.ToString() + } + ); + } else + { + list.Add( + new CorrespondenceStatusEntity + { + CorrespondenceId = correspondenceId, + Status = CorrespondenceStatus.Failed, + StatusChanged = DateTime.UtcNow, + StatusText = "Malware scan failed" + } + ); + } } await _correspondenceStatusRepository.AddCorrespondenceStatuses(list, cancellationToken); return; diff --git a/src/Altinn.Correspondence.Application/InitializeCorrespondence/InitializeCorrespondenceHandler.cs b/src/Altinn.Correspondence.Application/InitializeCorrespondence/InitializeCorrespondenceHandler.cs index c129670a..3167f868 100644 --- a/src/Altinn.Correspondence.Application/InitializeCorrespondence/InitializeCorrespondenceHandler.cs +++ b/src/Altinn.Correspondence.Application/InitializeCorrespondence/InitializeCorrespondenceHandler.cs @@ -16,25 +16,17 @@ public class InitializeCorrespondenceHandler : IHandler> Process(InitializeCorrespondenceRequest request, CancellationToken cancellationToken) @@ -48,32 +40,31 @@ public async Task> Process(Initia { return Errors.NoAttachments; } - InitializeCorrespondenceHelper initializeCorrespondenceHelper = new InitializeCorrespondenceHelper(_correspondenceRepository, _correspondenceStatusRepository, _attachmentStatusRepository, _attachmentRepository, _storageRepository, _hostEnvironment); - var contentError = initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); + var contentError = _initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); if (contentError != null) { return contentError; } - var attachmentError = initializeCorrespondenceHelper.ValidateAttachmentFiles(request.Attachments, request.Correspondence.Content!.Attachments, false); + var attachmentError = _initializeCorrespondenceHelper.ValidateAttachmentFiles(request.Attachments, request.Correspondence.Content!.Attachments, false); if (attachmentError != null) return attachmentError; var attachments = new List(); if (request.Correspondence.Content!.Attachments.Count > 0) { foreach (var attachment in request.Correspondence.Content!.Attachments) { - var a = await initializeCorrespondenceHelper.ProcessAttachment(attachment, true, cancellationToken); + var a = await _initializeCorrespondenceHelper.ProcessAttachment(attachment, cancellationToken); attachments.Add(a); } } if (request.Attachments.Count > 0) { - var uploadError = await initializeCorrespondenceHelper.UploadAttachments(attachments, request.Attachments, cancellationToken); + var uploadError = await _initializeCorrespondenceHelper.UploadAttachments(attachments, request.Attachments, cancellationToken); if (uploadError != null) { return uploadError; } } - var status = initializeCorrespondenceHelper.GetInitializeCorrespondenceStatus(request.Correspondence); + var status = _initializeCorrespondenceHelper.GetInitializeCorrespondenceStatus(request.Correspondence); var statuses = new List(){ new CorrespondenceStatusEntity { @@ -93,7 +84,7 @@ public async Task> Process(Initia } request.Correspondence.Statuses = statuses; - request.Correspondence.Notifications = initializeCorrespondenceHelper.ProcessNotifications(request.Correspondence.Notifications, cancellationToken); + request.Correspondence.Notifications = _initializeCorrespondenceHelper.ProcessNotifications(request.Correspondence.Notifications, cancellationToken); var correspondence = await _correspondenceRepository.CreateCorrespondence(request.Correspondence, cancellationToken); _backgroundJobClient.Schedule((service) => service.Publish(correspondence.Id, cancellationToken), correspondence.VisibleFrom); await _eventBus.Publish(AltinnEventType.CorrespondenceInitialized, correspondence.ResourceId, correspondence.Id.ToString(), "correspondence", correspondence.Sender, cancellationToken); diff --git a/src/Altinn.Correspondence.Application/InitializeMultipleCorrespondences/InitializeMultipleCorrespondencesHandler.cs b/src/Altinn.Correspondence.Application/InitializeMultipleCorrespondences/InitializeMultipleCorrespondencesHandler.cs index d39e9a26..038c0af1 100644 --- a/src/Altinn.Correspondence.Application/InitializeMultipleCorrespondences/InitializeMultipleCorrespondencesHandler.cs +++ b/src/Altinn.Correspondence.Application/InitializeMultipleCorrespondences/InitializeMultipleCorrespondencesHandler.cs @@ -16,25 +16,17 @@ public class InitializeMultipleCorrespondencesHandler : IHandler> Process(InitializeMultipleCorrespondencesRequest request, CancellationToken cancellationToken) @@ -52,33 +44,32 @@ public async Task> Proce { return Errors.DuplicateRecipients; } - InitializeCorrespondenceHelper initializeCorrespondenceHelper = new InitializeCorrespondenceHelper(_correspondenceRepository, _correspondenceStatusRepository, _attachmentStatusRepository, _attachmentRepository, _storageRepository, _hostEnvironment); - var contentError = initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); + var contentError = _initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); if (contentError != null) { return contentError; } - var attachmentError = initializeCorrespondenceHelper.ValidateAttachmentFiles(request.Attachments, request.Correspondence.Content!.Attachments, true); + var attachmentError = _initializeCorrespondenceHelper.ValidateAttachmentFiles(request.Attachments, request.Correspondence.Content!.Attachments, true); if (attachmentError != null) return attachmentError; var attachments = new List(); if (request.Correspondence.Content!.Attachments.Count() > 0) { foreach (var attachment in request.Correspondence.Content!.Attachments) { - var a = await initializeCorrespondenceHelper.ProcessAttachment(attachment, true, cancellationToken); + var a = await _initializeCorrespondenceHelper.ProcessAttachment(attachment, cancellationToken); attachments.Add(a); } } if (request.Attachments.Count > 0) { - var uploadError = await initializeCorrespondenceHelper.UploadAttachments(attachments, request.Attachments, cancellationToken); + var uploadError = await _initializeCorrespondenceHelper.UploadAttachments(attachments, request.Attachments, cancellationToken); if (uploadError != null) { return uploadError; } } - var status = initializeCorrespondenceHelper.GetInitializeCorrespondenceStatus(request.Correspondence); + var status = _initializeCorrespondenceHelper.GetInitializeCorrespondenceStatus(request.Correspondence); var correspondences = new List(); foreach (var recipient in request.Recipients) { @@ -108,7 +99,7 @@ public async Task> Proce PropertyList = request.Correspondence.PropertyList.ToDictionary(x => x.Key, x => x.Value), ReplyOptions = request.Correspondence.ReplyOptions, IsReservable = request.Correspondence.IsReservable, - Notifications = initializeCorrespondenceHelper.ProcessNotifications(request.Correspondence.Notifications, cancellationToken), + Notifications = _initializeCorrespondenceHelper.ProcessNotifications(request.Correspondence.Notifications, cancellationToken), Statuses = new List(){ new CorrespondenceStatusEntity { diff --git a/src/Altinn.Correspondence.Application/MalwareScanResult/MalwareScanResultHandler.cs b/src/Altinn.Correspondence.Application/MalwareScanResult/MalwareScanResultHandler.cs index 959b8936..04f67bae 100644 --- a/src/Altinn.Correspondence.Application/MalwareScanResult/MalwareScanResultHandler.cs +++ b/src/Altinn.Correspondence.Application/MalwareScanResult/MalwareScanResultHandler.cs @@ -1,4 +1,5 @@ -using Altinn.Correspondence.Application.MalwareScanResult.Models; +using Altinn.Correspondence.Application.Helpers; +using Altinn.Correspondence.Application.MalwareScanResult.Models; using Altinn.Correspondence.Core.Models.Enums; using Altinn.Correspondence.Core.Repositories; using Altinn.Correspondence.Core.Services; @@ -12,10 +13,12 @@ public class MalwareScanResultHandler( IAttachmentRepository attachmentRepository, IAttachmentStatusRepository attachmentStatusRepository, IEventBus eventBus, + UploadHelper uploadHelper, ILogger logger) : IHandler { private readonly IAttachmentRepository _attachmentRepository = attachmentRepository; private readonly IAttachmentStatusRepository _attachmentStatusRepository = attachmentStatusRepository; + private readonly UploadHelper _uploadHelper = uploadHelper; private readonly ILogger _logger = logger; private readonly IEventBus _eventBus = eventBus; @@ -47,6 +50,7 @@ await _attachmentStatusRepository.AddAttachmentStatus(new Correspondence.Core.Mo }, cancellationToken); await _eventBus.Publish(AltinnEventType.AttachmentPublished, attachment.ResourceId, attachmentIdFromBlobUri, "Attachment Published", attachment.SendersReference, cancellationToken); _logger.LogInformation("Non-malicious result for {fileTransferId} with result type {scanResultType}", attachmentId, data.ScanResultType); + await _uploadHelper.CheckCorrespondenceStatusesAfterUploadAndPublish(attachment.Id, true, cancellationToken); return Task.CompletedTask; } else @@ -60,7 +64,8 @@ await _attachmentStatusRepository.AddAttachmentStatus(new Correspondence.Core.Mo StatusText = $"Malware scan failed: {data.ScanResultType}: {data.ScanResultDetails}" }, cancellationToken); await _eventBus.Publish(AltinnEventType.AttachmentUploadFailed, attachment.ResourceId, attachmentIdFromBlobUri, "Malware scan", attachment.SendersReference, cancellationToken); - _logger.LogInformation("Non-malicious result for {fileTransferId} with result type {scanResultType}", attachmentId, data.ScanResultType); + _logger.LogWarning("Malicious result for {fileTransferId} with result type {scanResultType}", attachmentId, data.ScanResultType); + await _uploadHelper.CheckCorrespondenceStatusesAfterUploadAndPublish(attachmentId, false, cancellationToken); return Task.CompletedTask; } } diff --git a/src/Altinn.Correspondence.Application/UploadAttachment/UploadAttachmentHandler.cs b/src/Altinn.Correspondence.Application/UploadAttachment/UploadAttachmentHandler.cs index e0266e8c..7c3f37a1 100644 --- a/src/Altinn.Correspondence.Application/UploadAttachment/UploadAttachmentHandler.cs +++ b/src/Altinn.Correspondence.Application/UploadAttachment/UploadAttachmentHandler.cs @@ -42,7 +42,10 @@ public async Task> Process(UploadAttachme UploadHelper uploadHelper = new UploadHelper(_correspondenceRepository, _correspondenceStatusRepository, _attachmentStatusRepository, _attachmentRepository, _storageRepository, _hostEnvironment); var uploadResult = await uploadHelper.UploadAttachment(request.UploadStream, request.AttachmentId, cancellationToken); - await uploadHelper.CheckCorrespondenceStatusesAfterUploadAndPublish(attachment.Id, cancellationToken); + if (_hostEnvironment.IsDevelopment()) + { + await uploadHelper.CheckCorrespondenceStatusesAfterUploadAndPublish(attachment.Id, true, cancellationToken); + } return uploadResult.Match>( data => { return data; },