diff --git a/backend/src/Designer/Controllers/ProcessModelingController.cs b/backend/src/Designer/Controllers/ProcessModelingController.cs index 4c6b3e520dd..bef996892f2 100644 --- a/backend/src/Designer/Controllers/ProcessModelingController.cs +++ b/backend/src/Designer/Controllers/ProcessModelingController.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net.Mime; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; @@ -67,12 +67,17 @@ await _processModelingService.SaveProcessDefinitionAsync( return Ok(); } - [HttpPut("process-definition-latest")] - public async Task UpsertProcessDefinition(string org, string repo, [FromForm] ProcessDefinitionDto processDefinitionDto, CancellationToken cancellationToken) + [HttpPost("process-definition-latest")] + public async Task UpsertProcessDefinitionAndNotify(string org, string repo, [FromForm] IFormFile content, [FromForm] string metadata, CancellationToken cancellationToken) { Request.EnableBuffering(); - Stream stream = processDefinitionDto.Content.OpenReadStream(); + var metadataObject = metadata is not null + ? JsonSerializer.Deserialize(metadata, + new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }) + : null; + + Stream stream = content.OpenReadStream(); try { @@ -87,9 +92,9 @@ public async Task UpsertProcessDefinition(string org, string repo await _processModelingService.SaveProcessDefinitionAsync( AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer), stream, cancellationToken); - if (processDefinitionDto.ProcessDefinitionMetadata?.TaskIdChanges is not null) + if (metadataObject?.TaskIdChanges is not null) { - foreach (TaskIdChange taskIdChange in processDefinitionDto.ProcessDefinitionMetadata.TaskIdChanges) + foreach (TaskIdChange taskIdChange in metadataObject.TaskIdChanges) { await _mediator.Publish(new ProcessTaskIdChangedEvent { diff --git a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedApplicationMetadataHandler.cs b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedApplicationMetadataHandler.cs index 7076d4db91a..369231a9d58 100644 --- a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedApplicationMetadataHandler.cs +++ b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedApplicationMetadataHandler.cs @@ -9,6 +9,8 @@ public class ProcessTaskIdChangedApplicationMetadataHandler : INotificationHandl { public Task Handle(ProcessTaskIdChangedEvent notification, CancellationToken cancellationToken) { + // TODO: Implement logic to handle the event here: https://github.com/Altinn/altinn-studio/issues/12220 + // Here we should think how to handle errors in the handlers. Should we throw exceptions or use websocket to send error messages to the client? return Task.CompletedTask; } } diff --git a/backend/src/Designer/Models/Dto/ProcessDefinitionDto.cs b/backend/src/Designer/Models/Dto/ProcessDefinitionDto.cs deleted file mode 100644 index 5890523773f..00000000000 --- a/backend/src/Designer/Models/Dto/ProcessDefinitionDto.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Microsoft.AspNetCore.Http; - -namespace Altinn.Studio.Designer.Models.Dto; - -public class ProcessDefinitionDto -{ - public IFormFile Content { get; set; } - - public ProcessDefinitionMetadata ProcessDefinitionMetadata { get; set; } -} diff --git a/backend/tests/Designer.Tests/Controllers/ProcessModelingController/UpsertProcessDefinitionAndNotifyTests.cs b/backend/tests/Designer.Tests/Controllers/ProcessModelingController/UpsertProcessDefinitionAndNotifyTests.cs new file mode 100644 index 00000000000..a6c3311cdca --- /dev/null +++ b/backend/tests/Designer.Tests/Controllers/ProcessModelingController/UpsertProcessDefinitionAndNotifyTests.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using System.Xml.Linq; +using Altinn.Studio.Designer.Models.Dto; +using Designer.Tests.Controllers.ApiTests; +using Designer.Tests.Utils; +using FluentAssertions; +using Microsoft.AspNetCore.Mvc.Testing; +using SharedResources.Tests; +using Xunit; + +namespace Designer.Tests.Controllers.ProcessModelingController; + +public class UpsertProcessDefinitionAndNotifyTests : DisagnerEndpointsTestsBase, IClassFixture> +{ + private static string VersionPrefix(string org, string repository) => $"/designer/api/{org}/{repository}/process-modelling/process-definition-latest"; + + public UpsertProcessDefinitionAndNotifyTests(WebApplicationFactory factory) : base(factory) + { + } + + [Theory] + [MemberData(nameof(UpsertProcessDefinitionAndNotifyTestData))] + public async Task UpsertProcessDefinition_ShouldReturnOk(string org, string app, string developer, string bpmnFilePath, ProcessDefinitionMetadata metadata) + { + string targetRepository = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, app, developer, targetRepository); + string fileContent = SharedResourcesHelper.LoadTestDataAsString(bpmnFilePath); + fileContent = metadata.TaskIdChanges.Aggregate(fileContent, (current, metadataTaskIdChange) => current.Replace(metadataTaskIdChange.OldId, metadataTaskIdChange.NewId)); + var fileStream = GenerateStreamFromString(fileContent); + + string url = VersionPrefix(org, targetRepository); + + var form = new MultipartFormDataContent(); + string metadataString = JsonSerializer.Serialize(metadata, + new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); + form.Add(new StreamContent(fileStream), "content", "process.bpmn"); + form.Add(new StringContent(metadataString, Encoding.UTF8, MediaTypeNames.Application.Json), "metadata"); + + using var response = await HttpClient.PostAsync(url, form); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string savedFile = TestDataHelper.GetFileFromRepo(org, targetRepository, developer, "App/config/process/process.bpmn"); + + XDocument expectedXml = XDocument.Parse(fileContent); + XDocument savedXml = XDocument.Parse(savedFile); + XNode.DeepEquals(savedXml, expectedXml).Should().BeTrue(); + } + + private static Stream GenerateStreamFromString(string s) + { + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(s); + writer.Flush(); + stream.Position = 0; + return stream; + } + + public static IEnumerable UpsertProcessDefinitionAndNotifyTestData() + { + yield return new object[] { "ttd", "empty-app", "testUser", "App/config/process/process.bpmn", + new ProcessDefinitionMetadata + { + TaskIdChanges = new List { new() { OldId = "Task_1", NewId = "SomeNewId" } } + } }; + } +} diff --git a/testdata/App/config/process/process.bpmn b/testdata/App/config/process/process.bpmn index 5400f3ee0f9..d3b0916f0a6 100644 --- a/testdata/App/config/process/process.bpmn +++ b/testdata/App/config/process/process.bpmn @@ -1,48 +1,78 @@ - - - - - To_Task_1 - - - To_Task_1 - To_Task_2 - - - To_Task_2 - To_Task_3 - - - To_Task_3 - To_Task_4 - - - To_Task_4 - To_Task_5 - - - To_Task_5 - To_Task_6 - - - To_Task_6 - To_End - - - To_End - - - - - - - - - + + + + + To_Task_1 + + + To_Task_1 + To_Task_2 + + + data + + + + + To_Task_2 + To_Task_3 + + + data + + fill + + + + + + To_Task_3 + To_Task_4 + + + data + + + + + To_Task_4 + To_Task_5 + + + data + + + + + To_Task_5 + To_Task_6 + + + data + + + + + To_Task_6 + To_End + + + confirmation + + confirm + + + + + + To_End + + + + + + + + +