diff --git a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs index c73de4d8..c6b9e1fd 100644 --- a/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs +++ b/Test/Altinn.Correspondence.Tests/CorrespondenceControllerTests.cs @@ -108,6 +108,79 @@ 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_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_AllowSystemDeleteAfter_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_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_AllowSystemDeleteAfter_PriorDueDate_Returns_BadRequest() + { + // Arrange + var correspondence = InitializeCorrespondenceFactory.BasicCorrespondences(); + 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); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, initializeCorrespondenceResponse.StatusCode); + } + [Fact] public async Task UploadCorrespondence_Gives_Ok() { @@ -130,7 +203,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(); @@ -523,6 +596,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" }, diff --git a/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs b/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs index 9105749d..be588b58 100644 --- a/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs +++ b/Test/Altinn.Correspondence.Tests/Factories/InitializeCorrespondenceFactory.cs @@ -29,9 +29,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() { diff --git a/src/Altinn.Correspondence.Application/Errors.cs b/src/Altinn.Correspondence.Application/Errors.cs index b099f5db..91d950c6 100644 --- a/src/Altinn.Correspondence.Application/Errors.cs +++ b/src/Altinn.Correspondence.Application/Errors.cs @@ -31,4 +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, "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..0826b96a 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)) diff --git a/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs b/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs index cfaa49b1..816e6025 100644 --- a/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs +++ b/src/Altinn.Correspondence.Application/InitializeCorrespondences/InitializeCorrespondencesHandler.cs @@ -46,6 +46,11 @@ public async Task> Process(Initi { return Errors.DuplicateRecipients; } + var dateError = _initializeCorrespondenceHelper.ValidateDateConstraints(request.Correspondence); + if (dateError != null) + { + return dateError; + } var contentError = _initializeCorrespondenceHelper.ValidateCorrespondenceContent(request.Correspondence.Content); if (contentError != null) {