diff --git a/loadbalancer/templates/nginx.conf.conf b/loadbalancer/templates/nginx.conf.conf index 451c463d..7e26c95d 100644 --- a/loadbalancer/templates/nginx.conf.conf +++ b/loadbalancer/templates/nginx.conf.conf @@ -31,7 +31,7 @@ http { sendfile on; - upstream localtest { + upstream localtest { server host.docker.internal:5101; } @@ -58,7 +58,7 @@ http { } server { - listen 80 default_server; + listen 80 default_server; server_name ${TEST_DOMAIN}; proxy_redirect off; @@ -68,52 +68,53 @@ http { error_page 502 /502LocalTest.html; - location = / { + location = / { proxy_pass http://localtest/Home/; sub_filter '' ''; - } + } - location / { + location / { #Support using Local js, when a cookie value is set sub_filter_once off; sub_filter 'https://altinncdn.no/toolkits/altinn-app-frontend/3/' $LOCAL_SUB_FILTER; proxy_pass http://app/; error_page 502 /502App.html; proxy_cookie_domain altinn3local.no local.altinn.cloud; - } + } location /Home/_framework/ { - proxy_pass http://localtest/_framework/; + proxy_pass http://localtest/_framework/; } - location /Home/ { - proxy_pass http://localtest/Home/; + location /Home/ { + proxy_pass http://localtest/Home/; sub_filter '' ''; - } + } location /receipt/ { - proxy_pass http://receiptcomp/receipt/; - error_page 502 /502Receipt.html; - } + proxy_pass http://receiptcomp/receipt/; + error_page 502 /502Receipt.html; + } location /accessmanagement/ { - proxy_pass http://accessmanagementcomp/accessmanagement/; + proxy_pass http://accessmanagementcomp/accessmanagement/; error_page 502 /502Accessmanagement.html; - } + } location /storage/ { - proxy_pass http://localtest/storage/; - } + proxy_pass http://localtest/storage/; + } location /pdfservice/ { proxy_pass http://pdfservice/; } location /localtestresources/ { - proxy_pass http://localtest/localtestresources/; - } + proxy_pass http://localtest/localtestresources/; + } location /LocalPlatformStorage/ { - proxy_pass http://localtest/LocalPlatformStorage/; + proxy_pass http://localtest/LocalPlatformStorage/; + sub_filter '' ''; } location /502LocalTest.html { root /www; @@ -128,5 +129,5 @@ http { root /www; } - } + } } diff --git a/src/Configuration/LocalPlatformSettings.cs b/src/Configuration/LocalPlatformSettings.cs index 6f5c5231..8b3aadcb 100644 --- a/src/Configuration/LocalPlatformSettings.cs +++ b/src/Configuration/LocalPlatformSettings.cs @@ -68,5 +68,7 @@ public string LocalTestingStaticTestDataPath { public string RolesFolder { get; set; } = "roles/"; public string ClaimsFolder { get; set; } = "claims/"; + + public string TenorDataFolder { get; set; } = "tenorUsers"; } } diff --git a/src/Controllers/DebugUsersController.cs b/src/Controllers/DebugUsersController.cs new file mode 100644 index 00000000..d31012bc --- /dev/null +++ b/src/Controllers/DebugUsersController.cs @@ -0,0 +1,65 @@ +#nullable enable + +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; + + +using LocalTest.Configuration; + +using LocalTest.Services.TestData; +using Microsoft.AspNetCore.Authorization; + +namespace LocalTest.Controllers; + +[Route("Home/[controller]/[action]")] +public class DebugUsersController : Controller +{ + private readonly LocalPlatformSettings _localPlatformSettings; + private readonly TenorDataRepository _tenorDataRepository; + + public DebugUsersController( + IOptions localPlatformSettings, + TenorDataRepository tenorDataRepository) + { + _localPlatformSettings = localPlatformSettings.Value; + _tenorDataRepository = tenorDataRepository; + } + + // Debugging endpoint + [AllowAnonymous] + public async Task LocalTestUsersRaw() + { + var localData = await TestDataDiskReader.ReadFromDisk(_localPlatformSettings.LocalTestingStaticTestDataPath); + + return Json(localData); + } + + //Debugging endpoint + [AllowAnonymous] + public async Task LocalTestUsers() + { + var localData = await TestDataDiskReader.ReadFromDisk(_localPlatformSettings.LocalTestingStaticTestDataPath); + var constructedAppData = AppTestDataModel.FromTestDataModel(localData); + + return Json(constructedAppData); + } + + // Debugging endpoint + [AllowAnonymous] + public async Task LocalTestUsersRoundTrip() + { + var localData = await TestDataDiskReader.ReadFromDisk(_localPlatformSettings.LocalTestingStaticTestDataPath); + var constructedAppData = AppTestDataModel.FromTestDataModel(localData); + + return Json(constructedAppData.GetTestDataModel()); + } + + // Debugging endpoint + [AllowAnonymous] + public async Task ShowTenorUsers() + { + var localData = await _tenorDataRepository.GetAppTestDataModel(); + + return Json(localData); + } +} \ No newline at end of file diff --git a/src/Controllers/FrontendVersionController.cs b/src/Controllers/FrontendVersionController.cs new file mode 100644 index 00000000..74db638f --- /dev/null +++ b/src/Controllers/FrontendVersionController.cs @@ -0,0 +1,87 @@ +#nullable enable +using System.Text.Json; + +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; + +using LocalTest.Configuration; +using LocalTest.Models; +using LocalTest.Services.LocalApp.Interface; + +using LocalTest.Services.TestData; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Mvc.Rendering; + +namespace LocalTest.Controllers; + +[Route("Home/[controller]/[action]")] +public class FrontendVersionController : Controller +{ + /// + /// See src\development\loadbalancer\nginx.conf + /// + public static readonly string FRONTEND_URL_COOKIE_NAME = "frontendVersion"; + + [HttpGet] + public async Task Index([FromServices] HttpClient client) + { + var versionFromCookie = HttpContext.Request.Cookies[FRONTEND_URL_COOKIE_NAME]; + + var frontendVersion = new FrontendVersion() + { + Version = versionFromCookie, + Versions = new List() + { + new () + { + Text = "Keep as is", + Value = "", + }, + new () + { + Text = "localhost:8080 (local dev)", + Value = "http://localhost:8080/" + } + } + }; + var cdnVersionsString = await client.GetStringAsync("https://altinncdn.no/toolkits/altinn-app-frontend/index.json"); + var groupCdnVersions = new SelectListGroup() { Name = "Specific version from cdn" }; + var versions = JsonSerializer.Deserialize>(cdnVersionsString)!; + versions.Reverse(); + versions.ForEach(version => + { + frontendVersion.Versions.Add(new() + { + Text = version, + Value = $"https://altinncdn.no/toolkits/altinn-app-frontend/{version}/", + Group = groupCdnVersions + }); + }); + + return View(frontendVersion); + } + public ActionResult Index(FrontendVersion frontendVersion) + { + var options = new CookieOptions + { + Expires = DateTime.MaxValue, + HttpOnly = true, + }; + ICookieManager cookieManager = new ChunkingCookieManager(); + if (string.IsNullOrWhiteSpace(frontendVersion.Version)) + { + cookieManager.DeleteCookie(HttpContext, FRONTEND_URL_COOKIE_NAME, options); + } + else + { + cookieManager.AppendResponseCookie( + HttpContext, + FRONTEND_URL_COOKIE_NAME, + frontendVersion.Version, + options + ); + } + + return RedirectToAction("Index", "Home"); + } +} \ No newline at end of file diff --git a/src/Controllers/HomeController.cs b/src/Controllers/HomeController.cs index 0fa01b82..945b881c 100644 --- a/src/Controllers/HomeController.cs +++ b/src/Controllers/HomeController.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Text.Json; using System.Xml; using Microsoft.AspNetCore.Authentication; @@ -24,6 +23,7 @@ namespace LocalTest.Controllers { + [Route("/Home/[action]")] public class HomeController : Controller { private readonly GeneralSettings _generalSettings; @@ -32,7 +32,7 @@ public class HomeController : Controller private readonly IAuthentication _authenticationService; private readonly IApplicationRepository _applicationRepository; private readonly IParties _partiesService; - private readonly IClaims _claimsService; + private readonly ILocalApp _localApp; private readonly TestDataService _testDataService; @@ -43,7 +43,6 @@ public HomeController( IAuthentication authenticationService, IApplicationRepository applicationRepository, IParties partiesService, - IClaims claimsService, ILocalApp localApp, TestDataService testDataService) { @@ -53,40 +52,14 @@ public HomeController( _authenticationService = authenticationService; _applicationRepository = applicationRepository; _partiesService = partiesService; - _claimsService = claimsService; _localApp = localApp; _testDataService = testDataService; } [AllowAnonymous] - public async Task LocalTestUsersRaw() - { - var localData = await TestDataDiskReader.ReadFromDisk(_localPlatformSettings.LocalTestingStaticTestDataPath); - - return Json(localData); - } - - //Debugging endpoint - [AllowAnonymous] - public async Task LocalTestUsers() - { - var localData = await TestDataDiskReader.ReadFromDisk(_localPlatformSettings.LocalTestingStaticTestDataPath); - var constructedAppData = AppTestDataModel.FromTestDataModel(localData); - - return Json(constructedAppData); - } - - // Debugging endpoint - [AllowAnonymous] - public async Task LocalTestUsersRoundTrip() - { - var localData = await TestDataDiskReader.ReadFromDisk(_localPlatformSettings.LocalTestingStaticTestDataPath); - var constructedAppData = AppTestDataModel.FromTestDataModel(localData); - - return Json(constructedAppData.GetTestDataModel()); - } - - [AllowAnonymous] + [HttpGet("/")] + [HttpGet("/Home")] + [HttpGet("/Home/Index")] public async Task Index() { StartAppModel model = new StartAppModel() @@ -95,7 +68,7 @@ public async Task Index() AppPath = _localPlatformSettings.AppRepositoryBasePath, StaticTestDataPath = _localPlatformSettings.LocalTestingStaticTestDataPath, LocalAppUrl = _localPlatformSettings.LocalAppUrl, - LocalFrontendUrl = HttpContext.Request.Cookies[FRONTEND_URL_COOKIE_NAME], + LocalFrontendUrl = HttpContext.Request.Cookies[FrontendVersionController.FRONTEND_URL_COOKIE_NAME], }; try @@ -234,76 +207,6 @@ public async Task GetTestOrgToken(string id, [FromQuery] string or return Ok(token); } - /// - /// See src\development\loadbalancer\nginx.conf - /// - public static readonly string FRONTEND_URL_COOKIE_NAME = "frontendVersion"; - - [HttpGet] - public async Task FrontendVersion([FromServices] HttpClient client) - { - var versionFromCookie = HttpContext.Request.Cookies[FRONTEND_URL_COOKIE_NAME]; - - - - var frontendVersion = new FrontendVersion() - { - Version = versionFromCookie, - Versions = new List() - { - new () - { - Text = "Keep as is", - Value = "", - }, - new () - { - Text = "localhost:8080 (local dev)", - Value = "http://localhost:8080/" - } - } - }; - var cdnVersionsString = await client.GetStringAsync("https://altinncdn.no/toolkits/altinn-app-frontend/index.json"); - var groupCdnVersions = new SelectListGroup() { Name = "Specific version from cdn" }; - var versions = JsonSerializer.Deserialize>(cdnVersionsString); - versions.Reverse(); - versions.ForEach(version => - { - frontendVersion.Versions.Add(new() - { - Text = version, - Value = $"https://altinncdn.no/toolkits/altinn-app-frontend/{version}/", - Group = groupCdnVersions - }); - }); - - return View(frontendVersion); - } - public ActionResult FrontendVersion(FrontendVersion frontendVersion) - { - var options = new CookieOptions - { - Expires = DateTime.MaxValue, - HttpOnly = true, - }; - ICookieManager cookieManager = new ChunkingCookieManager(); - if (string.IsNullOrWhiteSpace(frontendVersion.Version)) - { - cookieManager.DeleteCookie(HttpContext, FRONTEND_URL_COOKIE_NAME, options); - } - else - { - cookieManager.AppendResponseCookie( - HttpContext, - FRONTEND_URL_COOKIE_NAME, - frontendVersion.Version, - options - ); - } - - return RedirectToAction("Index"); - } - private async Task> GetTestUsersForList() { var data = await _testDataService.GetTestData(); diff --git a/src/Controllers/StorageExplorerController.cs b/src/Controllers/StorageExplorerController.cs new file mode 100644 index 00000000..7085cf93 --- /dev/null +++ b/src/Controllers/StorageExplorerController.cs @@ -0,0 +1,14 @@ +#nullable enable + +using Microsoft.AspNetCore.Mvc; + +namespace LocalTest.Controllers; + +[Route("Home/[controller]/[action]")] +public class StorageExplorerController : Controller +{ + public IActionResult Index() + { + return View(); + } +} \ No newline at end of file diff --git a/src/Controllers/TenorUsersController.cs b/src/Controllers/TenorUsersController.cs new file mode 100644 index 00000000..d5c39abe --- /dev/null +++ b/src/Controllers/TenorUsersController.cs @@ -0,0 +1,73 @@ +#nullable enable +using System.Text.Json; + +using Microsoft.AspNetCore.Mvc; +using LocalTest.Models; +using LocalTest.Services.LocalApp.Interface; + +using LocalTest.Services.TestData; + +namespace LocalTest.Controllers; + +[Route("Home/[controller]/[action]")] +public class TenorUsersController : Controller +{ + private readonly TenorDataRepository _tenorDataRepository; + + public TenorUsersController(TenorDataRepository tenorDataRepository) + { + _tenorDataRepository = tenorDataRepository; + } + + + + public async Task Index() + { + return View(new TenorViewModel() + { + FileItems = await _tenorDataRepository.GetFileItems(), + }); + } + + + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Upload() + { + //TODO: validate uploaded files + foreach (var file in Request.Form.Files) + { + await _tenorDataRepository.StoreUploadedFile(file); + } + return RedirectToAction("Index"); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Update() + { + var files = Request.Form.Keys.Where(k => k.EndsWith(".json")).ToList(); + if (Request.Form.ContainsKey("Download")) + { + return Json(await _tenorDataRepository.GetAppTestDataModel(files)); + } + else if (Request.Form.ContainsKey("DownloadFile")) + { + return File(JsonSerializer.SerializeToUtf8Bytes(await _tenorDataRepository.GetAppTestDataModel(files)), "application/json", "testData.json"); + } + else if (Request.Form.ContainsKey("Delete")) + { + foreach (var file in files) + { + _tenorDataRepository.DeleteFile(file); + } + + return RedirectToAction("Index"); + } + else + { + throw new Exception("Unknown action"); + } + } +} \ No newline at end of file diff --git a/src/Models/Authentication/CustomClaim.cs b/src/Models/Authentication/CustomClaim.cs index 9283c96c..1d14df2e 100644 --- a/src/Models/Authentication/CustomClaim.cs +++ b/src/Models/Authentication/CustomClaim.cs @@ -1,21 +1,26 @@ -namespace Altinn.Platform.Authentication.Model +using System.Text.Json.Serialization; + +namespace Altinn.Platform.Authentication.Model { public class CustomClaim { /// /// Gets or sets the claim type, E.g. custom:claim /// + [JsonPropertyName("type")] public string Type { get; set; } /// /// Gets or sets the claim value, E.g. customValue /// + [JsonPropertyName("value")] public string Value { get; set; } /// /// Gets or sets the value type for the claim, E.g. http://www.w3.org/2001/XMLSchema#string /// See System.Security.Claims.ClaimValueTypes for more value types /// + [JsonPropertyName("valueType")] public string ValueType { get; set; } } } diff --git a/src/Models/Authorization/Role.cs b/src/Models/Authorization/Role.cs index a67fe7f6..17acdf07 100644 --- a/src/Models/Authorization/Role.cs +++ b/src/Models/Authorization/Role.cs @@ -1,7 +1,5 @@ using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Text; +using System.Text.Json.Serialization; namespace Authorization.Interface.Models { @@ -15,12 +13,14 @@ public class Role /// Gets or sets the role type /// [JsonProperty] + [JsonPropertyName("type")] public string Type { get; set; } /// /// Gets or sets the role /// [JsonProperty] + [JsonPropertyName("value")] public string Value { get; set; } } } diff --git a/src/Models/TenorViewModel.cs b/src/Models/TenorViewModel.cs new file mode 100644 index 00000000..d1cb4d9a --- /dev/null +++ b/src/Models/TenorViewModel.cs @@ -0,0 +1,19 @@ +#nullable enable +namespace LocalTest.Models; + +using LocalTest.Services.Tenor.Models; +using LocalTest.Services.TestData; + +public class TenorViewModel +{ + public List FileItems { get; set; } = default!; +} + +public class TenorFileItem +{ + public string FileName { get; set; } = default!; + public string RawFileContent { get; set; } = default!; + public bool Valid => Freg is not null || Brreg is not null; + public Freg? Freg { get; set; } + public BrregErFr? Brreg { get; set; } +} \ No newline at end of file diff --git a/src/Services/Tenor/Models/BrregErFr.cs b/src/Services/Tenor/Models/BrregErFr.cs new file mode 100644 index 00000000..1cdda1c3 --- /dev/null +++ b/src/Services/Tenor/Models/BrregErFr.cs @@ -0,0 +1,365 @@ +#nullable disable +namespace LocalTest.Services.Tenor.Models; + + +using System.Text.Json.Serialization; + +public class BrregErFr +{ + /// + /// Internally assigned property that is Altinn's inernal ID + /// + [JsonIgnore] + public int PartyId { get; set; } + + [JsonPropertyName("organisasjonsnummer")] + public string Organisasjonsnummer { get; set; } + + [JsonPropertyName("navn")] + public string Navn { get; set; } + + [JsonPropertyName("oppdeltNavn")] + public List OppdeltNavn { get; set; } + + [JsonPropertyName("organisasjonsform")] + public Organisasjonsform Organisasjonsform { get; set; } + + [JsonPropertyName("forretningsadresse")] + public Forretningsadresse Forretningsadresse { get; set; } + + [JsonPropertyName("postadresse")] + public Postadresse Postadresse { get; set; } + + [JsonPropertyName("naeringskoder")] + public List Naeringskoder { get; set; } + + [JsonPropertyName("institusjonellSektorkode")] + public InstitusjonellSektorkode InstitusjonellSektorkode { get; set; } + + [JsonPropertyName("registreringsdatoEnhetsregisteret")] + public string RegistreringsdatoEnhetsregisteret { get; set; } + + [JsonPropertyName("slettetIEnhetsregisteret")] + public string SlettetIEnhetsregisteret { get; set; } + + [JsonPropertyName("registrertIForetaksregisteret")] + public string RegistrertIForetaksregisteret { get; set; } + + [JsonPropertyName("registreringsdatoForetaksregisteret")] + public string RegistreringsdatoForetaksregisteret { get; set; } + + [JsonPropertyName("slettetIForetaksregisteret")] + public string SlettetIForetaksregisteret { get; set; } + + [JsonPropertyName("registreringspliktigForetaksregisteret")] + public string RegistreringspliktigForetaksregisteret { get; set; } + + [JsonPropertyName("registrertIFrivillighetsregisteret")] + public string RegistrertIFrivillighetsregisteret { get; set; } + + [JsonPropertyName("registrertIStiftelsesregisteret")] + public string RegistrertIStiftelsesregisteret { get; set; } + + [JsonPropertyName("registrertIMvaregisteret")] + public string RegistrertIMvaregisteret { get; set; } + + [JsonPropertyName("stiftelsesdato")] + public string Stiftelsesdato { get; set; } + + [JsonPropertyName("aktivitetBransje")] + public List AktivitetBransje { get; set; } + + [JsonPropertyName("vedtektsdato")] + public string Vedtektsdato { get; set; } + + [JsonPropertyName("vedtektsfestetFormaal")] + public List VedtektsfestetFormaal { get; set; } + + [JsonPropertyName("sisteInnsendteAarsregnskap")] + public string SisteInnsendteAarsregnskap { get; set; } + + [JsonPropertyName("konkurs")] + public string Konkurs { get; set; } + + [JsonPropertyName("underAvvikling")] + public string UnderAvvikling { get; set; } + + [JsonPropertyName("underTvangsavviklingEllerTvangsopplosning")] + public string UnderTvangsavviklingEllerTvangsopplosning { get; set; } + + [JsonPropertyName("maalform")] + public string Maalform { get; set; } + + [JsonPropertyName("ansvarsbegrensning")] + public string Ansvarsbegrensning { get; set; } + + [JsonPropertyName("harAnsatte")] + public string HarAnsatte { get; set; } + + [JsonPropertyName("antallAnsatte")] + public int? AntallAnsatte { get; set; } + + [JsonPropertyName("underenhet")] + public Underenhet Underenhet { get; set; } + + [JsonPropertyName("bedriftsforsamling")] + public string Bedriftsforsamling { get; set; } + + [JsonPropertyName("representantskap")] + public string Representantskap { get; set; } + + [JsonPropertyName("enhetstatuser")] + public List Enhetstatuser { get; set; } + + [JsonPropertyName("fullmakter")] + public List Fullmakter { get; set; } + + [JsonPropertyName("frivilligMvaRegistrert")] + public List FrivilligMvaRegistrert { get; set; } + + [JsonPropertyName("finansielleInstrumenter")] + public List FinansielleInstrumenter { get; set; } + + [JsonPropertyName("kapital")] + public Kapital Kapital { get; set; } + + [JsonPropertyName("kjonnsrepresentasjon")] + public string Kjonnsrepresentasjon { get; set; } + + [JsonPropertyName("matrikkelnummer")] + public List Matrikkelnummer { get; set; } + + [JsonPropertyName("paategninger")] + public List Paategninger { get; set; } + + [JsonPropertyName("fravalgAvRevisjon")] + public FravalgAvRevisjon FravalgAvRevisjon { get; set; } + + [JsonPropertyName("norskregistrertUtenlandskForetak")] + public NorskregistrertUtenlandskForetak NorskregistrertUtenlandskForetak { get; set; } + + [JsonPropertyName("lovgivningOgForetaksformIHjemlandet")] + public LovgivningOgForetaksformIHjemlandet LovgivningOgForetaksformIHjemlandet { get; set; } + + [JsonPropertyName("registerIHjemlandet")] + public RegisterIHjemlandet RegisterIHjemlandet { get; set; } + + [JsonPropertyName("fusjoner")] + public List Fusjoner { get; set; } + + [JsonPropertyName("fisjoner")] + public List Fisjoner { get; set; } + + [JsonPropertyName("rollegrupper")] + public List Rollegrupper { get; set; } +} + +public class Forretningsadresse +{ + [JsonPropertyName("land")] + public string Land { get; set; } + + [JsonPropertyName("landkode")] + public string Landkode { get; set; } + + [JsonPropertyName("postnummer")] + public string Postnummer { get; set; } + + [JsonPropertyName("poststed")] + public string Poststed { get; set; } + + [JsonPropertyName("adresse")] + public List Adresse { get; set; } + + [JsonPropertyName("kommune")] + public string Kommune { get; set; } + + [JsonPropertyName("kommunenummer")] + public string Kommunenummer { get; set; } +} + +public class FravalgAvRevisjon +{ + [JsonPropertyName("fravalg")] + public string Fravalg { get; set; } +} + +public class Fritekst +{ + [JsonPropertyName("plassering")] + public string Plassering { get; set; } +} + +public class InstitusjonellSektorkode +{ + [JsonPropertyName("kode")] + public string Kode { get; set; } + + [JsonPropertyName("beskrivelse")] + public string Beskrivelse { get; set; } +} + +public class Kapital +{ + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("belop")] + public string Belop { get; set; } + + [JsonPropertyName("antallAksjer")] + public string AntallAksjer { get; set; } + + [JsonPropertyName("innbetaltBelop")] + public string InnbetaltBelop { get; set; } + + [JsonPropertyName("fritekst")] + public List Fritekst { get; set; } + + [JsonPropertyName("fulltInnbetaltBelop")] + public string FulltInnbetaltBelop { get; set; } + + [JsonPropertyName("sakkyndigRedegjorelse")] + public string SakkyndigRedegjorelse { get; set; } +} + +public class LovgivningOgForetaksformIHjemlandet +{ + [JsonPropertyName("foretaksform")] + public string Foretaksform { get; set; } +} + +public class Naeringskoder +{ + [JsonPropertyName("kode")] + public string Kode { get; set; } + + [JsonPropertyName("beskrivelse")] + public string Beskrivelse { get; set; } + + [JsonPropertyName("hjelpeenhetskode")] + public bool? Hjelpeenhetskode { get; set; } + + [JsonPropertyName("rekkefolge")] + public int? Rekkefolge { get; set; } + + [JsonPropertyName("nivaa")] + public int? Nivaa { get; set; } +} + +public class NorskregistrertUtenlandskForetak +{ + [JsonPropertyName("helNorskEierskap")] + public string HelNorskEierskap { get; set; } + + [JsonPropertyName("aktivitetINorge")] + public string AktivitetINorge { get; set; } +} + +public class Organisasjonsform +{ + [JsonPropertyName("kode")] + public string Kode { get; set; } + + [JsonPropertyName("beskrivelse")] + public string Beskrivelse { get; set; } +} + +public class Person +{ + [JsonPropertyName("foedselsnummer")] + public string Foedselsnummer { get; set; } +} + +public class Postadresse +{ + [JsonPropertyName("land")] + public string Land { get; set; } + + [JsonPropertyName("landkode")] + public string Landkode { get; set; } + + [JsonPropertyName("postnummer")] + public string Postnummer { get; set; } + + [JsonPropertyName("poststed")] + public string Poststed { get; set; } + + [JsonPropertyName("adresse")] + public List Adresse { get; set; } + + [JsonPropertyName("kommune")] + public string Kommune { get; set; } + + [JsonPropertyName("kommunenummer")] + public string Kommunenummer { get; set; } +} + +public class RegisterIHjemlandet +{ + [JsonPropertyName("navnRegister")] + public List NavnRegister { get; set; } + + [JsonPropertyName("adresse")] + public List Adresse { get; set; } +} + +public class Rollegrupper +{ + [JsonPropertyName("type")] + public Type Type { get; set; } + + [JsonPropertyName("fritekst")] + public List Fritekst { get; set; } + + [JsonPropertyName("roller")] + public List Roller { get; set; } +} + +public class Roller +{ + [JsonPropertyName("type")] + public Type Type { get; set; } + + [JsonPropertyName("person")] + public Person Person { get; set; } + + [JsonPropertyName("virksomhet")] + public Virksomhet Virksomhet { get; set; } + + [JsonPropertyName("valgtAv")] + public ValgtAv ValgtAv { get; set; } + + [JsonPropertyName("fratraadt")] + public string Fratraadt { get; set; } + + [JsonPropertyName("fritekst")] + public List Fritekst { get; set; } + + [JsonPropertyName("rekkefolge")] + public int? Rekkefolge { get; set; } +} + + + +public class Type +{ + [JsonPropertyName("kode")] + public string Kode { get; set; } + + [JsonPropertyName("beskrivelse")] + public string Beskrivelse { get; set; } +} + +public class Underenhet +{ +} + +public class ValgtAv +{ +} + +public class Virksomhet +{ +} + diff --git a/src/Services/Tenor/Models/Freg.cs b/src/Services/Tenor/Models/Freg.cs new file mode 100644 index 00000000..5c6b3842 --- /dev/null +++ b/src/Services/Tenor/Models/Freg.cs @@ -0,0 +1,342 @@ +#nullable disable +namespace LocalTest.Services.Tenor.Models; + +using System.Text.Json.Serialization; + +public class Freg +{ + /// + /// Internally assigned property that is Altinn's inernal ID + /// + [JsonIgnore] + public int PartyId { get; set; } + + [JsonPropertyName("identifikasjonsnummer")] + public List Identifikasjonsnummer { get; set; } + + [JsonPropertyName("status")] + public List Status { get; set; } + + [JsonPropertyName("kjoenn")] + public List Kjoenn { get; set; } + + [JsonPropertyName("foedsel")] + public List Foedsel { get; set; } + + [JsonPropertyName("foedselINorge")] + public List FoedselINorge { get; set; } + + [JsonPropertyName("familierelasjon")] + public List Familierelasjon { get; set; } + + [JsonPropertyName("sivilstand")] + public List Sivilstand { get; set; } + + [JsonPropertyName("navn")] + public List Navn { get; set; } + + [JsonPropertyName("bostedsadresse")] + public List Bostedsadresse { get; set; } + + [JsonPropertyName("statsborgerskap")] + public List Statsborgerskap { get; set; } +} + +public class Adressenummer +{ + [JsonPropertyName("husnummer")] + public string Husnummer { get; set; } +} + +public class Bostedsadresse +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("aarsak")] + public string Aarsak { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("vegadresse")] + public Vegadresse Vegadresse { get; set; } + + [JsonPropertyName("adresseIdentifikatorFraMatrikkelen")] + public string AdresseIdentifikatorFraMatrikkelen { get; set; } + + [JsonPropertyName("adressegradering")] + public string Adressegradering { get; set; } + + [JsonPropertyName("flyttedato")] + public string Flyttedato { get; set; } + + [JsonPropertyName("grunnkrets")] + public int? Grunnkrets { get; set; } + + [JsonPropertyName("stemmekrets")] + public int? Stemmekrets { get; set; } + + [JsonPropertyName("skolekrets")] + public int? Skolekrets { get; set; } + + [JsonPropertyName("kirkekrets")] + public int? Kirkekrets { get; set; } +} + +public class Familierelasjon +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("aarsak")] + public string Aarsak { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("relatertPerson")] + public string RelatertPerson { get; set; } + + [JsonPropertyName("relatertPersonsRolle")] + public string RelatertPersonsRolle { get; set; } + + [JsonPropertyName("minRolleForPerson")] + public string MinRolleForPerson { get; set; } +} + +public class Foedsel +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("foedselsdato")] + public string Foedselsdato { get; set; } + + [JsonPropertyName("foedselsaar")] + public string Foedselsaar { get; set; } + + [JsonPropertyName("foedekommuneINorge")] + public string FoedekommuneINorge { get; set; } + + [JsonPropertyName("foedeland")] + public string Foedeland { get; set; } +} + +public class FoedselINorge +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("aarsak")] + public string Aarsak { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("foedselsinstitusjonsnavn")] + public string Foedselsinstitusjonsnavn { get; set; } + + [JsonPropertyName("rekkefoelgenummer")] + public int? Rekkefoelgenummer { get; set; } +} + +public class Identifikasjonsnummer +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("foedselsEllerDNummer")] + public string FoedselsEllerDNummer { get; set; } + + [JsonPropertyName("identifikatortype")] + public string Identifikatortype { get; set; } +} + +public class KjoennType +{ + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("kjoenn")] + public string Kjoenn { get; set; } +} + +public class Navn +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("aarsak")] + public string Aarsak { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("fornavn")] + public string Fornavn { get; set; } + + [JsonPropertyName("mellomnavn")] + public string Mellomnavn { get; set; } + + [JsonPropertyName("etternavn")] + public string Etternavn { get; set; } +} + +public class Poststed +{ + [JsonPropertyName("poststedsnavn")] + public string Poststedsnavn { get; set; } + + [JsonPropertyName("postnummer")] + public string Postnummer { get; set; } +} + + +public class SivilstandType +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("aarsak")] + public string Aarsak { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("sivilstand")] + public string Sivilstand { get; set; } + + [JsonPropertyName("sivilstandsdato")] + public string Sivilstandsdato { get; set; } + + [JsonPropertyName("myndighet")] + public string Myndighet { get; set; } + + [JsonPropertyName("kommune")] + public string Kommune { get; set; } + + [JsonPropertyName("sted")] + public string Sted { get; set; } + + [JsonPropertyName("relatertVedSivilstand")] + public string RelatertVedSivilstand { get; set; } +} + +public class StatsborgerskapType +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("aarsak")] + public string Aarsak { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("statsborgerskap")] + public string Statsborgerskap { get; set; } + + [JsonPropertyName("ervervsdato")] + public string Ervervsdato { get; set; } +} + +public class StatusType +{ + [JsonPropertyName("ajourholdstidspunkt")] + public DateTime? Ajourholdstidspunkt { get; set; } + + [JsonPropertyName("erGjeldende")] + public bool? ErGjeldende { get; set; } + + [JsonPropertyName("kilde")] + public string Kilde { get; set; } + + [JsonPropertyName("gyldighetstidspunkt")] + public DateTime? Gyldighetstidspunkt { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } +} + +public class Vegadresse +{ + [JsonPropertyName("kommunenummer")] + public string Kommunenummer { get; set; } + + [JsonPropertyName("bruksenhetsnummer")] + public string Bruksenhetsnummer { get; set; } + + [JsonPropertyName("bruksenhetstype")] + public string Bruksenhetstype { get; set; } + + [JsonPropertyName("adressenavn")] + public string Adressenavn { get; set; } + + [JsonPropertyName("adressenummer")] + public Adressenummer Adressenummer { get; set; } + + [JsonPropertyName("adressekode")] + public string Adressekode { get; set; } + + [JsonPropertyName("poststed")] + public Poststed Poststed { get; set; } +} + diff --git a/src/Services/Tenor/TenorDataReader.cs b/src/Services/Tenor/TenorDataReader.cs new file mode 100644 index 00000000..d41cfa6c --- /dev/null +++ b/src/Services/Tenor/TenorDataReader.cs @@ -0,0 +1,199 @@ +#nullable enable +using System.Text.Json; +using Authorization.Interface.Models; +using LocalTest.Configuration; +using LocalTest.Models; +using LocalTest.Services.Tenor.Models; +using Microsoft.Extensions.Options; + +namespace LocalTest.Services.TestData; + +public class TenorDataRepository +{ + private static readonly JsonSerializerOptions _options = new(JsonSerializerDefaults.Web) + { + Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() } + }; + private readonly LocalPlatformSettings _settings; + + public TenorDataRepository(IOptions settings) + { + _settings = settings.Value; + } + + public DirectoryInfo GetTenorStorageDirectory() + { + var dir = new DirectoryInfo(Path.Join(_settings.LocalTestingStorageBasePath, _settings.TenorDataFolder)); + if (!dir.Exists) + { + dir.Create(); + } + return dir; + } + + + public async Task<(List, List)> ReadFromDisk(List? files = null) + { + var freg = new List(); + var brregErFr = new List(); + var tenorFolder = GetTenorStorageDirectory(); + + foreach (var fregFile in tenorFolder.GetFiles("freg.*.kildedata.json").Where(f => files?.Contains(f.Name) ?? true)) + { + var fileBytes = await File.ReadAllBytesAsync(fregFile.FullName); + var fileData = JsonSerializer.Deserialize(fileBytes, _options); + if (fileData is not null) + freg.Add(fileData); + } + foreach (var brregFile in tenorFolder.GetFiles("brreg-er-fr.*.kildedata.json").Where(f => files?.Contains(f.Name) ?? true)) + { + var fileBytes = await File.ReadAllBytesAsync(brregFile.FullName); + var fileData = JsonSerializer.Deserialize(fileBytes, _options); + if (fileData is not null) + brregErFr.Add(fileData); + } + + return (brregErFr, freg); + } + + public async Task GetAppTestDataModel(List? files = null) + { + var (brreg, freg) = await ReadFromDisk(files); + // Assign partyId to all entities + int partyId = 600000; + freg.ForEach(f => f.PartyId = partyId++); + partyId = 700000; + brreg.ForEach(b => b.PartyId = partyId++); + + + var roles = brreg.SelectMany(b => b.Rollegrupper.SelectMany(rg => rg.Roller.Select(r => (b.PartyId, r.Type.Kode, r.Person.Foedselsnummer)))).Where(r => r.Foedselsnummer is not null); + var fnrRoleLookup = roles.GroupBy(r => r.Foedselsnummer).ToDictionary(role => role.Key, role => role.GroupBy(r => r.PartyId).ToDictionary(k => k.Key, k => k.Select(tuple => new Role { Type = "Altinn", Value = tuple.Kode }).ToList())); + + + int userId = 10000; + return new() + { + Persons = freg.Select(f => + { + var fnr = f.Identifikasjonsnummer.FirstErGjeldende()?.FoedselsEllerDNummer ?? throw new Exception("fødselsnummer ikke funnet"); + var adresse = f.Bostedsadresse.FirstErGjeldende() ?? throw new Exception("Mangler bostedsadresse"); + return new AppTestPerson + { + UserId = userId++, + PartyId = f.PartyId, + SSN = fnr, + FirstName = f.Navn.FirstErGjeldende()?.Fornavn ?? "Ukjent", + LastName = f.Navn.FirstErGjeldende()?.Etternavn ?? "Ukjent", + MiddleName = f.Navn.FirstErGjeldende()?.Mellomnavn, + UserName = $"user-{99999999999 - long.Parse(fnr)}", // Make an sytnetic username based on an obfuscated fnr + AddressCity = adresse.Vegadresse.Poststed.Poststedsnavn, + // AddressMunicipalName = adresse.Vegadresse.Kommunenummer, + AddressMunicipalNumber = adresse.Vegadresse.Kommunenummer, + AddressHouseLetter = f.Bostedsadresse.FirstErGjeldende()?.Vegadresse.Adressekode, + AddressHouseNumber = f.Bostedsadresse.FirstErGjeldende()?.Vegadresse.Adressenummer.Husnummer, + AddressMunicipalName = null, + AddressPostalCode = null, + AddressStreetName = null, + Email = null, + MobileNumber = null, + TelephoneNumber = null, + Language = null, + MailingAddress = null, + MailingPostalCity = null, + MailingPostalCode = null, + PartyRoles = fnrRoleLookup.TryGetValue(fnr, out var partyRoles) ? partyRoles : new Dictionary>(), + CustomClaims = new() + { + new() + { + Type = "user:source", + ValueType = "http://www.w3.org/2001/XMLSchema#string", + Value = "localTenor" + } + }, + + }; + }).ToList(), + Orgs = brreg.Select(b => new AppTestOrg + { + PartyId = b.PartyId, + ParentPartyId = null, + OrgNumber = b.Organisasjonsnummer, + Name = b.Navn, + BusinessAddress = string.Join("\n", b.Forretningsadresse.Adresse), + BusinessPostalCity = b.Forretningsadresse.Poststed, + BusinessPostalCode = b.Forretningsadresse.Postnummer, + MailingAddress = string.Join("\n", b.Postadresse.Adresse), + MailingPostalCity = b.Postadresse.Poststed, + MailingPostalCode = b.Postadresse.Postnummer, + EMailAddress = null, + FaxNumber = null, + InternetAddress = null, + MobileNumber = null, + TelephoneNumber = null, + UnitStatus = null, + UnitType = null, + }).ToList(), + }; + } + + public async Task StoreUploadedFile(IFormFile file) + { + var dir = GetTenorStorageDirectory(); + var filename = new FileInfo(Path.Join(dir.FullName, file.FileName)); + if (filename.Directory?.FullName != dir.FullName) + { + throw new Exception($"Invalid filename {file.FileName}"); + } + using Stream fileStream = filename.OpenWrite(); + await file.CopyToAsync(fileStream); + } + private static T? ParseCatchException(string rawJson) where T : class + { + try + { + return JsonSerializer.Deserialize(rawJson, _options); + } + catch (Exception) + { + return null; + } + } + public async Task> GetFileItems() + { + var directory = GetTenorStorageDirectory(); + var itemList = new List(); + foreach (var f in directory.GetFiles()) + { + if (f.Name.StartsWith('.')) + { + continue; // Ignore hidden files (like .DS_Store) + } + var content = await System.IO.File.ReadAllTextAsync(f.FullName); + + itemList.Add(new() + { + FileName = f.Name, + RawFileContent = content, + Freg = ParseCatchException(content), + Brreg = ParseCatchException(content), + }); + }; + return itemList; + } + + public void DeleteFile(string fileName) + { + var fileHandle = GetTenorStorageDirectory().GetFiles(fileName).First(f => f.Name == fileName); + fileHandle.Delete(); + } +} + +public static class ListExtentions +{ + public static T? FirstErGjeldende(this List list) + { + var erGjeldendeAccessor = typeof(T).GetProperty("erGjeldende"); + return list.FirstOrDefault(t => erGjeldendeAccessor?.GetValue(t) as bool? == true) ?? list.FirstOrDefault(); + } +} \ No newline at end of file diff --git a/src/Services/TestData/AppTestDataModel.cs b/src/Services/TestData/AppTestDataModel.cs index b97792e8..a6ead9e1 100644 --- a/src/Services/TestData/AppTestDataModel.cs +++ b/src/Services/TestData/AppTestDataModel.cs @@ -1,4 +1,5 @@ #nullable enable +using System.Text.Json.Serialization; using Altinn.Platform.Authentication.Model; using Altinn.Platform.Profile.Models; using Altinn.Platform.Register.Models; @@ -12,7 +13,12 @@ namespace LocalTest.Services.TestData; /// public class AppTestDataModel { + [JsonPropertyOrder(int.MinValue)] + [JsonPropertyName("$schema")] + public string Schema => "https://altinncdn.no/schemas/json/test-users/test-users.schema.v1.json"; + [JsonPropertyName("persons")] public List Persons { get; set; } = default!; + [JsonPropertyName("orgs")] public List Orgs { get; set; } = default!; public TestDataModel GetTestDataModel() @@ -155,27 +161,49 @@ public static AppTestDataModel FromTestDataModel(TestDataModel localData) }; return constructedAppData; } + + public bool IsEmpty() + { + return Persons.Count == 0 && Orgs.Count == 0; + } } public class AppTestOrg { + [JsonPropertyName("partyId")] public int PartyId { get; set; } + [JsonPropertyName("orgNumber")] public string OrgNumber { get; set; } = default!; + [JsonPropertyName("parentPartyId")] public int? ParentPartyId { get; set; } + [JsonPropertyName("name")] public string? Name { get; set; } + [JsonPropertyName("businessAddress")] public string? BusinessAddress { get; set; } + [JsonPropertyName("businessPostalCity")] public string? BusinessPostalCity { get; set; } + [JsonPropertyName("businessPostalCode")] public string? BusinessPostalCode { get; set; } + [JsonPropertyName("eMailAddress")] public string? EMailAddress { get; set; } + [JsonPropertyName("faxNumber")] public string? FaxNumber { get; set; } + [JsonPropertyName("internetAddress")] public string? InternetAddress { get; set; } + [JsonPropertyName("mailingAddress")] public string? MailingAddress { get; set; } + [JsonPropertyName("mailingPostalCity")] public string? MailingPostalCity { get; set; } + [JsonPropertyName("mailingPostalCode")] public string? MailingPostalCode { get; set; } + [JsonPropertyName("mobileNumber")] public string? MobileNumber { get; set; } + [JsonPropertyName("telephoneNumber")] public string? TelephoneNumber { get; set; } + [JsonPropertyName("unitStatus")] public string? UnitStatus { get; set; } + [JsonPropertyName("unitType")] public string? UnitType { get; set; } public Party ToParty(List? potentialChildOrgs = null) @@ -226,28 +254,51 @@ public Party ToParty(List? potentialChildOrgs = null) public class AppTestPerson { + [JsonPropertyName("partyId")] public int PartyId { get; set; } = default!; + [JsonPropertyName("ssn")] public string SSN { get; set; } = default!; - public string FirstName { get; set; } = default!; - public string MiddleName { get; set; } = default!; + [JsonPropertyName("firstName")] + public string? FirstName { get; set; } = default!; + [JsonPropertyName("middleName")] + public string? MiddleName { get; set; } + [JsonPropertyName("lastName")] public string LastName { get; set; } = default!; + [JsonPropertyName("customClaims")] public List CustomClaims { get; set; } = new(); + [JsonPropertyName("partyRoles")] public Dictionary> PartyRoles { get; set; } = new(); + [JsonPropertyName("addressCity")] public string? AddressCity { get; set; } + [JsonPropertyName("addressHouseLetter")] public string? AddressHouseLetter { get; set; } + [JsonPropertyName("addressHouseNumber")] public string? AddressHouseNumber { get; set; } + [JsonPropertyName("addressMunicipalName")] public string? AddressMunicipalName { get; set; } + [JsonPropertyName("addressMunicipalNumber")] public string? AddressMunicipalNumber { get; set; } + [JsonPropertyName("addressPostalCode")] public string? AddressPostalCode { get; set; } + [JsonPropertyName("addressStreetName")] public string? AddressStreetName { get; set; } + [JsonPropertyName("mailingAddress")] public string? MailingAddress { get; set; } + [JsonPropertyName("mailingPostalCity")] public string? MailingPostalCity { get; set; } + [JsonPropertyName("mailingPostalCode")] public string? MailingPostalCode { get; set; } + [JsonPropertyName("mobileNumber")] public string? MobileNumber { get; set; } + [JsonPropertyName("telephoneNumber")] public string? TelephoneNumber { get; set; } + [JsonPropertyName("email")] public string? Email { get; set; } + [JsonPropertyName("userId")] public int UserId { get; set; } + [JsonPropertyName("language")] public string? Language { get; set; } + [JsonPropertyName("userName")] public string? UserName { get; set; } public string GetFullName() => string.IsNullOrWhiteSpace(MiddleName) ? $"{FirstName} {LastName}" : $"{FirstName} {MiddleName} {LastName}"; diff --git a/src/Services/TestData/TestDataService.cs b/src/Services/TestData/TestDataService.cs index aca43d46..816f0a7a 100644 --- a/src/Services/TestData/TestDataService.cs +++ b/src/Services/TestData/TestDataService.cs @@ -9,13 +9,15 @@ namespace LocalTest.Services.TestData; public class TestDataService { private readonly ILocalApp _localApp; - private readonly LocalPlatformSettings _settings; + private readonly TenorDataRepository _tenorDataRepository; private readonly IMemoryCache _cache; + private readonly LocalPlatformSettings _settings; private readonly ILogger _logger; - public TestDataService(ILocalApp localApp, IOptions settings, IMemoryCache memoryCache, ILogger logger) + public TestDataService(ILocalApp localApp, TenorDataRepository tenorDataRepository, IOptions settings, IMemoryCache memoryCache, ILogger logger) { - _cache = memoryCache; _localApp = localApp; + _tenorDataRepository = tenorDataRepository; + _cache = memoryCache; _settings = settings.Value; _logger = logger; } @@ -42,6 +44,14 @@ public async Task GetTestData() _logger.LogInformation(e, "Fetching Test data from app failed."); } + var tenorUsers = await _tenorDataRepository.GetAppTestDataModel(); + if (tenorUsers is not null && !tenorUsers.IsEmpty()) + { + // Use tenor users if they exist + return tenorUsers.GetTestDataModel(); + } + + //Fallback to Ola Nordmann, Sofie Salt ... if no other users are availible return await TestDataDiskReader.ReadFromDisk(_settings.LocalTestingStaticTestDataPath); }))!; } diff --git a/src/Startup.cs b/src/Startup.cs index dbd1ba94..532a7f28 100644 --- a/src/Startup.cs +++ b/src/Startup.cs @@ -109,6 +109,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Views/Home/FrontendVersion.cshtml b/src/Views/FrontendVersion/Index.cshtml similarity index 66% rename from src/Views/Home/FrontendVersion.cshtml rename to src/Views/FrontendVersion/Index.cshtml index 80787a16..d2ed08ed 100644 --- a/src/Views/Home/FrontendVersion.cshtml +++ b/src/Views/FrontendVersion/Index.cshtml @@ -1,13 +1,13 @@ @model FrontendVersion @{ - ViewData["Title"] = "Frontend version"; + ViewData["Title"] = "Frontend version"; }

@ViewData["Title"]

-@using (Html.BeginForm("FrontendVersion", "Home", FormMethod.Post, new { Class = "form-signin" })) +@using (Html.BeginForm("Index", "FrontendVersion", FormMethod.Post, new { Class = "form-signin" })) { - @Html.AntiForgeryToken(); + @Html.AntiForgeryToken()
@Html.DropDownListFor(model => model.Version, Model.Versions, new { Class = "form-control" }) diff --git a/src/Views/Home/Index.cshtml b/src/Views/Home/Index.cshtml index 43cc4659..c910fb34 100644 --- a/src/Views/Home/Index.cshtml +++ b/src/Views/Home/Index.cshtml @@ -84,7 +84,6 @@ @Html.DropDownListFor(model => model.AuthenticationLevel, Model.AuthenticationLevels, new { Class = "form-control" })
- @if(Model.AppModeIsHttp) {
@@ -95,23 +94,16 @@
} - - } - - - - @if(string.IsNullOrWhiteSpace(Model.LocalFrontendUrl)) - { - diff --git a/src/Views/Shared/_Layout.cshtml b/src/Views/Shared/_Layout.cshtml index f8ea777e..5bcddce3 100644 --- a/src/Views/Shared/_Layout.cshtml +++ b/src/Views/Shared/_Layout.cshtml @@ -4,20 +4,35 @@ @ViewData["Title"] - Altinn Studio - +
@@ -27,12 +42,7 @@ @RenderBody() - -
-
- © 2019 - LocalTest - Privacy -
-
@RenderSection("Scripts", required: false) + diff --git a/src/Views/StorageExplorer/Index.cshtml b/src/Views/StorageExplorer/Index.cshtml new file mode 100644 index 00000000..4e4e9c03 --- /dev/null +++ b/src/Views/StorageExplorer/Index.cshtml @@ -0,0 +1,39 @@ + + + + + diff --git a/src/Views/TenorUsers/Index.cshtml b/src/Views/TenorUsers/Index.cshtml new file mode 100644 index 00000000..28a3a79b --- /dev/null +++ b/src/Views/TenorUsers/Index.cshtml @@ -0,0 +1,106 @@ +@model LocalTest.Models.TenorViewModel + +@using Microsoft.Extensions.Options +@using LocalTest.Configuration +@using LocalTest.Services.TestData + +@inject IOptions LocalPlatformSettings + + +@{ + ViewData["Title"] = "Local users and orgs (preview)"; +} +

@ViewData["Title"]

+ +

+ By default Altinn Studio publishes a limited set of test accouns for local testing. For most apps these will be + enough, but if you have more specific needs, or want the same users as in tt02, you probably want to import data + from Tenor testdata to use for your local development +

+ +

+ Tenor requires login with an official norwegian ID (like BankID), so you currently have to login and download + "kildedata" for the persons and organisations that you want to reference. Make sure you find suitable users and + organisations and download "kildedata" for each org/user. +

+ + + +
+
+

Last opp tenor kildefiler

+
+ @using (Html.BeginForm("Upload", "TenorUsers", FormMethod.Post, new + { + Class = "form-signin", + enctype = + "multipart/form-data" + })) + { + @Html.AntiForgeryToken() + ; +
+ +
+
+ +
+ } +
+ +@using (Html.BeginForm("Update", "TenorUsers", FormMethod.Post, new { })) +{ + + + + + + + + + + + + @foreach (var item in Model.FileItems) + { + + + + @if (item.Brreg is not null) + { + + + + } + else if (item.Freg is not null) + { + + + + + + } + else + { + + + } + + } + +
VelgFilenameNameFnr/org
+ + @item.FileName@item.Brreg.Navn@item.Brreg.Organisasjonsnummer@item.Freg.Navn?.FirstErGjeldende()?.Fornavn @item.Freg.Navn?.FirstErGjeldende()?.Mellomnavn + @item.Freg.Navn?.FirstErGjeldende()?.Etternavn@item.Freg.Identifikasjonsnummer?.FirstErGjeldende()?.FoedselsEllerDNummer +
@item.RawFileContent
+
+ +
+ + +
+}