diff --git a/docs/schema/V1/schema.verified.graphql b/docs/schema/V1/schema.verified.graphql index e6b5177e3..a77019319 100644 --- a/docs/schema/V1/schema.verified.graphql +++ b/docs/schema/V1/schema.verified.graphql @@ -141,6 +141,10 @@ type DialogByIdForbidden implements DialogByIdError { message: String! } +type DialogByIdForbiddenAuthLevelToLow implements DialogByIdError { + message: String! +} + type DialogByIdNotFound implements DialogByIdError { message: String! } @@ -466,4 +470,4 @@ scalar DateTime @specifiedBy(url: "https:\/\/www.graphql-scalars.com\/date-time" scalar URL @specifiedBy(url: "https:\/\/tools.ietf.org\/html\/rfc3986") -scalar UUID @specifiedBy(url: "https:\/\/tools.ietf.org\/html\/rfc4122") \ No newline at end of file +scalar UUID @specifiedBy(url: "https:\/\/tools.ietf.org\/html\/rfc4122") diff --git a/docs/schema/V1/swagger.verified.json b/docs/schema/V1/swagger.verified.json index 05a308733..3dc480624 100644 --- a/docs/schema/V1/swagger.verified.json +++ b/docs/schema/V1/swagger.verified.json @@ -2258,6 +2258,24 @@ } ] }, + "nonSensitiveSummary": { + "description": "An optional non-sensitive summary of the dialog and its current state.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, + "nonSensitiveTitle": { + "description": "An optional non-sensitive title of the dialog.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, "senderName": { "description": "Overridden sender name. If not supplied, assume \u0022org\u0022 as the sender name. Must be text/plain if supplied.\nSupported media types: text/plain", "nullable": true, @@ -2912,6 +2930,24 @@ } ] }, + "nonSensitiveSummary": { + "description": "An optional non-sensitive summary of the dialog and its current state.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, + "nonSensitiveTitle": { + "description": "An optional non-sensitive title of the dialog.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, "senderName": { "description": "Overridden sender name. If not supplied, assume \u0022org\u0022 as the sender name. Must be text/plain if supplied.", "nullable": true, @@ -3367,6 +3403,24 @@ } ] }, + "nonSensitiveSummary": { + "description": "An optional non-sensitive summary of the dialog and its current state.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, + "nonSensitiveTitle": { + "description": "An optional non-sensitive title of the dialog.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, "senderName": { "description": "Overridden sender name. If not supplied, assume \u0022org\u0022 as the sender name.", "nullable": true, @@ -4062,6 +4116,24 @@ } ] }, + "nonSensitiveSummary": { + "description": "An optional non-sensitive summary of the dialog and its current state.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, + "nonSensitiveTitle": { + "description": "An optional non-sensitive title of the dialog.\nUsed for search and list views if the user authorization does not meet the required eIDAS level", + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/V1CommonContent_ContentValue" + } + ] + }, "senderName": { "description": "Overridden sender name. If not supplied, assume \u0022org\u0022 as the sender name.", "nullable": true, diff --git a/src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs b/src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs index b999531c7..d156a0339 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs @@ -10,6 +10,10 @@ public static class Constants public const string TransmissionReadAction = "transmissionread"; public static readonly Uri UnauthorizedUri = new("urn:dialogporten:unauthorized"); + public const string IdportenLoaSubstantial = "idporten-loa-substantial"; + public const string IdportenLoaHigh = "idporten-loa-high"; + public const string AltinnAuthLevelTooLow = "Altinn authentication level too low."; + public const string DisableAltinnEventsRequiresAdminScope = "Disabling Altinn events requires service owner admin scope."; @@ -24,7 +28,7 @@ public static class Constants public static class AuthorizationScope { /// - /// Needed to be able to modify (create/update/delete) correspondence service resources. Primarily used by the correspondence service. + /// Needed to be able to modify (create/update/delete) correspondence service resources. Primarily used by the correspondence service. /// public const string CorrespondenceScope = "digdir:dialogporten.correspondence"; diff --git a/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs b/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs index 0d4c92054..85e6e1889 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs @@ -1,4 +1,5 @@ -using Digdir.Domain.Dialogporten.Application.Externals.Presentation; +using System.Diagnostics; +using Digdir.Domain.Dialogporten.Application.Externals.Presentation; using System.Security.Claims; using System.Diagnostics.CodeAnalysis; using System.Text.Json; @@ -175,30 +176,26 @@ public static bool TryGetOrganizationNumber(this Claim? consumerClaim, [NotNullW return orgNumber is not null; } - public static bool TryGetAuthenticationLevel(this ClaimsPrincipal claimsPrincipal, [NotNullWhen(true)] out int? authenticationLevel) + public static int GetAuthenticationLevel(this ClaimsPrincipal claimsPrincipal) { if (claimsPrincipal.TryGetClaimValue(AltinnAuthLevelClaim, out var claimValue) && int.TryParse(claimValue, out var level)) { - authenticationLevel = level; - return true; + return level; } if (claimsPrincipal.TryGetClaimValue(IdportenAuthLevelClaim, out claimValue)) { // The acr claim value is either "idporten-loa-substantial" (previously "Level3") or "idporten-loa-high" (previously "Level4") // https://docs.digdir.no/docs/idporten/oidc/oidc_protocol_new_idporten#new-acr-values - authenticationLevel = claimValue switch + return claimValue switch { - "idporten-loa-substantial" => 3, - "idporten-loa-high" => 4, - _ => null + Constants.IdportenLoaSubstantial => 3, + Constants.IdportenLoaHigh => 4, + _ => throw new ArgumentException("Unknown acr value") }; - - return authenticationLevel.HasValue; } - authenticationLevel = null; - return false; + throw new UnreachableException("No authentication level claim found"); } public static IEnumerable GetIdentifyingClaims(this IEnumerable claims) diff --git a/src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs b/src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs index b14d22402..15df63bdb 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs @@ -50,10 +50,7 @@ public string GetDialogToken(DialogEntity dialog, DialogDetailsAuthorizationResu { { DialogTokenClaimTypes.JwtId, Guid.NewGuid() }, { DialogTokenClaimTypes.AuthenticatedParty, GetAuthenticatedParty() }, - { DialogTokenClaimTypes.AuthenticationLevel, - claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel) - ? authenticationLevel.Value - : 0 }, + { DialogTokenClaimTypes.AuthenticationLevel, claimsPrincipal.GetAuthenticationLevel() }, { DialogTokenClaimTypes.DialogParty, dialog.Party }, { DialogTokenClaimTypes.ServiceResource, dialog.ServiceResource }, { DialogTokenClaimTypes.DialogId, dialog.Id }, diff --git a/src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs b/src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs index ae0503854..4090a4acc 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs @@ -18,4 +18,7 @@ Task GetAuthorizedParties(IPartyIdentifier authenticate CancellationToken cancellationToken = default); Task HasListAuthorizationForDialog(DialogEntity dialog, CancellationToken cancellationToken); + + bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel); + Task UserHasRequiredAuthLevel(string serviceResource, CancellationToken cancellationToken); } diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs index 245445b55..784055962 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Common.ReturnTypes; using Digdir.Domain.Dialogporten.Application.Externals; using Digdir.Domain.Dialogporten.Application.Externals.AltinnAuthorization; @@ -17,7 +18,7 @@ public sealed class GetActivityQuery : IRequest } [GenerateOneOf] -public sealed partial class GetActivityResult : OneOfBase; +public sealed partial class GetActivityResult : OneOfBase; internal sealed class GetActivityQueryHandler : IRequestHandler { @@ -67,6 +68,11 @@ public async Task Handle(GetActivityQuery request, return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + var activity = dialog.Activities.FirstOrDefault(); if (activity is null) diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs index 09b46bdc5..9f99fa285 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Common.ReturnTypes; using Digdir.Domain.Dialogporten.Application.Externals; using Digdir.Domain.Dialogporten.Application.Externals.AltinnAuthorization; @@ -15,7 +16,7 @@ public sealed class SearchActivityQuery : IRequest } [GenerateOneOf] -public sealed partial class SearchActivityResult : OneOfBase, EntityNotFound, EntityDeleted>; +public sealed partial class SearchActivityResult : OneOfBase, EntityNotFound, EntityDeleted, Forbidden>; internal sealed class SearchActivityQueryHandler : IRequestHandler { @@ -61,6 +62,11 @@ public async Task Handle(SearchActivityQuery request, Canc return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + return _mapper.Map>(dialog.Activities); } } diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs index 5d229e1bc..d363c778c 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Common.ReturnTypes; using Digdir.Domain.Dialogporten.Application.Externals; using Digdir.Domain.Dialogporten.Application.Externals.AltinnAuthorization; @@ -15,7 +16,7 @@ public sealed class SearchLabelAssignmentLogQuery : IRequest, EntityNotFound, EntityDeleted>; +public sealed partial class SearchLabelAssignmentLogResult : OneOfBase, EntityNotFound, EntityDeleted, Forbidden>; internal sealed class SearchLabelAssignmentLogQueryHandler : IRequestHandler { @@ -55,6 +56,11 @@ public async Task Handle(SearchLabelAssignmentLo return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + return _mapper.Map>(dialog.DialogEndUserContext.LabelAssignmentLogs); } } diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs index e4c79666c..9fb99dae4 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs @@ -1,5 +1,6 @@ using AutoMapper; using Digdir.Domain.Dialogporten.Application.Common; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Common.ReturnTypes; using Digdir.Domain.Dialogporten.Application.Externals; using Digdir.Domain.Dialogporten.Application.Externals.AltinnAuthorization; @@ -77,6 +78,11 @@ public async Task Handle(GetSeenLogQuery request, return new EntityNotFound(request.SeenLogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + var dto = _mapper.Map(seenLog); dto.IsCurrentEndUser = currentUserInformation.UserId.ExternalIdWithPrefix == seenLog.SeenBy.ActorId; diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs index 8aa65d356..af8b9dc92 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs @@ -7,6 +7,7 @@ using OneOf; using Microsoft.EntityFrameworkCore; using Digdir.Domain.Dialogporten.Application.Common; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; namespace Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.DialogSeenLogs.Queries.Search; @@ -69,6 +70,11 @@ public async Task Handle(SearchSeenLogQuery request, Cancel return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + return dialog.SeenLog .Select(x => { diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs index 0dd96e5e2..0f2b6f57a 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs @@ -18,7 +18,7 @@ public sealed class GetTransmissionQuery : IRequest } [GenerateOneOf] -public sealed partial class GetTransmissionResult : OneOfBase; +public sealed partial class GetTransmissionResult : OneOfBase; internal sealed class GetTransmissionQueryHandler : IRequestHandler { @@ -72,6 +72,11 @@ public async Task Handle(GetTransmissionQuery request, return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + var transmission = dialog.Transmissions.FirstOrDefault(); if (transmission is null) { diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs index 8e1675ade..6254ea3f2 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs @@ -16,7 +16,7 @@ public sealed class SearchTransmissionQuery : IRequest } [GenerateOneOf] -public sealed partial class SearchTransmissionResult : OneOfBase, EntityNotFound, EntityDeleted>; +public sealed partial class SearchTransmissionResult : OneOfBase, EntityNotFound, EntityDeleted, Forbidden>; internal sealed class SearchTransmissionQueryHandler : IRequestHandler { @@ -69,6 +69,11 @@ public async Task Handle(SearchTransmissionQuery reque return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + var dto = _mapper.Map>(dialog.Transmissions); foreach (var transmission in dto) diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs index 7c807edc6..10667ef3f 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs @@ -116,6 +116,11 @@ public async Task Handle(GetDialogQuery request, CancellationTo return new EntityDeleted(request.DialogId); } + if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken)) + { + return new Forbidden(Constants.AltinnAuthLevelTooLow); + } + // TODO: What if name lookup fails // https://github.com/altinn/dialogporten/issues/387 var currentUserInformation = await _userRegistry.GetCurrentUserInformation(cancellationToken); diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs new file mode 100644 index 000000000..357bf5ae9 --- /dev/null +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs @@ -0,0 +1,23 @@ +using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents; + +namespace Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Search; + +internal static class DialogContentExtensions +{ + public static void SetNonSensitiveContent(this List content) + { + var nonSensitiveTitle = content.FirstOrDefault(x => x.TypeId == DialogContentType.Values.NonSensitiveTitle); + if (nonSensitiveTitle is not null) + { + var title = content.First(x => x.TypeId == DialogContentType.Values.Title); + title.Value = nonSensitiveTitle.Value; + } + + var nonSensitiveSummary = content.FirstOrDefault(x => x.TypeId == DialogContentType.Values.NonSensitiveSummary); + if (nonSensitiveSummary is not null) + { + var summary = content.First(x => x.TypeId == DialogContentType.Values.Summary); + summary.Value = nonSensitiveSummary.Value; + } + } +} diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs index 9dd51bcba..fb311c402 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs @@ -188,6 +188,27 @@ public async Task Handle(SearchDialogQuery request, Cancella seenLog.IsCurrentEndUser = IdentifierMasker.GetMaybeMaskedIdentifier(_userRegistry.GetCurrentUserId().ExternalIdWithPrefix) == seenLog.SeenBy.ActorId; } + var serviceResources = paginatedList.Items + .Select(x => x.ServiceResource) + .Distinct() + .ToList(); + + var resourcePolicyInformation = await _db.ResourcePolicyInformation + .Where(x => serviceResources.Contains(x.Resource)) + .ToDictionaryAsync(x => x.Resource, x => x.MinimumAuthenticationLevel, cancellationToken); + + foreach (var dialog in paginatedList.Items) + { + if (!resourcePolicyInformation.TryGetValue(dialog.ServiceResource, out var minimumAuthenticationLevel)) + { + continue; + } + + if (!_altinnAuthorization.UserHasRequiredAuthLevel(minimumAuthenticationLevel)) + { + dialog.Content.SetNonSensitiveContent(); + } + } return paginatedList.ConvertTo(_mapper.Map); } } diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs index f0499d5c8..ecc45a708 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs @@ -220,12 +220,24 @@ public sealed class ContentDto /// public ContentValueDto Title { get; set; } = null!; + /// + /// An optional non-sensitive title of the dialog. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveTitle { get; set; } + /// /// A short summary of the dialog and its current state. /// Supported media types: text/plain /// public ContentValueDto Summary { get; set; } = null!; + /// + /// An optional non-sensitive summary of the dialog and its current state. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveSummary { get; set; } + /// /// Overridden sender name. If not supplied, assume "org" as the sender name. Must be text/plain if supplied. /// Supported media types: text/plain diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs index 09c953bf4..4824e92ed 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs @@ -194,11 +194,23 @@ public sealed class ContentDto /// public ContentValueDto Title { get; set; } = null!; + /// + /// An optional non-sensitive title of the dialog. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveTitle { get; set; } + /// /// A short summary of the dialog and its current state. Must be text/plain. /// public ContentValueDto Summary { get; set; } = null!; + /// + /// An optional non-sensitive summary of the dialog and its current state. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveSummary { get; set; } + /// /// Overridden sender name. If not supplied, assume "org" as the sender name. Must be text/plain if supplied. /// diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs index e95e98cbe..04eb20fa6 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs @@ -282,11 +282,23 @@ public sealed class ContentDto /// public ContentValueDto Title { get; set; } = null!; + /// + /// An optional non-sensitive title of the dialog. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveTitle { get; set; } + /// /// A short summary of the dialog and its current state. /// public ContentValueDto Summary { get; set; } = null!; + /// + /// An optional non-sensitive summary of the dialog and its current state. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveSummary { get; set; } + /// /// Overridden sender name. If not supplied, assume "org" as the sender name. /// diff --git a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs index 6a852a27c..e628e81f6 100644 --- a/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs +++ b/src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs @@ -20,11 +20,23 @@ public sealed class ContentDto /// public ContentValueDto Title { get; set; } = null!; + /// + /// An optional non-sensitive title of the dialog. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveTitle { get; set; } + /// /// A short summary of the dialog and its current state. /// public ContentValueDto Summary { get; set; } = null!; + /// + /// An optional non-sensitive summary of the dialog and its current state. + /// Used for search and list views if the user authorization does not meet the required eIDAS level + /// + public ContentValueDto? NonSensitiveSummary { get; set; } + /// /// Overridden sender name. If not supplied, assume "org" as the sender name. /// diff --git a/src/Digdir.Domain.Dialogporten.Domain/Dialogs/Entities/Contents/DialogContentType.cs b/src/Digdir.Domain.Dialogporten.Domain/Dialogs/Entities/Contents/DialogContentType.cs index c5d63a5ed..5f763f34d 100644 --- a/src/Digdir.Domain.Dialogporten.Domain/Dialogs/Entities/Contents/DialogContentType.cs +++ b/src/Digdir.Domain.Dialogporten.Domain/Dialogs/Entities/Contents/DialogContentType.cs @@ -13,7 +13,9 @@ public enum Values Summary = 3, AdditionalInfo = 4, ExtendedStatus = 5, - MainContentReference = 6 + MainContentReference = 6, + NonSensitiveTitle = 7, + NonSensitiveSummary = 8, } public bool Required { get; private init; } @@ -67,6 +69,20 @@ public enum Values OutputInList = false, AllowedMediaTypes = [MediaTypes.EmbeddableMarkdown] }, + Values.NonSensitiveTitle => new(id) + { + Required = false, + MaxLength = Constants.DefaultMaxStringLength, + OutputInList = true, + AllowedMediaTypes = [MediaTypes.PlainText] + }, + Values.NonSensitiveSummary => new(id) + { + Required = false, + MaxLength = Constants.DefaultMaxStringLength, + OutputInList = true, + AllowedMediaTypes = [MediaTypes.PlainText] + }, _ => throw new ArgumentOutOfRangeException(nameof(id), id, null) }; diff --git a/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs b/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs index ac5cb36e4..99c037d40 100644 --- a/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs +++ b/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs @@ -1,3 +1,4 @@ +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.GraphQL.EndUser.Common; namespace Digdir.Domain.Dialogporten.GraphQL.EndUser.DialogById; @@ -23,6 +24,11 @@ public sealed class DialogByIdForbidden : IDialogByIdError public string Message { get; set; } = "Forbidden"; } +public sealed class DialogByIdForbiddenAuthLevelToLow : IDialogByIdError +{ + public string Message { get; set; } = Constants.AltinnAuthLevelTooLow; +} + public sealed class DialogByIdPayload { public Dialog? Dialog { get; set; } diff --git a/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs b/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs index a56867716..99244cc56 100644 --- a/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs +++ b/src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs @@ -1,5 +1,6 @@ using AppAny.HotChocolate.FluentValidation; using AutoMapper; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Common.Pagination.Continuation; using Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Get; using Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Search; @@ -23,7 +24,21 @@ public async Task GetDialogById( dialog => new DialogByIdPayload { Dialog = mapper.Map(dialog) }, notFound => new DialogByIdPayload { Errors = [new DialogByIdNotFound { Message = notFound.Message }] }, deleted => new DialogByIdPayload { Errors = [new DialogByIdDeleted { Message = deleted.Message }] }, - forbidden => new DialogByIdPayload { Errors = [new DialogByIdForbidden { Message = "Forbidden" }] }); + forbidden => + { + var response = new DialogByIdPayload(); + + if (forbidden.Reasons.Any(x => x.Contains(Constants.AltinnAuthLevelTooLow))) + { + response.Errors.Add(new DialogByIdForbiddenAuthLevelToLow()); + } + else + { + response.Errors.Add(new DialogByIdForbidden()); + } + + return response; + }); } public async Task SearchDialogs( diff --git a/src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs b/src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs index c0d2c6954..7298857c3 100644 --- a/src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs +++ b/src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs @@ -24,6 +24,7 @@ public static IServiceCollection AddDialogportenGraphQl(this IServiceCollection .AddType() .AddType() .AddType() + .AddType() .AddType() .AddType() .AddType() diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs index 2523de8f9..cf4785092 100644 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs @@ -3,6 +3,7 @@ using System.Text.Json.Serialization; using Altinn.Authorization.ABAC.Xacml.JsonProfile; using Digdir.Domain.Dialogporten.Application.Common.Extensions; +using Digdir.Domain.Dialogporten.Application.Externals; using Digdir.Domain.Dialogporten.Application.Externals.AltinnAuthorization; using Digdir.Domain.Dialogporten.Application.Externals.Presentation; using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities; @@ -26,6 +27,7 @@ internal sealed class AltinnAuthorizationClient : IAltinnAuthorization private readonly IFusionCache _partiesCache; private readonly IFusionCache _subjectResourcesCache; private readonly IUser _user; + private readonly IDialogDbContext _db; private readonly ILogger _logger; private readonly IServiceScopeFactory _serviceScopeFactory; @@ -39,6 +41,7 @@ public AltinnAuthorizationClient( HttpClient client, IFusionCacheProvider cacheProvider, IUser user, + IDialogDbContext db, ILogger logger, IServiceScopeFactory serviceScopeFactory) { @@ -47,6 +50,7 @@ public AltinnAuthorizationClient( _partiesCache = cacheProvider.GetCache(nameof(AuthorizedPartiesResult)) ?? throw new ArgumentNullException(nameof(cacheProvider)); _subjectResourcesCache = cacheProvider.GetCache(nameof(SubjectResource)) ?? throw new ArgumentNullException(nameof(cacheProvider)); _user = user ?? throw new ArgumentNullException(nameof(user)); + _db = db ?? throw new ArgumentNullException(nameof(db)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory)); } @@ -106,6 +110,19 @@ public async Task HasListAuthorizationForDialog(DialogEntity dialog, Cance || authorizedResourcesForSearch.DialogIds.Contains(dialog.Id); } + public bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel) => + minimumAuthenticationLevel <= _user.GetPrincipal().GetAuthenticationLevel(); + + public async Task UserHasRequiredAuthLevel(string serviceResource, CancellationToken cancellationToken) + { + var minimumAuthenticationLevel = await _db.ResourcePolicyInformation + .Where(x => x.Resource == serviceResource) + .Select(x => x.MinimumAuthenticationLevel) + .FirstOrDefaultAsync(cancellationToken); + + return UserHasRequiredAuthLevel(minimumAuthenticationLevel); + } + private static AuthorizedPartiesResult GetFlattenedAuthorizedParties(AuthorizedPartiesResult authorizedParties) { var flattenedAuthorizedParties = new AuthorizedPartiesResult(); diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs index 7e6b0593e..f2d658379 100644 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs @@ -70,4 +70,7 @@ public async Task GetAuthorizedParties(IPartyIdentifier }); public Task HasListAuthorizationForDialog(DialogEntity _, CancellationToken __) => Task.FromResult(true); + + public bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel) => true; + public Task UserHasRequiredAuthLevel(string serviceResource, CancellationToken _) => Task.FromResult(true); } diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.Designer.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.Designer.cs new file mode 100644 index 000000000..665039c10 --- /dev/null +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.Designer.cs @@ -0,0 +1,2230 @@ +// +using System; +using Digdir.Domain.Dialogporten.Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.Migrations +{ + [DbContext(typeof(DialogDbContext))] + [Migration("20250214154726_AddNewNonSensitiveContentTypes")] + partial class AddNewNonSensitiveContentTypes + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Actors.Actor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("ActorId") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ActorName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ActorTypeId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("ActorTypeId"); + + b.ToTable("Actor"); + + b.HasDiscriminator().HasValue("Actor"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Actors.ActorType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("ActorType"); + + b.HasData( + new + { + Id = 1, + Name = "PartyRepresentative" + }, + new + { + Id = 2, + Name = "ServiceOwner" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.Attachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.ToTable("Attachment"); + + b.HasDiscriminator().HasValue("Attachment"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentUrl", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("AttachmentId") + .HasColumnType("uuid"); + + b.Property("ConsumerTypeId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("MediaType") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.HasKey("Id"); + + b.HasIndex("AttachmentId"); + + b.HasIndex("ConsumerTypeId"); + + b.ToTable("AttachmentUrl"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentUrlConsumerType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("AttachmentUrlConsumerType"); + + b.HasData( + new + { + Id = 1, + Name = "Gui" + }, + new + { + Id = 2, + Name = "Api" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.DialogEndUserContext", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("Revision") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("SystemLabelId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("DialogId") + .IsUnique(); + + b.HasIndex("SystemLabelId"); + + b.ToTable("DialogEndUserContext"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ContextId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("ContextId"); + + b.ToTable("LabelAssignmentLog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.SystemLabel", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("SystemLabel"); + + b.HasData( + new + { + Id = 1, + Name = "Default" + }, + new + { + Id = 2, + Name = "Bin" + }, + new + { + Id = 3, + Name = "Archive" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogApiAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AuthorizationAttribute") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("DialogId"); + + b.ToTable("DialogApiAction"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogApiActionEndpoint", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Deprecated") + .HasColumnType("boolean"); + + b.Property("DocumentationUrl") + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.Property("HttpMethodId") + .HasColumnType("integer"); + + b.Property("RequestSchema") + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.Property("ResponseSchema") + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.Property("SunsetAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.Property("Version") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("HttpMethodId"); + + b.ToTable("DialogApiActionEndpoint"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AuthorizationAttribute") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("HttpMethodId") + .HasColumnType("integer"); + + b.Property("IsDeleteDialogAction") + .HasColumnType("boolean"); + + b.Property("PriorityId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.HasKey("Id"); + + b.HasIndex("DialogId"); + + b.HasIndex("HttpMethodId"); + + b.HasIndex("PriorityId"); + + b.ToTable("DialogGuiAction"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionPriority", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("DialogGuiActionPriority"); + + b.HasData( + new + { + Id = 1, + Name = "Primary" + }, + new + { + Id = 2, + Name = "Secondary" + }, + new + { + Id = 3, + Name = "Tertiary" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("ExtendedType") + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.Property("TransmissionId") + .HasColumnType("uuid"); + + b.Property("TypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DialogId"); + + b.HasIndex("TransmissionId"); + + b.HasIndex("TypeId"); + + b.ToTable("DialogActivity"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("DialogActivityType"); + + b.HasData( + new + { + Id = 1, + Name = "DialogCreated" + }, + new + { + Id = 2, + Name = "DialogClosed" + }, + new + { + Id = 3, + Name = "Information" + }, + new + { + Id = 4, + Name = "TransmissionOpened" + }, + new + { + Id = 5, + Name = "PaymentMade" + }, + new + { + Id = 6, + Name = "SignatureProvided" + }, + new + { + Id = 7, + Name = "DialogOpened" + }, + new + { + Id = 8, + Name = "DialogDeleted" + }, + new + { + Id = 9, + Name = "DialogRestored" + }, + new + { + Id = 10, + Name = "SentToSigning" + }, + new + { + Id = 11, + Name = "SentToFormFill" + }, + new + { + Id = 12, + Name = "SentToSendIn" + }, + new + { + Id = 13, + Name = "SentToPayment" + }, + new + { + Id = 14, + Name = "FormSubmitted" + }, + new + { + Id = 15, + Name = "FormSaved" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("MediaType") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TypeId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("TypeId"); + + b.HasIndex("DialogId", "TypeId") + .IsUnique(); + + b.ToTable("DialogContent"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContentType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.PrimitiveCollection("AllowedMediaTypes") + .IsRequired() + .HasColumnType("text[]"); + + b.Property("MaxLength") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("OutputInList") + .HasColumnType("boolean"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("DialogContentType"); + + b.HasData( + new + { + Id = 1, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "Title", + OutputInList = true, + Required = true + }, + new + { + Id = 2, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "SenderName", + OutputInList = true, + Required = false + }, + new + { + Id = 3, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "Summary", + OutputInList = true, + Required = true + }, + new + { + Id = 4, + AllowedMediaTypes = new[] { "text/plain", "text/markdown" }, + MaxLength = 1023, + Name = "AdditionalInfo", + OutputInList = false, + Required = false + }, + new + { + Id = 5, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 20, + Name = "ExtendedStatus", + OutputInList = true, + Required = false + }, + new + { + Id = 6, + AllowedMediaTypes = new[] { "application/vnd.dialogporten.frontchannelembed-url;type=text/markdown" }, + MaxLength = 1023, + Name = "MainContentReference", + OutputInList = false, + Required = false + }, + new + { + Id = 7, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "NonSensitiveTitle", + OutputInList = true, + Required = false + }, + new + { + Id = 8, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "NonSensitiveSummary", + OutputInList = true, + Required = false + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Deleted") + .HasColumnType("boolean"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DueAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExtendedStatus") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExternalReference") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IdempotentKey") + .HasMaxLength(36) + .HasColumnType("character varying(36)"); + + b.Property("Org") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .UseCollation("C"); + + b.Property("Party") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .UseCollation("C"); + + b.Property("PrecedingProcess") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Process") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Progress") + .HasColumnType("integer"); + + b.Property("Revision") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("ServiceResource") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)") + .UseCollation("C"); + + b.Property("ServiceResourceType") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("StatusId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("VisibleFrom") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("DueAt"); + + b.HasIndex("Org"); + + b.HasIndex("Party"); + + b.HasIndex("Process"); + + b.HasIndex("ServiceResource"); + + b.HasIndex("StatusId"); + + b.HasIndex("UpdatedAt"); + + b.HasIndex("Org", "IdempotentKey") + .IsUnique() + .HasFilter("\"IdempotentKey\" is not null"); + + b.ToTable("Dialog", (string)null); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSearchTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(63) + .HasColumnType("character varying(63)"); + + b.HasKey("Id"); + + b.HasIndex("DialogId", "Value") + .IsUnique(); + + b.ToTable("DialogSearchTag"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("EndUserTypeId") + .HasColumnType("integer"); + + b.Property("IsViaServiceOwner") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("DialogId"); + + b.HasIndex("EndUserTypeId"); + + b.ToTable("DialogSeenLog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogStatus", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("DialogStatus"); + + b.HasData( + new + { + Id = 1, + Name = "New" + }, + new + { + Id = 2, + Name = "InProgress" + }, + new + { + Id = 3, + Name = "Draft" + }, + new + { + Id = 4, + Name = "Sent" + }, + new + { + Id = 5, + Name = "RequiresAttention" + }, + new + { + Id = 6, + Name = "Completed" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogUserType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("DialogUserType"); + + b.HasData( + new + { + Id = 0, + Name = "Unknown" + }, + new + { + Id = 1, + Name = "Person" + }, + new + { + Id = 2, + Name = "SystemUser" + }, + new + { + Id = 3, + Name = "ServiceOwner" + }, + new + { + Id = 4, + Name = "ServiceOwnerOnBehalfOfPerson" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("MediaType") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TransmissionId") + .HasColumnType("uuid"); + + b.Property("TypeId") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("TypeId"); + + b.HasIndex("TransmissionId", "TypeId") + .IsUnique(); + + b.ToTable("DialogTransmissionContent"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContentType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.PrimitiveCollection("AllowedMediaTypes") + .IsRequired() + .HasColumnType("text[]"); + + b.Property("MaxLength") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("DialogTransmissionContentType"); + + b.HasData( + new + { + Id = 1, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "Title", + Required = true + }, + new + { + Id = 2, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "Summary", + Required = true + }, + new + { + Id = 3, + AllowedMediaTypes = new[] { "application/vnd.dialogporten.frontchannelembed-url;type=text/markdown" }, + MaxLength = 1023, + Name = "ContentReference", + Required = false + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("AuthorizationAttribute") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.Property("ExtendedType") + .HasMaxLength(1023) + .HasColumnType("character varying(1023)"); + + b.Property("RelatedTransmissionId") + .HasColumnType("uuid"); + + b.Property("TypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DialogId"); + + b.HasIndex("RelatedTransmissionId"); + + b.HasIndex("TypeId"); + + b.ToTable("DialogTransmission"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionType", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("DialogTransmissionType"); + + b.HasData( + new + { + Id = 1, + Name = "Information" + }, + new + { + Id = 2, + Name = "Acceptance" + }, + new + { + Id = 3, + Name = "Rejection" + }, + new + { + Id = 4, + Name = "Request" + }, + new + { + Id = 5, + Name = "Alert" + }, + new + { + Id = 6, + Name = "Decision" + }, + new + { + Id = 7, + Name = "Submission" + }, + new + { + Id = 8, + Name = "Correction" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Http.HttpVerb", b => + { + b.Property("Id") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("HttpVerb"); + + b.HasData( + new + { + Id = 1, + Name = "GET" + }, + new + { + Id = 2, + Name = "POST" + }, + new + { + Id = 3, + Name = "PUT" + }, + new + { + Id = 4, + Name = "PATCH" + }, + new + { + Id = 5, + Name = "DELETE" + }, + new + { + Id = 6, + Name = "HEAD" + }, + new + { + Id = 7, + Name = "OPTIONS" + }, + new + { + Id = 8, + Name = "TRACE" + }, + new + { + Id = 9, + Name = "CONNECT" + }); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Localizations.Localization", b => + { + b.Property("LocalizationSetId") + .HasColumnType("uuid"); + + b.Property("LanguageCode") + .HasMaxLength(15) + .HasColumnType("character varying(15)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(4095) + .HasColumnType("character varying(4095)"); + + b.HasKey("LocalizationSetId", "LanguageCode"); + + b.ToTable("Localization"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("LocalizationSet"); + + b.HasDiscriminator().HasValue("LocalizationSet"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.ResourcePolicyInformation.ResourcePolicyInformation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("MinimumAuthenticationLevel") + .HasColumnType("integer"); + + b.Property("Resource") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("Resource") + .IsUnique(); + + b.ToTable("ResourcePolicyInformation"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.SubjectResources.SubjectResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("gen_random_uuid()"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.Property("Resource") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("Id"); + + b.HasIndex("Resource", "Subject") + .IsUnique(); + + b.ToTable("SubjectResource"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Infrastructure.Persistence.IdempotentNotifications.NotificationAcknowledgement", b => + { + b.Property("EventId") + .HasColumnType("uuid"); + + b.Property("NotificationHandler") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AcknowledgedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("current_timestamp at time zone 'utc'"); + + b.HasKey("EventId", "NotificationHandler"); + + b.HasIndex("EventId"); + + b.ToTable("NotificationAcknowledgement"); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Consumed") + .HasColumnType("timestamp with time zone"); + + b.Property("ConsumerId") + .HasColumnType("uuid"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LastSequenceNumber") + .HasColumnType("bigint"); + + b.Property("LockId") + .HasColumnType("uuid"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("ReceiveCount") + .HasColumnType("integer"); + + b.Property("Received") + .HasColumnType("timestamp with time zone"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("Delivered"); + + b.ToTable("MassTransitInboxState", (string)null); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => + { + b.Property("SequenceNumber") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ConversationId") + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("DestinationAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EnqueueTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("FaultAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Headers") + .HasColumnType("text"); + + b.Property("InboxConsumerId") + .HasColumnType("uuid"); + + b.Property("InboxMessageId") + .HasColumnType("uuid"); + + b.Property("InitiatorId") + .HasColumnType("uuid"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("MessageType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OutboxId") + .HasColumnType("uuid"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RequestId") + .HasColumnType("uuid"); + + b.Property("ResponseAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SentTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SourceAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("SequenceNumber"); + + b.HasIndex("EnqueueTime"); + + b.HasIndex("ExpirationTime"); + + b.HasIndex("OutboxId", "SequenceNumber") + .IsUnique(); + + b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") + .IsUnique(); + + b.ToTable("MassTransitOutboxMessage", (string)null); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => + { + b.Property("OutboxId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Created") + .HasColumnType("timestamp with time zone"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone"); + + b.Property("LastSequenceNumber") + .HasColumnType("bigint"); + + b.Property("LockId") + .HasColumnType("uuid"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea"); + + b.HasKey("OutboxId"); + + b.HasIndex("Created"); + + b.ToTable("MassTransitOutboxState", (string)null); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLogActor", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Actors.Actor"); + + b.Property("LabelAssignmentLogId") + .HasColumnType("uuid"); + + b.HasIndex("LabelAssignmentLogId") + .IsUnique(); + + b.HasDiscriminator().HasValue("LabelAssignmentLogActor"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityPerformedByActor", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Actors.Actor"); + + b.Property("ActivityId") + .HasColumnType("uuid"); + + b.HasIndex("ActivityId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogActivityPerformedByActor"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLogSeenByActor", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Actors.Actor"); + + b.Property("DialogSeenLogId") + .HasColumnType("uuid"); + + b.HasIndex("DialogSeenLogId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogSeenLogSeenByActor"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionSenderActor", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Actors.Actor"); + + b.Property("TransmissionId") + .HasColumnType("uuid"); + + b.HasIndex("TransmissionId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogTransmissionSenderActor"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogAttachment", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Attachments.Attachment"); + + b.Property("DialogId") + .HasColumnType("uuid"); + + b.HasIndex("DialogId"); + + b.HasDiscriminator().HasValue("DialogAttachment"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionAttachment", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Attachments.Attachment"); + + b.Property("TransmissionId") + .HasColumnType("uuid"); + + b.HasIndex("TransmissionId"); + + b.HasDiscriminator().HasValue("DialogTransmissionAttachment"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentDisplayName", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet"); + + b.Property("AttachmentId") + .HasColumnType("uuid"); + + b.HasIndex("AttachmentId") + .IsUnique(); + + b.HasDiscriminator().HasValue("AttachmentDisplayName"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionPrompt", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet"); + + b.Property("GuiActionId") + .HasColumnType("uuid"); + + b.HasIndex("GuiActionId") + .IsUnique(); + + b.ToTable("LocalizationSet", t => + { + t.Property("GuiActionId") + .HasColumnName("DialogGuiActionPrompt_GuiActionId"); + }); + + b.HasDiscriminator().HasValue("DialogGuiActionPrompt"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionTitle", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet"); + + b.Property("GuiActionId") + .HasColumnType("uuid"); + + b.HasIndex("GuiActionId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogGuiActionTitle"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityDescription", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet"); + + b.Property("ActivityId") + .HasColumnType("uuid"); + + b.HasIndex("ActivityId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogActivityDescription"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContentValue", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet"); + + b.Property("DialogContentId") + .HasColumnType("uuid"); + + b.HasIndex("DialogContentId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogContentValue"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContentValue", b => + { + b.HasBaseType("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet"); + + b.Property("TransmissionContentId") + .HasColumnType("uuid"); + + b.HasIndex("TransmissionContentId") + .IsUnique(); + + b.HasDiscriminator().HasValue("DialogTransmissionContentValue"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Actors.Actor", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Actors.ActorType", "ActorType") + .WithMany() + .HasForeignKey("ActorTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ActorType"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentUrl", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Attachments.Attachment", "Attachment") + .WithMany("Urls") + .HasForeignKey("AttachmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentUrlConsumerType", "ConsumerType") + .WithMany() + .HasForeignKey("ConsumerTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Attachment"); + + b.Navigation("ConsumerType"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.DialogEndUserContext", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithOne("DialogEndUserContext") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.DialogEndUserContext", "DialogId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.SystemLabel", "SystemLabel") + .WithMany() + .HasForeignKey("SystemLabelId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Dialog"); + + b.Navigation("SystemLabel"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLog", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.DialogEndUserContext", "Context") + .WithMany("LabelAssignmentLogs") + .HasForeignKey("ContextId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Context"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogApiAction", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("ApiActions") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dialog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogApiActionEndpoint", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogApiAction", "Action") + .WithMany("Endpoints") + .HasForeignKey("ActionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Http.HttpVerb", "HttpMethod") + .WithMany() + .HasForeignKey("HttpMethodId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Action"); + + b.Navigation("HttpMethod"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiAction", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("GuiActions") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Http.HttpVerb", "HttpMethod") + .WithMany() + .HasForeignKey("HttpMethodId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionPriority", "Priority") + .WithMany() + .HasForeignKey("PriorityId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Dialog"); + + b.Navigation("HttpMethod"); + + b.Navigation("Priority"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivity", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("Activities") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", "Transmission") + .WithMany("Activities") + .HasForeignKey("TransmissionId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Dialog"); + + b.Navigation("Transmission"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContent", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("Content") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContentType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Dialog"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogStatus", "Status") + .WithMany() + .HasForeignKey("StatusId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Status"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSearchTag", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("SearchTags") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dialog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLog", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("SeenLog") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogUserType", "EndUserType") + .WithMany() + .HasForeignKey("EndUserTypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Dialog"); + + b.Navigation("EndUserType"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContent", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", "Transmission") + .WithMany("Content") + .HasForeignKey("TransmissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContentType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Transmission"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("Transmissions") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", "RelatedTransmission") + .WithMany("RelatedTransmissions") + .HasForeignKey("RelatedTransmissionId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionType", "Type") + .WithMany() + .HasForeignKey("TypeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Dialog"); + + b.Navigation("RelatedTransmission"); + + b.Navigation("Type"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Localizations.Localization", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet", "LocalizationSet") + .WithMany("Localizations") + .HasForeignKey("LocalizationSetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LocalizationSet"); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => + { + b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null) + .WithMany() + .HasForeignKey("OutboxId"); + + b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null) + .WithMany() + .HasForeignKey("InboxMessageId", "InboxConsumerId") + .HasPrincipalKey("MessageId", "ConsumerId"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLogActor", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLog", "LabelAssignmentLog") + .WithOne("PerformedBy") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLogActor", "LabelAssignmentLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LabelAssignmentLog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityPerformedByActor", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivity", "Activity") + .WithOne("PerformedBy") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityPerformedByActor", "ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLogSeenByActor", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLog", "DialogSeenLog") + .WithOne("SeenBy") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLogSeenByActor", "DialogSeenLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DialogSeenLog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionSenderActor", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", "Transmission") + .WithOne("Sender") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionSenderActor", "TransmissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Transmission"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogAttachment", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", "Dialog") + .WithMany("Attachments") + .HasForeignKey("DialogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Dialog"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmissionAttachment", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", "Transmission") + .WithMany("Attachments") + .HasForeignKey("TransmissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Transmission"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentDisplayName", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Attachments.Attachment", "Attachment") + .WithOne("DisplayName") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Attachments.AttachmentDisplayName", "AttachmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Attachment"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionPrompt", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiAction", "GuiAction") + .WithOne("Prompt") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionPrompt", "GuiActionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuiAction"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionTitle", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiAction", "GuiAction") + .WithOne("Title") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiActionTitle", "GuiActionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuiAction"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityDescription", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivity", "Activity") + .WithOne("Description") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivityDescription", "ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Activity"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContentValue", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContent", "DialogContent") + .WithOne("Value") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContentValue", "DialogContentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DialogContent"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContentValue", b => + { + b.HasOne("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContent", "TransmissionContent") + .WithOne("Value") + .HasForeignKey("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContentValue", "TransmissionContentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TransmissionContent"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Attachments.Attachment", b => + { + b.Navigation("DisplayName"); + + b.Navigation("Urls"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.DialogEndUserContext", b => + { + b.Navigation("LabelAssignmentLogs"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.DialogEndUserContexts.Entities.LabelAssignmentLog", b => + { + b.Navigation("PerformedBy") + .IsRequired(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogApiAction", b => + { + b.Navigation("Endpoints"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Actions.DialogGuiAction", b => + { + b.Navigation("Prompt"); + + b.Navigation("Title"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Activities.DialogActivity", b => + { + b.Navigation("Description"); + + b.Navigation("PerformedBy") + .IsRequired(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents.DialogContent", b => + { + b.Navigation("Value") + .IsRequired(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogEntity", b => + { + b.Navigation("Activities"); + + b.Navigation("ApiActions"); + + b.Navigation("Attachments"); + + b.Navigation("Content"); + + b.Navigation("DialogEndUserContext") + .IsRequired(); + + b.Navigation("GuiActions"); + + b.Navigation("SearchTags"); + + b.Navigation("SeenLog"); + + b.Navigation("Transmissions"); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.DialogSeenLog", b => + { + b.Navigation("SeenBy") + .IsRequired(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents.DialogTransmissionContent", b => + { + b.Navigation("Value") + .IsRequired(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.DialogTransmission", b => + { + b.Navigation("Activities"); + + b.Navigation("Attachments"); + + b.Navigation("Content"); + + b.Navigation("RelatedTransmissions"); + + b.Navigation("Sender") + .IsRequired(); + }); + + modelBuilder.Entity("Digdir.Domain.Dialogporten.Domain.Localizations.LocalizationSet", b => + { + b.Navigation("Localizations"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.cs new file mode 100644 index 000000000..abe2d59dc --- /dev/null +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.Migrations +{ + /// + public partial class AddNewNonSensitiveContentTypes : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "DialogContentType", + columns: new[] { "Id", "AllowedMediaTypes", "MaxLength", "Name", "OutputInList", "Required" }, + values: new object[,] + { + { 7, new[] { "text/plain" }, 255, "NonSensitiveTitle", true, false }, + { 8, new[] { "text/plain" }, 255, "NonSensitiveSummary", true, false } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "DialogContentType", + keyColumn: "Id", + keyValue: 7); + + migrationBuilder.DeleteData( + table: "DialogContentType", + keyColumn: "Id", + keyValue: 8); + } + } +} diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/DialogDbContextModelSnapshot.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/DialogDbContextModelSnapshot.cs index 3430c2750..bc079adc4 100644 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/DialogDbContextModelSnapshot.cs +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/DialogDbContextModelSnapshot.cs @@ -723,6 +723,24 @@ protected override void BuildModel(ModelBuilder modelBuilder) Name = "MainContentReference", OutputInList = false, Required = false + }, + new + { + Id = 7, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "NonSensitiveTitle", + OutputInList = true, + Required = false + }, + new + { + Id = 8, + AllowedMediaTypes = new[] { "text/plain" }, + MaxLength = 255, + Name = "NonSensitiveSummary", + OutputInList = true, + Required = false }); }); diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Get/GetDialogActivityEndpoint.cs b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Get/GetDialogActivityEndpoint.cs index 74028e0dc..fba94b59f 100644 --- a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Get/GetDialogActivityEndpoint.cs +++ b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Get/GetDialogActivityEndpoint.cs @@ -33,6 +33,7 @@ public override async Task HandleAsync(GetActivityQuery req, CancellationToken c await result.Match( dto => SendOkAsync(dto, ct), notFound => this.NotFoundAsync(notFound, ct), - deleted => this.GoneAsync(deleted, ct)); + deleted => this.GoneAsync(deleted, ct), + forbidden => this.ForbiddenAsync(forbidden, ct)); } } diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Search/SearchDialogActivityEndpoint.cs b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Search/SearchDialogActivityEndpoint.cs index 4877e132d..639de5311 100644 --- a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Search/SearchDialogActivityEndpoint.cs +++ b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Search/SearchDialogActivityEndpoint.cs @@ -28,6 +28,7 @@ public override async Task HandleAsync(SearchActivityQuery req, CancellationToke await result.Match( dto => SendOkAsync(dto, ct), notFound => this.NotFoundAsync(notFound, ct), - deleted => this.GoneAsync(deleted, ct)); + deleted => this.GoneAsync(deleted, ct), + forbidden => this.ForbiddenAsync(forbidden, ct)); } } diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/SearchDialogLabelAssignmentLogEndpoint.cs b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/SearchDialogLabelAssignmentLogEndpoint.cs index 48b536646..9a32a246e 100644 --- a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/SearchDialogLabelAssignmentLogEndpoint.cs +++ b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/SearchDialogLabelAssignmentLogEndpoint.cs @@ -32,6 +32,7 @@ public override async Task HandleAsync(SearchLabelAssignmentLogQuery req, Cancel await result.Match( dto => SendOkAsync(dto, ct), notFound => this.NotFoundAsync(notFound, ct), - deleted => this.GoneAsync(deleted, ct)); + deleted => this.GoneAsync(deleted, ct), + forbidden => this.ForbiddenAsync(forbidden, ct)); } } diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Get/GetDialogTransmissionEndpoint.cs b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Get/GetDialogTransmissionEndpoint.cs index 7f1c9481c..f2f66b012 100644 --- a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Get/GetDialogTransmissionEndpoint.cs +++ b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Get/GetDialogTransmissionEndpoint.cs @@ -33,6 +33,7 @@ public override async Task HandleAsync(GetTransmissionQuery req, CancellationTok await result.Match( dto => SendOkAsync(dto, ct), notFound => this.NotFoundAsync(notFound, ct), - deleted => this.GoneAsync(deleted, ct)); + deleted => this.GoneAsync(deleted, ct), + forbidden => this.ForbiddenAsync(forbidden, ct)); } } diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Search/SearchDialogTransmissionEndpoint.cs b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Search/SearchDialogTransmissionEndpoint.cs index 4b87ac8ae..84c733fb9 100644 --- a/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Search/SearchDialogTransmissionEndpoint.cs +++ b/src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Search/SearchDialogTransmissionEndpoint.cs @@ -28,6 +28,7 @@ public override async Task HandleAsync(SearchTransmissionQuery req, Cancellation await result.Match( dto => SendOkAsync(dto, ct), notFound => this.NotFoundAsync(notFound, ct), - deleted => this.GoneAsync(deleted, ct)); + deleted => this.GoneAsync(deleted, ct), + forbidden => this.ForbiddenAsync(forbidden, ct)); } } diff --git a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Common/IntegrationTestUser.cs b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Common/IntegrationTestUser.cs index 382dcb88c..0a7f16ca0 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Common/IntegrationTestUser.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Common/IntegrationTestUser.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Externals.Presentation; namespace Digdir.Domain.Dialogporten.Application.Integration.Tests.Common; @@ -26,6 +27,7 @@ private static List GetDefaultClaims() return [ new Claim(ClaimTypes.Name, "Integration Test User"), + new Claim("acr", Constants.IdportenLoaHigh), new Claim(ClaimTypes.NameIdentifier, "integration-test-user"), new Claim("pid", "22834498646"), new Claim("consumer", diff --git a/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/ContentTypeTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/ContentTypeTests.cs index 020497a7d..1ebc6f693 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/ContentTypeTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/ContentTypeTests.cs @@ -1,14 +1,20 @@ using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Contents; using Digdir.Domain.Dialogporten.Domain.Dialogs.Entities.Transmissions.Contents; -using ContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Commands.Create.ContentDto; +using CreateDialogContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Commands.Create.ContentDto; using TransmissionContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Commands.Create.TransmissionContentDto; +using UpdateDialogContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Commands.Update.ContentDto; +using EUGetDialogContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Get.ContentDto; +using EUSearchDialogContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.EndUser.Dialogs.Queries.Search.ContentDto; +using SOGetDialogContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Queries.Get.ContentDto; +using SOSearchDialogContentDto = Digdir.Domain.Dialogporten.Application.Features.V1.ServiceOwner.Dialogs.Queries.Search.ContentDto; + namespace Digdir.Domain.Dialogporten.Application.Unit.Tests.Features.V1.Common; public class ContentTypeTests { [Fact] - public void DialogContentType_Names_Should_Match_Props_On_All_DTOs() + public void DialogContentType_Names_Should_Match_Props_On_ServiceOwner_DTOs() { // Arrange var dialogContentTypeNames = DialogContentType.GetValues() @@ -17,10 +23,9 @@ public void DialogContentType_Names_Should_Match_Props_On_All_DTOs() var dtoTypes = new[] { - typeof(ContentDto), - typeof(Application.Features.V1.ServiceOwner.Dialogs.Commands.Update.ContentDto), - typeof(Application.Features.V1.EndUser.Dialogs.Queries.Get.ContentDto), - typeof(Application.Features.V1.ServiceOwner.Dialogs.Queries.Get.ContentDto) + typeof(CreateDialogContentDto), + typeof(UpdateDialogContentDto), + typeof(SOGetDialogContentDto) }; foreach (var dtoType in dtoTypes) @@ -38,31 +43,68 @@ public void DialogContentType_Names_Should_Match_Props_On_All_DTOs() } [Fact] - public void OutPutInList_DialogContentType_Names_Should_Match_Props_On_All_Search_DTOs() + public void DialogContentType_Names_Should_Match_Props_On_EndUser_DTOs() { // Arrange var dialogContentTypeNames = DialogContentType.GetValues() - .Where(x => x.OutputInList) + .Where(x => x.Id is not DialogContentType.Values.NonSensitiveSummary + and not DialogContentType.Values.NonSensitiveTitle) .Select(x => x.Name) .ToList(); - var dtoTypes = new[] + var dtoPropertyNames = typeof(EUGetDialogContentDto).GetProperties() + .Select(p => p.Name) + .ToList(); + + // Assert + Assert.Equal(dialogContentTypeNames.Count, dtoPropertyNames.Count); + foreach (var contentTypeName in dialogContentTypeNames) { - typeof(Application.Features.V1.EndUser.Dialogs.Queries.Search.ContentDto), - typeof(Application.Features.V1.ServiceOwner.Dialogs.Queries.Search.ContentDto) - }; + Assert.Contains(contentTypeName, dtoPropertyNames, StringComparer.OrdinalIgnoreCase); + } + } - foreach (var dtoType in dtoTypes) + [Fact] + public void OutPutInList_DialogContentType_Names_Should_Match_Props_On_ServiceOwner_Search_DTO() + { + // Arrange + var dialogContentTypeNames = DialogContentType.GetValues() + .Where(x => x.OutputInList) + .Select(x => x.Name) + .ToList(); + + var dtoPropertyNames = typeof(SOSearchDialogContentDto).GetProperties() + .Select(p => p.Name) + .ToList(); + + // Assert + Assert.Equal(dialogContentTypeNames.Count, dtoPropertyNames.Count); + foreach (var contentTypeName in dialogContentTypeNames) { - var dtoPropertyNames = dtoType.GetProperties() - .Select(p => p.Name) - .ToList(); + Assert.Contains(contentTypeName, dtoPropertyNames, StringComparer.OrdinalIgnoreCase); + } + } - Assert.Equal(dialogContentTypeNames.Count, dtoPropertyNames.Count); - foreach (var contentTypeName in dialogContentTypeNames) - { - Assert.Contains(contentTypeName, dtoPropertyNames, StringComparer.OrdinalIgnoreCase); - } + [Fact] + public void OutPutInList_DialogContentType_Names_Should_Match_Props_On_EndUser_Search_DTO() + { + // Arrange + var dialogContentTypeNames = DialogContentType.GetValues() + .Where(x => x.OutputInList) + .Where(x => x.Id is not DialogContentType.Values.NonSensitiveSummary + and not DialogContentType.Values.NonSensitiveTitle) + .Select(x => x.Name) + .ToList(); + + var dtoPropertyNames = typeof(EUSearchDialogContentDto).GetProperties() + .Select(p => p.Name) + .ToList(); + + // Assert + Assert.Equal(dialogContentTypeNames.Count, dtoPropertyNames.Count); + foreach (var contentTypeName in dialogContentTypeNames) + { + Assert.Contains(contentTypeName, dtoPropertyNames, StringComparer.OrdinalIgnoreCase); } } diff --git a/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs b/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs index 938d1c6d6..affa57195 100644 --- a/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs +++ b/tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using Digdir.Domain.Dialogporten.Application.Common.Authorization; using Digdir.Domain.Dialogporten.Application.Common.Extensions; namespace Digdir.Domain.Dialogporten.Application.Unit.Tests.Features.V1.Common.Extensions; @@ -6,51 +7,48 @@ namespace Digdir.Domain.Dialogporten.Application.Unit.Tests.Features.V1.Common.E public class ClaimsPrincipalExtensionsTests { [Fact] - public void TryGetAuthenticationLevel_Should_Parse_Idporten_Acr_Claim_For_Level3() + public void GetAuthenticationLevel_Should_Parse_Idporten_Acr_Claim_For_Level3() { // Arrange var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity([ - new Claim("acr", "idporten-loa-substantial") + new Claim("acr", Constants.IdportenLoaSubstantial) ])); // Act - var result = claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel); + var authenticationLevel = claimsPrincipal.GetAuthenticationLevel(); // Assert - Assert.True(result); Assert.Equal(3, authenticationLevel); } [Fact] - public void TryGetAuthenticationLevel_Should_Parse_Idporten_Acr_Claim_For_Level4() + public void GetAuthenticationLevel_Should_Parse_Idporten_Acr_Claim_For_Level4() { // Arrange var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity([ - new Claim("acr", "idporten-loa-high") + new Claim("acr", Constants.IdportenLoaHigh) ])); // Act - var result = claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel); + var authenticationLevel = claimsPrincipal.GetAuthenticationLevel(); // Assert - Assert.True(result); Assert.Equal(4, authenticationLevel); } [Fact] - public void TryGetAuthenticationLevel_Should_Parse_Altinn_Authlevel_First() + public void GetAuthenticationLevel_Should_Parse_Altinn_Authlevel_First() { // Arrange var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity([ - new Claim("acr", "idporten-loa-high"), + new Claim("acr", Constants.IdportenLoaHigh), new Claim("urn:altinn:authlevel", "5") ])); // Act - var result = claimsPrincipal.TryGetAuthenticationLevel(out var authenticationLevel); + var authenticationLevel = claimsPrincipal.GetAuthenticationLevel(); // Assert - Assert.True(result); Assert.Equal(5, authenticationLevel); } diff --git a/tests/Digdir.Domain.Dialogporten.GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs b/tests/Digdir.Domain.Dialogporten.GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs index dbfdeccb3..ec3af0353 100644 --- a/tests/Digdir.Domain.Dialogporten.GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs +++ b/tests/Digdir.Domain.Dialogporten.GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs @@ -11,6 +11,8 @@ public void DialogContentType_Names_Should_Match_Props_On_Content() { // Arrange var dialogContentTypeNames = DialogContentType.GetValues() + .Where(x => x.Id is not DialogContentType.Values.NonSensitiveSummary + and not DialogContentType.Values.NonSensitiveTitle) .Select(x => x.Name) .ToList(); @@ -31,6 +33,8 @@ public void OutPutInList_DialogContentType_Names_Should_Match_Props_On_SearchCon { // Arrange var dialogContentTypeNames = DialogContentType.GetValues() + .Where(x => x.Id is not DialogContentType.Values.NonSensitiveSummary + and not DialogContentType.Values.NonSensitiveTitle) .Where(x => x.OutputInList) .Select(x => x.Name) .ToList();