Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endpoint for updating task name #11814

Merged
merged 5 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions backend/src/Designer/Controllers/ProcessModelingController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,27 @@ public async Task<FileStreamResult> SaveProcessDefinitionFromTemplate(string org
Stream processDefinitionStream = _processModelingService.GetProcessDefinitionStream(editingContext);
return new FileStreamResult(processDefinitionStream, MediaTypeNames.Text.Plain);
}

[HttpPut("tasks/{taskId}/{taskName}")]
public async Task<ActionResult> UpdateProcessTaskName(string org, string repo, string taskId, string taskName, CancellationToken cancellationToken)
{
Guard.AssertArgumentNotNull(taskId, nameof(taskId));
Guard.AssertArgumentNotNull(taskName, nameof(taskName));
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer);
try
{
Stream updatedProcessDefinitionStream = await _processModelingService.UpdateProcessTaskNameAsync(editingContext, taskId, taskName, cancellationToken);
return new FileStreamResult(updatedProcessDefinitionStream, MediaTypeNames.Text.Plain);
}
catch (InvalidOperationException)
{
return BadRequest("Could not deserialize process definition.");
}
catch (ArgumentException)
{
return BadRequest("Could not find task with given id.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Altinn.App.Core.Internal.Process.Elements;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Interfaces;
Expand Down Expand Up @@ -52,6 +55,37 @@ public Stream GetProcessDefinitionStream(AltinnRepoEditingContext altinnRepoEdit
return altinnAppGitRepository.GetProcessDefinitionFile();
}

public async Task<Stream> UpdateProcessTaskNameAsync(AltinnRepoEditingContext altinnRepoEditingContext, string taskId, string taskName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(altinnRepoEditingContext.Org, altinnRepoEditingContext.Repo, altinnRepoEditingContext.Developer);
XmlSerializer serializer = new(typeof(Definitions));
Definitions? definitions;
using (Stream processDefinitionStream = GetProcessDefinitionStream(altinnRepoEditingContext))
{
definitions = (Definitions?)serializer.Deserialize(processDefinitionStream);
}

if (definitions == null)
{
throw new InvalidOperationException("Could not deserialize process definition.");
}

ProcessTask? processTask = (definitions.Process.Tasks?.FirstOrDefault(t => t.Id == taskId)) ?? throw new ArgumentException($"Could not find task with id {taskId}.");
processTask.Name = taskName;

Stream processStream = new MemoryStream();
serializer.Serialize(processStream, definitions);

// Reset stream position to beginning after serialization
processStream.Seek(0, SeekOrigin.Begin);
await altinnAppGitRepository.SaveProcessDefinitionFileAsync(processStream, cancellationToken);

// Reset stream position to beginning after saving
processStream.Seek(0, SeekOrigin.Begin);
return processStream;
}

private IEnumerable<string> EnumerateTemplateResources(Version version)
{
return typeof(ProcessModelingService).Assembly.GetManifestResourceNames()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,15 @@ public interface IProcessModelingService
/// <param name="altinnRepoEditingContext">An <see cref="AltinnRepoEditingContext"/>.</param>
/// <returns>A <see cref="Stream"/> of a process definition file.</returns>
Stream GetProcessDefinitionStream(AltinnRepoEditingContext altinnRepoEditingContext);

/// <summary>
/// Updates the name of a task in the process definition file.
/// </summary>
/// <param name="altinnRepoEditingContext">n <see cref="AltinnRepoEditingContext"/>.</param>
/// <param name="taskId">The ID of the task to update</param>
/// <param name="taskName">The name to set for the task</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
/// <returns></returns>
Task<Stream> UpdateProcessTaskNameAsync(AltinnRepoEditingContext altinnRepoEditingContext, string taskId, string taskName, CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Net;
using System.Net.Http;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Designer.Tests.Controllers.ApiTests;
using Designer.Tests.Utils;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;

namespace Designer.Tests.Controllers.ProcessModelingController
{
public class UpdateProcessTaskName : DisagnerEndpointsTestsBase<UpdateProcessTaskName>, IClassFixture<WebApplicationFactory<Program>>
{
private static string Url(string org, string repository, string taskId, string taskName) => $"/designer/api/{org}/{repository}/process-modelling/tasks/{taskId}/{taskName}";

public UpdateProcessTaskName(WebApplicationFactory<Program> factory) : base(factory)
{
}

[Theory]
[InlineData("ttd", "app-with-process", "testUser", "Task_1", "NewTaskName")]
public async Task UpdateProcessTaskName_ShouldReturnUpdatedProcess(string org, string app, string developer, string taskId, string taskName)
{
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);

string url = Url(org, targetRepository, taskId, taskName);

using var response = await HttpClient.PutAsync(url, null);
response.StatusCode.Should().Be(HttpStatusCode.OK);

string responseContent = await response.Content.ReadAsStringAsync();

responseContent.Should().NotBeNullOrEmpty();
responseContent.Should().Contain(taskName);
}

[Theory]
[InlineData("ttd", "app-with-process", "testUser", "Does_not_exist", "NewTaskName")]
public async Task InvalidTaskId_ShouldReturnBadRequest(string org, string app, string developer, string taskId, string taskName)
{
string targetRepository = TestDataHelper.GenerateTestRepoName();
await CopyRepositoryForTest(org, app, developer, targetRepository);

string url = Url(org, targetRepository, taskId, taskName);

using var response = await HttpClient.PutAsync(url, null);
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using Altinn.App.Core.Internal.Process.Elements;
using Altinn.Studio.Designer.Factories;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Implementation.ProcessModeling;
using Altinn.Studio.Designer.Services.Interfaces;
using Designer.Tests.Utils;
using FluentAssertions;
using Moq;
using SharedResources.Tests;
Expand Down Expand Up @@ -30,6 +36,34 @@ public void GetProcessDefinitionTemplates_GivenVersion_ReturnsListOfTemplates(st
}
}

[Theory]
[InlineData("ttd", "app-with-process", "testUser", "Task_1", "NewTaskName")]
public async void UpdateProcessTaskNameAsync_GivenTaskIdAndTaskName_UpdatesTaskName(string org, string repo, string developer, string taskId, string newTaskName)
{
// Arrange
string targetRepository = TestDataHelper.GenerateTestRepoName();
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, targetRepository, developer);
await TestDataHelper.CopyRepositoryForTest(org, repo, developer, targetRepository);

try
{
var altinnGitRepositoryFactory = new AltinnGitRepositoryFactory(TestDataHelper.GetTestDataRepositoriesRootDirectory());
IProcessModelingService processModelingService = new ProcessModelingService(altinnGitRepositoryFactory);

// Act
using Stream result = await processModelingService.UpdateProcessTaskNameAsync(editingContext, taskId, newTaskName);
XmlSerializer serializer = new(typeof(Definitions));
Definitions definitions = (Definitions)serializer.Deserialize(result);

// Assert
definitions.Process.Tasks.First(t => t.Id == taskId).Name.Should().Be(newTaskName);
}
finally
{
TestDataHelper.DeleteAppRepository(org, targetRepository, developer);
}
}

public static IEnumerable<object[]> TemplatesTestData => new List<object[]>
{
new object[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:altinn="http://altinn.no" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Altinn_SingleDataTask_Process_Definition" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:process id="SingleDataTask" isExecutable="false">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1n56yn5</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:endEvent id="EndEvent_1">
<bpmn:incoming>Flow_1htunjv</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_1n56yn5" sourceRef="StartEvent_1" targetRef="Task_1" />
<bpmn:task id="Task_1" name="Utfylling">
<bpmn:extensionElements>
<altinn:taskExtension>
<altinn:taskType>data</altinn:taskType>
</altinn:taskExtension>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_1n56yn5</bpmn:incoming>
<bpmn:outgoing>Flow_1htunjv</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="Flow_1htunjv" sourceRef="Task_1" targetRef="EndEvent_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="SingleDataTask">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="156" y="81" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_1_di" bpmnElement="Task_1">
<dc:Bounds x="260" y="59" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1">
<dc:Bounds x="422" y="81" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1n56yn5_di" bpmnElement="SequenceFlow_1n56yn5">
<di:waypoint x="192" y="99" />
<di:waypoint x="260" y="99" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1htunjv_di" bpmnElement="Flow_1htunjv">
<di:waypoint x="360" y="99" />
<di:waypoint x="422" y="99" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Loading