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

Feat/265 url param instantiation #1068

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
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
112 changes: 112 additions & 0 deletions src/Altinn.App.Api/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;

namespace Altinn.App.Api.Controllers;

Expand All @@ -27,6 +28,10 @@ public class HomeController : Controller
private readonly IAppResources _appResources;
private readonly IAppMetadata _appMetadata;
private readonly List<string> _onEntryWithInstance = new List<string> { "new-instance", "select-instance" };
private static readonly System.Text.Json.JsonSerializerOptions _jsonOptions = new()
{
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};

/// <summary>
/// Initialize a new instance of the <see cref="HomeController"/> class.
Expand Down Expand Up @@ -107,6 +112,113 @@ [FromQuery] bool dontChooseReportee
return Redirect(redirectUrl);
}

/// <summary>
/// Sets query parameters in frontend session storage
/// </summary>
/// <param name="org"></param>
/// <param name="app"></param>
/// <returns>An HTML file with a small javascript that will set session variables in frontend and redirect to the app.</returns>
[HttpGet]
[ApiExplorerSettings(IgnoreApi = true)]
[Route("{org}/{app}/set-query-params")]
public async Task<IActionResult> SetQueryParams(string org, string app)
{
var queryParams = HttpContext.Request.Query;

Application application = await _appMetadata.GetApplicationMetadata();

List<string> dataTypes = application.DataTypes.Select(type => type.Id).ToList();

// Build the modelPrefill dictionary
var modelPrefill = dataTypes
.Select(item =>
{
var prefillJson = _appResources.GetPrefillJson(item);
if (string.IsNullOrEmpty(prefillJson))
{
return null;
}

return new { DataModelName = item, PrefillConfiguration = JObject.Parse(prefillJson) };
})
.Where(item => item != null)
.ToList();

var result = modelPrefill
.Select(entry =>
{
if (entry == null || entry.PrefillConfiguration == null)
{
return null;
}

var prefillConfig = entry.PrefillConfiguration;

if (prefillConfig == null)
{
return null;
}

var queryParamsConfig = prefillConfig["QueryParams"];
if (queryParamsConfig == null || queryParamsConfig.Type != JTokenType.Object)
{
return null;
}

// Filter allowed query parameters. We only allow query params that are configured in
// <datamodel_name>.prefill.json
var allowedQueryParams = ((JObject)queryParamsConfig)
.Properties()
.Where(prop => queryParams.ContainsKey(prop.Name))
.Select(prop => new Dictionary<string, string>
{
{ prop.Value.ToString(), queryParams[prop.Name].ToString() },
})
.ToList();

return new
{
dataModelName = entry.DataModelName,
appId = application.Id,
prefillFields = allowedQueryParams,
};
})
.Where(entry => entry != null && entry.prefillFields != null && entry.prefillFields.Count > 0)
.ToList();

var safeResultJson = System.Text.Json.JsonSerializer.Serialize(result, _jsonOptions);
var encodedAppId = Uri.EscapeDataString(application.Id);

string nonce = Convert.ToBase64String(System.Security.Cryptography.RandomNumberGenerator.GetBytes(16));

var htmlContent =
$@"
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Set Query Params</title>
</head>
<body>
<script nonce='{nonce}'>

const prefillData = {safeResultJson}.map(entry => ({{
...entry,
expires: new Date(Date.now() + 60 * 60 * 1000).toISOString() // Expires in 1 hour
}}));
sessionStorage.setItem('queryParams', JSON.stringify(prefillData));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dette gjør vel at queryParams blir lagret for alle apper hos denne TE? Burde sikkert lagres bare for denne appen, og kanskje ha en viss levetid (slik at du ikke bruker noen gamle queryParams som har blitt liggende fra sist uke når du prøver å lage en ny instans manuelt).

const appOrg = decodeURIComponent('{encodedAppId}');
window.location.href = `${{window.location.origin}}/${{appOrg}}`;
</script>
</body>
</html>";

Response.Headers["Content-Security-Policy"] = $"default-src 'self'; script-src 'nonce-{nonce}';";

return Content(htmlContent, "text/html");
Fixed Show fixed Hide fixed
}

private async Task<bool> ShouldShowAppView()
{
if (User?.Identity?.IsAuthenticated == true)
Expand Down
Loading