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

Proccess file sync #12246

Merged
merged 4 commits into from
Feb 5, 2024
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
1 change: 1 addition & 0 deletions backend/packagegroups/NuGet.props
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<PackageReference Update="Polly" Version="8.2.1" />
<PackageReference Update="Altinn.Authorization.ABAC" Version="0.0.7" />
<PackageReference Update="Altinn.ApiClients.Maskinporten" Version="9.1.0" />
<PackageReference Update="MediatR" Version="12.2.0" />
</ItemGroup>

<ItemGroup Label="Packages used for testing">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Altinn.Studio.Designer.Helpers;
using Altinn.Studio.Designer.Infrastructure.GitRepository;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.Services.Interfaces;
using Altinn.Studio.Designer.ViewModels.Response;
using Microsoft.AspNetCore.Authorization;
Expand Down
88 changes: 60 additions & 28 deletions backend/src/Designer/Controllers/ProcessModelingController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
using System.Collections.Generic;
using System.IO;
using System.Net.Mime;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Events;
using Altinn.Studio.Designer.Helpers;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.Services.Interfaces;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -23,23 +27,30 @@ namespace Altinn.Studio.Designer.Controllers
public class ProcessModelingController : ControllerBase
{
private readonly IProcessModelingService _processModelingService;
public ProcessModelingController(IProcessModelingService processModelingService)
private readonly IMediator _mediator;

public ProcessModelingController(IProcessModelingService processModelingService, IMediator mediator)
{
_processModelingService = processModelingService;
_mediator = mediator;
}

[HttpGet("process-definition")]
public FileStreamResult GetProcessDefinition(string org, string repo)
{
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);

Stream processDefinitionStream = _processModelingService.GetProcessDefinitionStream(AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer));
Stream processDefinitionStream =
_processModelingService.GetProcessDefinitionStream(
AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer));

return new FileStreamResult(processDefinitionStream, MediaTypeNames.Text.Plain);
}

[HttpPut("process-definition")]
public async Task<IActionResult> SaveProcessDefinition(string org, string repo, CancellationToken cancellationToken)
[Obsolete("This endpoint should be replaced by process-definition-latest, and url fixed after integration with frontend")]
public async Task<IActionResult> SaveProcessDefinition(string org, string repo,
CancellationToken cancellationToken)
{
Request.EnableBuffering();
try
Expand All @@ -52,7 +63,48 @@ public async Task<IActionResult> SaveProcessDefinition(string org, string repo,
}

string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
await _processModelingService.SaveProcessDefinitionAsync(AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer), Request.Body, cancellationToken);
await _processModelingService.SaveProcessDefinitionAsync(
AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer), Request.Body, cancellationToken);
return Ok();
}

[HttpPut("process-definition-latest")]
public async Task<IActionResult> UpsertProcessDefinitionAndNotify(string org, string repo, [FromForm] IFormFile content, [FromForm] string metadata, CancellationToken cancellationToken)
{
Request.EnableBuffering();

var metadataObject = metadata is not null
? JsonSerializer.Deserialize<ProcessDefinitionMetadata>(metadata,
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })
: null;

Stream stream = content.OpenReadStream();

try
{
await Guard.AssertValidXmlStreamAndRewindAsync(stream);
}
catch (ArgumentException)
{
return BadRequest("BPMN file is not valid XML");
}

string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
await _processModelingService.SaveProcessDefinitionAsync(
AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer), stream, cancellationToken);

if (metadataObject?.TaskIdChanges is not null)
{
foreach (TaskIdChange taskIdChange in metadataObject.TaskIdChanges)
{
await _mediator.Publish(new ProcessTaskIdChangedEvent
{
OldId = taskIdChange.OldId,
NewId = taskIdChange.NewId
}, cancellationToken);
}
}

return Ok();
}

Expand All @@ -64,37 +116,17 @@ public IEnumerable<string> GetTemplates(string org, string repo, SemanticVersion
}

[HttpPut("templates/{appVersion}/{templateName}")]
public async Task<FileStreamResult> SaveProcessDefinitionFromTemplate(string org, string repo, SemanticVersion appVersion, string templateName, CancellationToken cancellationToken)
public async Task<FileStreamResult> SaveProcessDefinitionFromTemplate(string org, string repo,
SemanticVersion appVersion, string templateName, CancellationToken cancellationToken)
{
Guard.AssertArgumentNotNull(appVersion, nameof(appVersion));
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, repo, developer);
await _processModelingService.SaveProcessDefinitionFromTemplateAsync(editingContext, templateName, appVersion, cancellationToken);
await _processModelingService.SaveProcessDefinitionFromTemplateAsync(editingContext, templateName,
appVersion, cancellationToken);

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.");
}
}
}
}
1 change: 1 addition & 0 deletions backend/src/Designer/Designer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<PackageReference Include="ini-parser-netstandard" />
<PackageReference Include="JWTCookieAuthentication" />
<PackageReference Include="LibGit2Sharp" />
<PackageReference Include="MediatR" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Events;
using MediatR;

namespace Altinn.Studio.Designer.EventHandlers.ProcessTaskIdChanged;

public class ProcessTaskIdChangedApplicationMetadataHandler : INotificationHandler<ProcessTaskIdChangedEvent>
{
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;
}
}
9 changes: 9 additions & 0 deletions backend/src/Designer/Events/ProcessTaskIdChangedEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using MediatR;

namespace Altinn.Studio.Designer.Events;

public class ProcessTaskIdChangedEvent : INotification
{
public string OldId { get; set; }
public string NewId { get; set; }
}
8 changes: 8 additions & 0 deletions backend/src/Designer/Models/Dto/ProcessDefinitionMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Collections.Generic;

namespace Altinn.Studio.Designer.Models.Dto;

public class ProcessDefinitionMetadata
{
public List<TaskIdChange> TaskIdChanges { get; set; }
}
7 changes: 7 additions & 0 deletions backend/src/Designer/Models/Dto/TaskIdChange.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Altinn.Studio.Designer.Models.Dto;

public class TaskIdChange
{
public string OldId { get; set; }
public string NewId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using NuGet.Versioning;

namespace Altinn.Studio.Designer.ViewModels.Response
namespace Altinn.Studio.Designer.Models.Dto
{
public class VersionResponse
{
Expand Down
4 changes: 4 additions & 0 deletions backend/src/Designer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
// standalone package Microsoft.Extensions.Logging.ApplicationInsights
// or if you want to capture logs from early in the application startup
// pipeline from Startup.cs or Program.cs itself.
builder.AddApplicationInsights(applicationInsightsKey);

Check warning on line 152 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (ubuntu-latest)

'ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights(ILoggingBuilder, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsights() overload which accepts Action<TelemetryConfiguration> and set TelemetryConfiguration.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

Check warning on line 152 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run integration tests against actual gitea

'ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights(ILoggingBuilder, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsights() overload which accepts Action<TelemetryConfiguration> and set TelemetryConfiguration.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

Check warning on line 152 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (windows-latest)

'ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights(ILoggingBuilder, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsights() overload which accepts Action<TelemetryConfiguration> and set TelemetryConfiguration.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

Check warning on line 152 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

'ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights(ILoggingBuilder, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsights() overload which accepts Action<TelemetryConfiguration> and set TelemetryConfiguration.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

// Optional: Apply filters to control what logs are sent to Application Insights.
// The following configures LogLevel Information or above to be sent to
Expand Down Expand Up @@ -213,7 +213,7 @@
// Add application insight telemetry
if (!string.IsNullOrEmpty(applicationInsightsKey))
{
services.AddApplicationInsightsTelemetry(applicationInsightsKey);

Check warning on line 216 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (ubuntu-latest)

'ApplicationInsightsExtensions.AddApplicationInsightsTelemetry(IServiceCollection, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsightsTelemetry() overload which accepts Action<ApplicationInsightsServiceOptions> and set ApplicationInsightsServiceOptions.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

Check warning on line 216 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run integration tests against actual gitea

'ApplicationInsightsExtensions.AddApplicationInsightsTelemetry(IServiceCollection, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsightsTelemetry() overload which accepts Action<ApplicationInsightsServiceOptions> and set ApplicationInsightsServiceOptions.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

Check warning on line 216 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (windows-latest)

'ApplicationInsightsExtensions.AddApplicationInsightsTelemetry(IServiceCollection, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsightsTelemetry() overload which accepts Action<ApplicationInsightsServiceOptions> and set ApplicationInsightsServiceOptions.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'

Check warning on line 216 in backend/src/Designer/Program.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

'ApplicationInsightsExtensions.AddApplicationInsightsTelemetry(IServiceCollection, string)' is obsolete: 'InstrumentationKey based global ingestion is being deprecated. Use the AddApplicationInsightsTelemetry() overload which accepts Action<ApplicationInsightsServiceOptions> and set ApplicationInsightsServiceOptions.ConnectionString. See https://github.com/microsoft/ApplicationInsights-dotnet/issues/2560 for more details.'
services.ConfigureTelemetryModule<EventCounterCollectionModule>(
(module, o) =>
{
Expand Down Expand Up @@ -249,6 +249,10 @@

// Auto register all settings classes
services.RegisterSettingsByBaseType<ISettingsMarker>(configuration);

// Registers all handlers and the mediator
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

logger.LogInformation("// Program.cs // ConfigureServices // Configuration complete");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,37 +56,6 @@
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(SemanticVersion version)
{
return typeof(ProcessModelingService).Assembly.GetManifestResourceNames()
Expand All @@ -101,7 +70,7 @@
throw new FileNotFoundException("Unknown template.");
}
string template = templates.Single(template => template.EndsWith(templateName));
return typeof(ProcessModelingService).Assembly.GetManifestResourceStream(template);

Check warning on line 73 in backend/src/Designer/Services/Implementation/ProcessModeling/ProcessModelingService.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (windows-latest)

Possible null reference return.

Check warning on line 73 in backend/src/Designer/Services/Implementation/ProcessModeling/ProcessModelingService.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

Possible null reference return.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,5 @@ 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
Expand Up @@ -5,6 +5,7 @@
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.ViewModels.Response;
using Designer.Tests.Controllers.ApiTests;
using Designer.Tests.Utils;
Expand Down

This file was deleted.

Loading
Loading