From d64db5fe4778cccb2da645951271570c6a4fba5c Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 13:57:02 +0200 Subject: [PATCH 1/8] add errors for due date and allowsystemdeleteafter --- src/Altinn.Correspondence.Application/Errors.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Altinn.Correspondence.Application/Errors.cs b/src/Altinn.Correspondence.Application/Errors.cs index b099f5db..3dc0f33b 100644 --- a/src/Altinn.Correspondence.Application/Errors.cs +++ b/src/Altinn.Correspondence.Application/Errors.cs @@ -31,4 +31,7 @@ public static class Errors public static Error HashError = new Error(23, "Checksum mismatch", HttpStatusCode.BadRequest); public static Error DataLocationNotFound = new Error(24, "Could not get data location url", HttpStatusCode.BadRequest); public static Error ExistingAttachmentNotFound = new Error(25, "Existing attachment not found", HttpStatusCode.BadRequest); + public static Error DueDatePriorToday = new Error(26, "Due date cannot be prior to today", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorToday = new Error(26, "AllowSystemDelete cannot be prior to today", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorDueDate = new Error(26, "AllowSystemDelete cannot be prior to due date", HttpStatusCode.BadRequest); } From cb62d1d6917c08918fad23a539dce6e54f89e6c0 Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 13:58:54 +0200 Subject: [PATCH 2/8] validate duedate and allowsystemdeleteafter properties --- .../InitializeCorrespondencesHandler.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs b/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs index 9ad39cc1..673dd2fb 100644 --- a/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs +++ b/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs @@ -44,6 +44,18 @@ public async Task> Process(Initi { return Errors.DuplicateRecipients; } + if (request.Correspondence.DueDateTime < DateTimeOffset.Now) + { + return Errors.DueDatePriorToday; + } + if (request.Correspondence.AllowSystemDeleteAfter < DateTimeOffset.Now) + { + return Errors.AllowSystemDeletePriorToday; + } + if (request.Correspondence.AllowSystemDeleteAfter < request.Correspondence.DueDateTime) + { + return Errors.AllowSystemDeletePriorDueDate; + } var contentError = _initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); if (contentError != null) { From 92ed34acc3dab01903bf1adf64a6032e967315de Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 15:17:14 +0200 Subject: [PATCH 3/8] create tests for duedate and allowsystemdeleteafter --- .../CorrespondenceControllerTests.cs | 47 ++++++++++++++++++- .../InitializeCorrespondenceFactory.cs | 6 +-- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs index 5b707316..c730bbcf 100644 --- a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs +++ b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs @@ -108,6 +108,48 @@ public async Task InitializeCorrespondence_With_Invalid_Recipient_Returns_BadReq Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); } + [Fact] + public async Task InitializeCorrespondence_DueDate_PriorToday_Returns_BadRequest() + { + // Arrange + var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); + correspondence.Correspondence.DueDateTime = DateTimeOffset.Now.AddDays(-7); + + // Act + var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", correspondence); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); + } + + [Fact] + public async Task InitializeCorrespondence_AllowSystemDeleAfter_PriorToday_Returns_BadRequest() + { + // Arrange + var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); + correspondence.Correspondence.AllowSystemDeleteAfter = DateTimeOffset.Now.AddDays(-7); + + // Act + var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", correspondence); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); + } + [Fact] + public async Task InitializeCorrespondence_AllowSystemDeleAfter_PriorDueDate_Returns_BadRequest() + { + // Arrange + var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); + correspondence.Correspondence.AllowSystemDeleteAfter = DateTimeOffset.Now.AddDays(-7); + correspondence.Correspondence.DueDateTime = DateTimeOffset.Now; + + // Act + var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", correspondence); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); + } + [Fact] public async Task UploadCorrespondence_Gives_Ok() { @@ -130,7 +172,7 @@ public async Task UploadCorrespondence_Gives_Ok() using var fileStream = file.OpenReadStream(); formData.Add(new StreamContent(fileStream), "attachments", file.FileName); var uploadCorrespondenceResponse = await _client.PostAsync("correspondence/api/v1/correspondence/upload", formData); - uploadCorrespondenceResponse.EnsureSuccessStatusCode(); + Assert.True(uploadCorrespondenceResponse.IsSuccessStatusCode, await uploadCorrespondenceResponse.Content.ReadAsStringAsync()); var response = await uploadCorrespondenceResponse.Content.ReadFromJsonAsync(_responseSerializerOptions); var attachmentId = response?.AttachmentIds.FirstOrDefault(); @@ -521,6 +563,7 @@ private MultipartFormDataContent CorrespondenceToFormData(BaseCorrespondenceExt { new StringContent(correspondence.Sender), "correspondence.sender" }, { new StringContent(correspondence.SendersReference), "correspondence.sendersReference" }, { new StringContent(correspondence.VisibleFrom.ToString()), "correspondence.visibleFrom" }, + { new StringContent(correspondence.DueDateTime.ToString()), "correspondence.dueDateTime" }, { new StringContent(correspondence.AllowSystemDeleteAfter.ToString()), "correspondence.AllowSystemDeleteAfter" }, { new StringContent(correspondence.Content.MessageTitle), "correspondence.content.MessageTitle" }, { new StringContent(correspondence.Content.MessageSummary), "correspondence.content.MessageSummary" }, @@ -568,4 +611,4 @@ private MultipartFormDataContent CorrespondenceToFormData(BaseCorrespondenceExt .ForEach((item) => formData.Add(new StringContent(item.Value), "correspondence.propertyLists." + item.Key)); return formData; } -} \ No newline at end of file +} diff --git a/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs b/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs index 61592abb..2d08a0b4 100644 --- a/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs +++ b/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs @@ -30,9 +30,9 @@ internal static class InitializeCorrespondenceFactory } }, }, - VisibleFrom = DateTime.UtcNow, - AllowSystemDeleteAfter = DateTime.UtcNow.AddDays(3), - DueDateTime = DateTime.UtcNow.AddDays(2), + VisibleFrom = DateTimeOffset.UtcNow, + AllowSystemDeleteAfter = DateTimeOffset.UtcNow.AddDays(3), + DueDateTime= DateTimeOffset.UtcNow.AddDays(2), ExternalReferences = new List(){ new ExternalReferenceExt() { From f3e72fbc75e8a834e0a8f48fa23872776e6da490 Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 15:27:02 +0200 Subject: [PATCH 4/8] rewrite test to exclude prior bad requests --- .../CorrespondenceControllerTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs index c730bbcf..fc99e4e9 100644 --- a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs +++ b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs @@ -140,8 +140,9 @@ public async Task InitializeCorrespondence_AllowSystemDeleAfter_PriorDueDate_Ret { // Arrange var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); - correspondence.Correspondence.AllowSystemDeleteAfter = DateTimeOffset.Now.AddDays(-7); - correspondence.Correspondence.DueDateTime = DateTimeOffset.Now; + correspondence.Correspondence.VisibleFrom = DateTimeOffset.Now.AddDays(7); + correspondence.Correspondence.AllowSystemDeleteAfter = DateTimeOffset.Now.AddDays(14); + correspondence.Correspondence.DueDateTime = DateTimeOffset.Now.AddDays(21); // Act var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", correspondence); From 6f81d8e5a745ed28d85cd5a6424e2eaf452993e1 Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 15:27:52 +0200 Subject: [PATCH 5/8] fix: duplicate ErrorCode --- src/Altinn.Correspondence.Application/Errors.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Altinn.Correspondence.Application/Errors.cs b/src/Altinn.Correspondence.Application/Errors.cs index 3dc0f33b..ed8580af 100644 --- a/src/Altinn.Correspondence.Application/Errors.cs +++ b/src/Altinn.Correspondence.Application/Errors.cs @@ -32,6 +32,6 @@ public static class Errors public static Error DataLocationNotFound = new Error(24, "Could not get data location url", HttpStatusCode.BadRequest); public static Error ExistingAttachmentNotFound = new Error(25, "Existing attachment not found", HttpStatusCode.BadRequest); public static Error DueDatePriorToday = new Error(26, "Due date cannot be prior to today", HttpStatusCode.BadRequest); - public static Error AllowSystemDeletePriorToday = new Error(26, "AllowSystemDelete cannot be prior to today", HttpStatusCode.BadRequest); - public static Error AllowSystemDeletePriorDueDate = new Error(26, "AllowSystemDelete cannot be prior to due date", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorToday = new Error(27, "AllowSystemDelete cannot be prior to today", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorDueDate = new Error(28, "AllowSystemDelete cannot be prior to due date", HttpStatusCode.BadRequest); } From 6a48bd45cddf2ddeadf97ab9f0886b32a2aa7e2b Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 16:02:59 +0200 Subject: [PATCH 6/8] Add constraint with respect to VisibleFrom --- .../Errors.cs | 8 +++--- .../Helpers/InitializeCorrespondenceHelper.cs | 26 +++++++++++++++++++ .../InitializeCorrespondencesHandler.cs | 13 +++------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Altinn.Correspondence.Application/Errors.cs b/src/Altinn.Correspondence.Application/Errors.cs index ed8580af..91d950c6 100644 --- a/src/Altinn.Correspondence.Application/Errors.cs +++ b/src/Altinn.Correspondence.Application/Errors.cs @@ -31,7 +31,9 @@ public static class Errors public static Error HashError = new Error(23, "Checksum mismatch", HttpStatusCode.BadRequest); public static Error DataLocationNotFound = new Error(24, "Could not get data location url", HttpStatusCode.BadRequest); public static Error ExistingAttachmentNotFound = new Error(25, "Existing attachment not found", HttpStatusCode.BadRequest); - public static Error DueDatePriorToday = new Error(26, "Due date cannot be prior to today", HttpStatusCode.BadRequest); - public static Error AllowSystemDeletePriorToday = new Error(27, "AllowSystemDelete cannot be prior to today", HttpStatusCode.BadRequest); - public static Error AllowSystemDeletePriorDueDate = new Error(28, "AllowSystemDelete cannot be prior to due date", HttpStatusCode.BadRequest); + public static Error DueDatePriorToday = new Error(26, "DueDateTime cannot be prior to today", HttpStatusCode.BadRequest); + public static Error DueDatePriorVisibleFrom = new Error(27, "DueDateTime cannot be prior to VisibleFrom", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorToday = new Error(28, "AllowSystemDelete cannot be prior to today", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorVisibleFrom = new Error(29, "AllowSystemDelete cannot be prior to VisibleFrom", HttpStatusCode.BadRequest); + public static Error AllowSystemDeletePriorDueDate = new Error(30, "AllowSystemDelete cannot be prior to DueDateTime", HttpStatusCode.BadRequest); } diff --git a/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs b/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs index 12412ec6..e7d8c6a6 100644 --- a/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs +++ b/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs @@ -22,6 +22,31 @@ public InitializeCorrespondenceHelper(IAttachmentRepository attachmentRepository _uploadHelper = uploadHelper; } + public Error? ValidateDateConstraints(CorrespondenceEntity correspondence) + { + var visibleFrom = correspondence.VisibleFrom; + if (correspondence.DueDateTime < DateTimeOffset.Now) + { + return Errors.DueDatePriorToday; + } + if (correspondence.DueDateTime < visibleFrom) + { + return Errors.DueDatePriorVisibleFrom; + } + if (correspondence.AllowSystemDeleteAfter < DateTimeOffset.Now) + { + return Errors.AllowSystemDeletePriorToday; + } + if (correspondence.AllowSystemDeleteAfter < visibleFrom) + { + return Errors.AllowSystemDeletePriorVisibleFrom; + } + if (correspondence.AllowSystemDeleteAfter < correspondence.DueDateTime) + { + return Errors.AllowSystemDeletePriorDueDate; + } + return null; + } public Error? ValidateCorrespondenceContent(CorrespondenceContentEntity content) { if (!TextValidation.ValidatePlainText(content?.MessageTitle)) @@ -56,6 +81,7 @@ public InitializeCorrespondenceHelper(IAttachmentRepository attachmentRepository return null; } + public List ProcessNotifications(List? notifications, CancellationToken cancellationToken) { if (notifications == null) return new List(); diff --git a/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs b/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs index 673dd2fb..2de2d108 100644 --- a/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs +++ b/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs @@ -44,17 +44,10 @@ public async Task> Process(Initi { return Errors.DuplicateRecipients; } - if (request.Correspondence.DueDateTime < DateTimeOffset.Now) + var dateError = _initializeCorrespondenceHelper.ValidateDateConstraints(request.Correspondence); + if (dateError != null) { - return Errors.DueDatePriorToday; - } - if (request.Correspondence.AllowSystemDeleteAfter < DateTimeOffset.Now) - { - return Errors.AllowSystemDeletePriorToday; - } - if (request.Correspondence.AllowSystemDeleteAfter < request.Correspondence.DueDateTime) - { - return Errors.AllowSystemDeletePriorDueDate; + return dateError; } var contentError = _initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); if (contentError != null) From d00adead3a124926414d17c577be9b46dfbc2cd8 Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 16:25:25 +0200 Subject: [PATCH 7/8] Add more tests and ensure tests are independent of other errors --- .../CorrespondenceControllerTests.cs | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs index fc99e4e9..ce992e92 100644 --- a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs +++ b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs @@ -121,9 +121,23 @@ public async Task InitializeCorrespondence_DueDate_PriorToday_Returns_BadRequest // Assert Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); } + [Fact] + public async Task InitializeCorrespondence_DueDate_PriorVisibleFrom_Returns_BadRequest() + { + // Arrange + var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); + correspondence.Correspondence.DueDateTime = DateTimeOffset.Now.AddDays(7); + correspondence.Correspondence.VisibleFrom = DateTimeOffset.Now.AddDays(14); + + // Act + var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", correspondence); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); + } [Fact] - public async Task InitializeCorrespondence_AllowSystemDeleAfter_PriorToday_Returns_BadRequest() + public async Task InitializeCorrespondence_AllowSystemDeleteAfter_PriorToday_Returns_BadRequest() { // Arrange var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); @@ -135,8 +149,24 @@ public async Task InitializeCorrespondence_AllowSystemDeleAfter_PriorToday_Retur // Assert Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); } + + [Fact] + public async Task InitializeCorrespondence_AllowSystemDeleteAfter_PriorVisibleFrom_Returns_BadRequest() + { + // Arrange + var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); + correspondence.Correspondence.VisibleFrom = DateTimeOffset.Now.AddDays(14); + correspondence.Correspondence.DueDateTime = DateTimeOffset.Now.AddDays(21); // ensure DueDate is after VisibleFrom + correspondence.Correspondence.AllowSystemDeleteAfter = DateTimeOffset.Now.AddDays(7); + + // Act + var initializeCorrespondenceResponse = await _client.PostAsJsonAsync("correspondence/api/v1/correspondence", correspondence); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); + } [Fact] - public async Task InitializeCorrespondence_AllowSystemDeleAfter_PriorDueDate_Returns_BadRequest() + public async Task InitializeCorrespondence_AllowSystemDeleteAfter_PriorDueDate_Returns_BadRequest() { // Arrange var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); From 1b8b8983a11e6640f603a807e5e7a6bcddf0d8ce Mon Sep 17 00:00:00 2001 From: CelineTrammi Date: Thu, 29 Aug 2024 16:43:59 +0200 Subject: [PATCH 8/8] remove empty lines --- .../CorrespondenceControllerTests.cs | 2 +- .../Helpers/InitializeCorrespondenceHelper.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs index ce992e92..7808b74f 100644 --- a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs +++ b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs @@ -642,4 +642,4 @@ private MultipartFormDataContent CorrespondenceToFormData(BaseCorrespondenceExt .ForEach((item) => formData.Add(new StringContent(item.Value), "correspondence.propertyLists." + item.Key)); return formData; } -} +} \ No newline at end of file diff --git a/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs b/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs index e7d8c6a6..0826b96a 100644 --- a/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs +++ b/src/Altinn.Correspondence.Application/Helpers/InitializeCorrespondenceHelper.cs @@ -81,7 +81,6 @@ public InitializeCorrespondenceHelper(IAttachmentRepository attachmentRepository return null; } - public List ProcessNotifications(List? notifications, CancellationToken cancellationToken) { if (notifications == null) return new List();