Skip to content

Commit

Permalink
Merge branch 'main' into update-attachmentList-config-v4
Browse files Browse the repository at this point in the history
  • Loading branch information
lassopicasso committed Feb 6, 2024
2 parents 0b9d36a + 2108d11 commit f017dd5
Show file tree
Hide file tree
Showing 704 changed files with 40,254 additions and 1,973 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ on:
- main
paths:
- 'frontend/**'
- '.github/workflow/playwright.yml'
workflow_dispatch:
- '.github/workflows/playwright.yml'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
playwright-run:
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/run-cypress-on-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,16 @@ jobs:
working-directory: frontend/testing/cypress
env: environment=local
spec: src/integration/**/*.js
record: false
record: true
parallel: false

- name: Store artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-screenshots
path: frontend/testing/cypress/screenshots

- name: Stop compose file
if: always()
run: docker-compose down
7 changes: 4 additions & 3 deletions backend/packagegroups/NuGet.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</ItemGroup>

<ItemGroup Label="Shared nuget packages">
<PackageReference Update="JsonSchema.Net" Version="5.5.0" />
<PackageReference Update="JsonSchema.Net" Version="5.5.1" />
<PackageReference Update="CompilerAttributes" Version="1.1.2" />
<PackageReference Update="ini-parser-netstandard" Version="2.5.2" />
<PackageReference Update="JWTCookieAuthentication" Version="3.0.1" />
Expand All @@ -26,7 +26,7 @@
<PackageReference Update="Microsoft.Azure.Services.AppAuthentication" Version="1.6.2" />
<PackageReference Update="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.24" />
<PackageReference Update="Microsoft.VisualStudio.Web.BrowserLink" Version="2.2.0" />
<PackageReference Update="HtmlAgilityPack" Version="1.11.57" />
<PackageReference Update="HtmlAgilityPack" Version="1.11.58" />
<PackageReference Update="Microsoft.DiaSymReader.Native" Version="1.7.0" />
<PackageReference Update="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.16" />
<PackageReference Update="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.22" />
Expand All @@ -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 All @@ -45,7 +46,7 @@
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<!-- Do not upgrade Moq version from 4.18.4 -->
<PackageReference Update="Moq" Version="4.18.4" />
<PackageReference Update="xunit" Version="2.6.5" />
<PackageReference Update="xunit" Version="2.6.6" />
<PackageReference Update="xunit.runner.visualstudio" Version="2.5.6" />
<PackageReference Update="coverlet.collector" Version="6.0.0" />
<PackageReference Update="Basic.Reference.Assemblies" Version="1.4.5" />
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
28 changes: 28 additions & 0 deletions backend/src/Designer/Controllers/PreviewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ public IActionResult Index(string org, string app)
return View();
}

/// <summary>
/// Endpoint to fetch the cshtml to render app-frontend specific to what is defined in the app-repo
/// </summary>
/// <param name="org">Unique identifier of the organisation responsible for the app.</param>
/// <param name="app">Application identifier which is unique within an organisation.</param>
/// <returns>The cshtml modified to ignore this route path added in the iframe.</returns>
[HttpGet]
[Route("/app-specific-preview/{org}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}")]
public async Task<IActionResult> AppFrontendSpecificPreview(string org, string app)
{
string developer = AuthenticationHelper.GetDeveloperUserName(_httpContextAccessor.HttpContext);
AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, app, developer);
var appFrontendCshtml = await altinnAppGitRepository.GetAppFrontendCshtml();
var modifiedContent = ReplaceIndexToFetchCorrectOrgAppInCshtml(appFrontendCshtml);

return Content(modifiedContent, "text/html");
}

/// <summary>
/// Action for getting local app-images
/// </summary>
Expand Down Expand Up @@ -877,5 +895,15 @@ private string GetSelectedLayoutSetInEditorFromRefererHeader(string refererHeade

return string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
}

private string ReplaceIndexToFetchCorrectOrgAppInCshtml(string originalContent)
{
// Replace the array indexes in the script in the cshtml that retrieves the org and app name since
// /app-specific-preview/ is added when fetching the cshtml file from endpoint instead of designer wwwroot
string modifiedContent = originalContent.Replace("window.org = appId[1];", "window.org = appId[2];");
modifiedContent = modifiedContent.Replace("window.app = appId[2];", "window.app = appId[3];");

return modifiedContent;
}
}
}
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; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class AltinnAppGitRepository : AltinnGitRepository
private const string LANGUAGE_RESOURCE_FOLDER_NAME = "texts/";
private const string MARKDOWN_TEXTS_FOLDER_NAME = "md/";
private const string PROCESS_DEFINITION_FOLDER_PATH = "App/config/process/";
private const string CSHTML_PATH = "App/views/Home/index.cshtml";

private const string SERVICE_CONFIG_FILENAME = "config.json";
private const string LAYOUT_SETTINGS_FILENAME = "Settings.json";
Expand Down Expand Up @@ -701,6 +702,23 @@ public async Task<LayoutSets> CreateLayoutSetFile(string layoutSetName)
return layoutSets;
}

/// <summary>
/// Gets the cshtml file for the app
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
/// <returns>The content of Index.cshtml</returns>
public async Task<string> GetAppFrontendCshtml(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
if (FileExistsByRelativePath(CSHTML_PATH))
{
string cshtml = await ReadTextByRelativePathAsync(CSHTML_PATH, cancellationToken);
return cshtml;
}

throw new FileNotFoundException("Index.cshtml was not found.");
}

/// <summary>
/// Gets the options list with the provided id.
/// <param name="optionsListId">The id of the options list to fetch.</param>
Expand Down Expand Up @@ -854,8 +872,6 @@ private static string GetPathToRuleConfiguration(string layoutSetName)
Path.Combine(LAYOUTS_FOLDER_NAME, layoutSetName, RULE_CONFIGURATION_FILENAME);
}



/// <summary>
/// String writer that ensures UTF8 is used.
/// </summary>
Expand Down
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 @@ -249,6 +249,10 @@ void ConfigureServices(IServiceCollection services, IConfiguration configuration

// 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
Loading

0 comments on commit f017dd5

Please sign in to comment.