From aa2fcd8c5ad6550e70149b37c1d1fe4e5baee0ac Mon Sep 17 00:00:00 2001 From: Sondre Jahrsengene Date: Tue, 21 Jan 2025 12:35:31 +0100 Subject: [PATCH 1/2] chore: add xml descriptions to publicly exposed fields and methods --- .../AuthorizationRequirementJsonConverter.cs | 7 +++ Dan.Common/Constants.cs | 2 + Dan.Common/Dan.Common.csproj | 3 +- Dan.Common/Enums/FailureAction.cs | 3 + Dan.Common/Enums/LogAction.cs | 49 +++++++++++---- .../Extensions/HostBuilderExtensions.cs | 3 + .../IEntityRegistryApiClientService.cs | 13 ++-- .../Interfaces/IEntityRegistryService.cs | 4 ++ .../Interfaces/IServiceContextTextTemplate.cs | 36 +++++++++++ Dan.Common/Models/Accreditation.cs | 3 + .../Models/AccreditationPartyRequirement.cs | 3 + Dan.Common/Models/AuthorizationRequest.cs | 9 +++ Dan.Common/Models/DataRetrieval.cs | 9 +++ Dan.Common/Models/EntityRegistryUnit.cs | 5 +- Dan.Common/Models/EvidenceHarvesterOptions.cs | 3 + Dan.Common/Models/EvidenceStatusCode.cs | 9 ++- Dan.Common/Models/LocalizedString.cs | 11 ++++ .../Models/MaskinportenScopeRequirement.cs | 3 + Dan.Common/Models/NadobeCompat.cs | 7 ++- Dan.Common/Models/NotificationReminder.cs | 15 +++++ Dan.Common/Models/Party.cs | 25 ++++++++ Dan.Common/Models/PartyTypeRequirement.cs | 3 + .../Models/ProvideOwnTokenRequirement.cs | 3 + Dan.Common/Models/ReferenceRequirement.cs | 3 + Dan.Common/Models/Requirement.cs | 7 +++ Dan.Common/Models/ServiceContext.cs | 18 ++++++ Dan.Common/Models/SimpleEntityRegistryUnit.cs | 3 + Dan.Common/Models/Subject.cs | 6 ++ .../Models/WhiteListFromConfigRequirement.cs | 9 +++ Dan.Common/Models/WhiteListRequirement.cs | 3 + .../DefaultEntityRegistryApiClientService.cs | 9 +++ Dan.Common/Services/EntityRegistryService.cs | 61 ++++++++++++++++++- Dan.Common/Util/DateFormatConverter.cs | 7 +++ Dan.Common/Util/EvidenceSourceResponse.cs | 3 + Dan.Common/Util/KeyedLock.cs | 5 +- 35 files changed, 336 insertions(+), 26 deletions(-) diff --git a/Dan.Common/Compat/AuthorizationRequirementJsonConverter.cs b/Dan.Common/Compat/AuthorizationRequirementJsonConverter.cs index a35ed41..b710a4c 100644 --- a/Dan.Common/Compat/AuthorizationRequirementJsonConverter.cs +++ b/Dan.Common/Compat/AuthorizationRequirementJsonConverter.cs @@ -11,11 +11,18 @@ namespace Dan.Common.Compat; /// public class AuthorizationRequirementJsonConverter : System.Text.Json.Serialization.JsonConverter { + /// + /// Not implemented + /// + /// public override Requirement Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { throw new NotImplementedException(); } + /// + /// Standard jsonconverter write implementation + /// public override void Write(Utf8JsonWriter writer, Requirement value, JsonSerializerOptions options) { writer.WriteStartObject(); diff --git a/Dan.Common/Constants.cs b/Dan.Common/Constants.cs index 7d7a753..738aa91 100644 --- a/Dan.Common/Constants.cs +++ b/Dan.Common/Constants.cs @@ -1,5 +1,6 @@ namespace Dan.Common; +#pragma warning disable 1591 /// /// Shared constants in Dan /// @@ -81,3 +82,4 @@ public static class TextMacros public const string ConsentAndExternalReference = "#ConsentAndExternalReference#"; } +#pragma warning restore 1591 \ No newline at end of file diff --git a/Dan.Common/Dan.Common.csproj b/Dan.Common/Dan.Common.csproj index 22a9b49..29488ac 100644 --- a/Dan.Common/Dan.Common.csproj +++ b/Dan.Common/Dan.Common.csproj @@ -25,7 +25,8 @@ Altinn https://data.altinn.no MIT - Copyright (c) Digitaliseringsdirektoratet 2022 + Copyright (c) Digitaliseringsdirektoratet 2025 + true diff --git a/Dan.Common/Enums/FailureAction.cs b/Dan.Common/Enums/FailureAction.cs index b191867..3f991c9 100644 --- a/Dan.Common/Enums/FailureAction.cs +++ b/Dan.Common/Enums/FailureAction.cs @@ -1,5 +1,8 @@ namespace Dan.Common.Enums; +/// +/// Enum for determining what action to take if auth request is not satisfied +/// public enum FailureAction { /// diff --git a/Dan.Common/Enums/LogAction.cs b/Dan.Common/Enums/LogAction.cs index 23db652..86051d2 100644 --- a/Dan.Common/Enums/LogAction.cs +++ b/Dan.Common/Enums/LogAction.cs @@ -1,38 +1,63 @@ namespace Dan.Common.Enums; +/// +/// Log action enum +/// public enum LogAction { - // Used once per accreditation + /// + /// Used once per accreditation + /// AuthorizationGranted = 1, - // Used per consent request (one accreditation may incur several consent requests, each of which may span - // several datasets + /// + /// Used per consent request (one accreditation may incur several consent requests, each of which may span + /// several datasets + /// ConsentRequested = 2, - // As with ConsentRequested + /// + /// As with ConsentRequested + /// ConsentGiven = 3, - // As with ConsentRequested + /// + /// As with ConsentRequested + /// ConsentDenied = 4, - // Used for each harvest performed, of which there may be several per accreditation + /// + /// Used for each harvest performed, of which there may be several per accreditation + /// DatasetRetrieved = 5, - // As with ConsentRequested + /// + /// As with ConsentRequested + /// ConsentReminderSent = 6, - // Used when a open data set harvest is performed + /// + /// Used when a open data set harvest is performed + /// OpenDatasetRetrieved = 7, - // Used once per accreditation + /// + /// Used once per accreditation + /// AccreditationDeleted = 8, - // Used per data set requested for each AuthorizationGranted + /// + /// Used per data set requested for each AuthorizationGranted + /// DatasetRequested = 9, - // Used for each dataset in a consent request + /// + /// Used for each dataset in a consent request + /// DatasetRequiringConsentRequested = 10, - // Used for each correspondence sent related to consent requests (may be skipped, so counted seperately) + /// + /// Used for each correspondence sent related to consent requests (may be skipped, so counted seperately) + /// CorrespondenceSent = 11, } \ No newline at end of file diff --git a/Dan.Common/Extensions/HostBuilderExtensions.cs b/Dan.Common/Extensions/HostBuilderExtensions.cs index 42b0d72..03cd827 100644 --- a/Dan.Common/Extensions/HostBuilderExtensions.cs +++ b/Dan.Common/Extensions/HostBuilderExtensions.cs @@ -13,6 +13,9 @@ namespace Dan.Common.Extensions; +/// +/// HostBuilder extensions for setting up Dan plugin default configurations +/// public static class HostBuilderExtensions { /// diff --git a/Dan.Common/Interfaces/IEntityRegistryApiClientService.cs b/Dan.Common/Interfaces/IEntityRegistryApiClientService.cs index 127f510..b451855 100644 --- a/Dan.Common/Interfaces/IEntityRegistryApiClientService.cs +++ b/Dan.Common/Interfaces/IEntityRegistryApiClientService.cs @@ -1,11 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Dan.Common.Interfaces; -namespace Dan.Common.Interfaces; +/// +/// API Service for fetching entity registries +/// public interface IEntityRegistryApiClientService { + /// + /// Get entity registry unit + /// public Task GetUpstreamEntityRegistryUnitAsync(Uri registryApiUri); } diff --git a/Dan.Common/Interfaces/IEntityRegistryService.cs b/Dan.Common/Interfaces/IEntityRegistryService.cs index e701d83..d967c20 100644 --- a/Dan.Common/Interfaces/IEntityRegistryService.cs +++ b/Dan.Common/Interfaces/IEntityRegistryService.cs @@ -1,4 +1,8 @@ namespace Dan.Common.Interfaces; + +/// +/// Service for handling entity registry +/// public interface IEntityRegistryService { /// diff --git a/Dan.Common/Interfaces/IServiceContextTextTemplate.cs b/Dan.Common/Interfaces/IServiceContextTextTemplate.cs index b5773ee..36e86dd 100644 --- a/Dan.Common/Interfaces/IServiceContextTextTemplate.cs +++ b/Dan.Common/Interfaces/IServiceContextTextTemplate.cs @@ -5,28 +5,64 @@ /// public interface IServiceContextTextTemplate { + /// + /// Localised texts for consent request message + /// public LocalizedString ConsentDelegationContexts { get; } + /// + /// Email notification subject line + /// public T EmailNotificationSubject { get; } + /// + /// Email notification content + /// public T EmailNotificationContent { get; } + /// + /// SMS notification content + /// // ReSharper disable once InconsistentNaming public T SMSNotificationContent { get; } + /// + /// Correspondence sender name + /// public T CorrespondenceSender { get; } + /// + /// Correspondence title + /// public T CorrespondenceTitle { get; } + /// + /// Correspondence summary + /// public T CorrespondenceSummary { get; } + /// + /// Correspondence body + /// public T CorrespondenceBody { get; } + /// + /// Button text for giving consent + /// public T ConsentButtonText { get; } + /// + /// Receipt when giving consent + /// public T ConsentGivenReceiptText { get; } + /// + /// Receipt when denying consent + /// public T ConsentDeniedReceiptText { get; } + /// + /// Consent title text + /// public T ConsentTitleText { get; } } \ No newline at end of file diff --git a/Dan.Common/Models/Accreditation.cs b/Dan.Common/Models/Accreditation.cs index 45944d5..1b19f08 100644 --- a/Dan.Common/Models/Accreditation.cs +++ b/Dan.Common/Models/Accreditation.cs @@ -47,6 +47,9 @@ public class Accreditation [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public EvidenceStatusCode AggregateStatus { get; set; } = EvidenceStatusCode.Unknown; + /// + /// Flag to show if the accreditation is made from a direct harvest request + /// [DataMember(Name = "isDirectHarvest")] public bool IsDirectHarvest { get; set; } diff --git a/Dan.Common/Models/AccreditationPartyRequirement.cs b/Dan.Common/Models/AccreditationPartyRequirement.cs index cee3236..7d36918 100644 --- a/Dan.Common/Models/AccreditationPartyRequirement.cs +++ b/Dan.Common/Models/AccreditationPartyRequirement.cs @@ -14,6 +14,9 @@ public class AccreditationPartyRequirement : Requirement [JsonProperty(ItemConverterType = typeof(StringEnumConverter))] public List PartyRequirements { get; set; } + /// + /// Default constructor, sets PartyRequirements to a new empty list + /// public AccreditationPartyRequirement() { PartyRequirements = new List(); diff --git a/Dan.Common/Models/AuthorizationRequest.cs b/Dan.Common/Models/AuthorizationRequest.cs index 6338fe2..d725e03 100644 --- a/Dan.Common/Models/AuthorizationRequest.cs +++ b/Dan.Common/Models/AuthorizationRequest.cs @@ -60,12 +60,21 @@ public class AuthorizationRequest [DataMember(Name = "externalReference")] public string? ExternalReference { get; set; } + /// + /// Language code for the authorization request + /// [DataMember(Name = "languageCode")] public string? LanguageCode { get; set; } + /// + /// Redirect url for the consent receipt + /// [DataMember(Name = "consentReceiptRedirectUrl")] public string? ConsentReceiptRedirectUrl { get; set; } + /// + /// Flag to skip sending notification in Altinn + /// [DataMember(Name = "skipAltinnNotification")] public bool SkipAltinnNotification { get; set; } diff --git a/Dan.Common/Models/DataRetrieval.cs b/Dan.Common/Models/DataRetrieval.cs index b1aaf76..7e8889d 100644 --- a/Dan.Common/Models/DataRetrieval.cs +++ b/Dan.Common/Models/DataRetrieval.cs @@ -1,11 +1,20 @@ namespace Dan.Common.Models; +/// +/// For determining what dataset had data retrieved from and when +/// [DataContract] public class DataRetrieval { + /// + /// Name of dataset that data was retrieved from + /// [DataMember(Name = "evidenceCodeName")] public string? EvidenceCodeName { get; set; } + /// + /// When data was retrieved from dataset + /// [DataMember(Name = "timeStamp")] public DateTime TimeStamp { get; set; } } \ No newline at end of file diff --git a/Dan.Common/Models/EntityRegistryUnit.cs b/Dan.Common/Models/EntityRegistryUnit.cs index 077d254..201bfed 100644 --- a/Dan.Common/Models/EntityRegistryUnit.cs +++ b/Dan.Common/Models/EntityRegistryUnit.cs @@ -2,6 +2,8 @@ namespace Dan.Common.Models; +// Not our model, can add descriptions to fields on request +#pragma warning disable 1591 // ReSharper disable once InconsistentNaming public class EntityRegistryUnit { @@ -164,4 +166,5 @@ public class Organisasjonsform [JsonProperty("_links", Required = Required.Always)] public Links Links { get; set; } = null!; -} \ No newline at end of file +} +#pragma warning restore 1591 \ No newline at end of file diff --git a/Dan.Common/Models/EvidenceHarvesterOptions.cs b/Dan.Common/Models/EvidenceHarvesterOptions.cs index ecf107d..de42aff 100644 --- a/Dan.Common/Models/EvidenceHarvesterOptions.cs +++ b/Dan.Common/Models/EvidenceHarvesterOptions.cs @@ -1,5 +1,8 @@ namespace Dan.Common.Models; +/// +/// Settings for handing access tokens for evidence harvesting +/// public class EvidenceHarvesterOptions { /// diff --git a/Dan.Common/Models/EvidenceStatusCode.cs b/Dan.Common/Models/EvidenceStatusCode.cs index ddc4e83..7ccbbf4 100644 --- a/Dan.Common/Models/EvidenceStatusCode.cs +++ b/Dan.Common/Models/EvidenceStatusCode.cs @@ -67,14 +67,16 @@ public class EvidenceStatusCode : IEquatable [DataMember(Name = "retryAt")] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public DateTime? RetryAt { get; set; } - + + // Some default methods on method, shoud be self describing without descriptions what they do +#pragma warning disable 1591 public bool Equals(EvidenceStatusCode? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Code == other.Code; } - + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; @@ -82,7 +84,7 @@ public override bool Equals(object? obj) if (obj.GetType() != GetType()) return false; return Equals((EvidenceStatusCode)obj); } - + public override int GetHashCode() { return Code.GetHashCode(); @@ -97,4 +99,5 @@ public override int GetHashCode() { return !Equals(left, right); } +#pragma warning restore 1591 } \ No newline at end of file diff --git a/Dan.Common/Models/LocalizedString.cs b/Dan.Common/Models/LocalizedString.cs index 17a6954..a54e669 100644 --- a/Dan.Common/Models/LocalizedString.cs +++ b/Dan.Common/Models/LocalizedString.cs @@ -5,8 +5,19 @@ /// public class LocalizedString { + /// + /// English + /// public string? En { get; set; } + + /// + /// Bokmål + /// public string? NoNb { get; set; } + + /// + /// Nynorsk + /// public string? NoNn { get; set; } } \ No newline at end of file diff --git a/Dan.Common/Models/MaskinportenScopeRequirement.cs b/Dan.Common/Models/MaskinportenScopeRequirement.cs index ab83b2d..19e3813 100644 --- a/Dan.Common/Models/MaskinportenScopeRequirement.cs +++ b/Dan.Common/Models/MaskinportenScopeRequirement.cs @@ -13,6 +13,9 @@ public class MaskinportenScopeRequirement : Requirement [Required] public List RequiredScopes { get; set; } + /// + /// Default constructor, sets RequiredScopes to new empty list + /// public MaskinportenScopeRequirement() { RequiredScopes = new List(); diff --git a/Dan.Common/Models/NadobeCompat.cs b/Dan.Common/Models/NadobeCompat.cs index 452cf8b..01813bd 100644 --- a/Dan.Common/Models/NadobeCompat.cs +++ b/Dan.Common/Models/NadobeCompat.cs @@ -1,2 +1,7 @@ -namespace Nadobe.Common.Models; +// ReSharper disable once CheckNamespace +namespace Nadobe.Common.Models; + +/// +/// Depcrecated ConsentRequirement model, use Dan.Common.Models.ConsentRequirement instead +/// public class ConsentRequirement : Dan.Common.Models.ConsentRequirement { } diff --git a/Dan.Common/Models/NotificationReminder.cs b/Dan.Common/Models/NotificationReminder.cs index d9494e7..3e66c44 100644 --- a/Dan.Common/Models/NotificationReminder.cs +++ b/Dan.Common/Models/NotificationReminder.cs @@ -6,18 +6,33 @@ [DataContract] public class NotificationReminder { + /// + /// Type of notification reminder + /// [DataMember(Name = "notificationType")] public string? NotificationType { get; set; } + /// + /// True if everything went ok with sending of notification + /// [DataMember(Name = "success")] public bool Success { get; set; } + /// + /// Notification description + /// [DataMember(Name = "description")] public string? Description { get; set; } + /// + /// Amount of recipients + /// [DataMember(Name = "recipientCount")] public int RecipientCount { get; set; } + /// + /// When notification was sent + /// [DataMember(Name = "date")] public DateTime Date { get; set; } } \ No newline at end of file diff --git a/Dan.Common/Models/Party.cs b/Dan.Common/Models/Party.cs index 857355d..2e62b19 100644 --- a/Dan.Common/Models/Party.cs +++ b/Dan.Common/Models/Party.cs @@ -1,22 +1,42 @@ namespace Dan.Common.Models; +/// +/// Subject or requestor party for requests +/// [DataContract] public class Party { + /// + /// Party scheme. Example: iso6523-actorid-upis + /// [DataMember(Name = "scheme")] public string? Scheme { get; set; } + /// + /// Party identifier + /// [DataMember(Name = "id")] public string? Id { get; set; } + /// + /// Norwegian organisation number + /// [DataMember(Name = "norwegianOrganizationNumber")] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string? NorwegianOrganizationNumber { get; set; } + /// + /// Norwegian social security number + /// [DataMember(Name = "norwegianSocialSecurityNumber")] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string? NorwegianSocialSecurityNumber { get; set; } + /// + /// Returns norwegian organisation number if set, else norwegian social security if set, + /// if not returns scheme plus id. + /// + /// Masks part of social security number if true public string GetAsString(bool maskString = true) { if (NorwegianOrganizationNumber != null) @@ -31,5 +51,10 @@ public string GetAsString(bool maskString = true) return Scheme + "::" + Id; } + + /// + /// Returns norwegian organisation number if set, else norwegian social security if set, + /// if not returns scheme plus id. + /// public override string ToString() => GetAsString(); } \ No newline at end of file diff --git a/Dan.Common/Models/PartyTypeRequirement.cs b/Dan.Common/Models/PartyTypeRequirement.cs index 16f6757..66e5d6a 100644 --- a/Dan.Common/Models/PartyTypeRequirement.cs +++ b/Dan.Common/Models/PartyTypeRequirement.cs @@ -13,6 +13,9 @@ public class PartyTypeRequirement : Requirement [Required] public AllowedPartyTypesList AllowedPartyTypes { get; set; } + /// + /// Default constructor, sets AllowedPartyTypes to new instance + /// public PartyTypeRequirement() { AllowedPartyTypes = new AllowedPartyTypesList(); diff --git a/Dan.Common/Models/ProvideOwnTokenRequirement.cs b/Dan.Common/Models/ProvideOwnTokenRequirement.cs index 3210c7f..0c91382 100644 --- a/Dan.Common/Models/ProvideOwnTokenRequirement.cs +++ b/Dan.Common/Models/ProvideOwnTokenRequirement.cs @@ -1,5 +1,8 @@ namespace Dan.Common.Models { + /// + /// Requirement for requestor to provide a bearer token or delegates access to Digitaliseringsdirektoratet + /// [DataContract] public class ProvideOwnTokenRequirement : Requirement { } } \ No newline at end of file diff --git a/Dan.Common/Models/ReferenceRequirement.cs b/Dan.Common/Models/ReferenceRequirement.cs index 88df2ed..99d7e06 100644 --- a/Dan.Common/Models/ReferenceRequirement.cs +++ b/Dan.Common/Models/ReferenceRequirement.cs @@ -1,5 +1,8 @@ namespace Dan.Common.Models; +/// +/// Requirement for reference +/// [DataContract] public class ReferenceRequirement : Requirement { diff --git a/Dan.Common/Models/Requirement.cs b/Dan.Common/Models/Requirement.cs index 4e8adc6..6c90d5f 100644 --- a/Dan.Common/Models/Requirement.cs +++ b/Dan.Common/Models/Requirement.cs @@ -25,9 +25,16 @@ public class Requirement [DataMember(Name = "appliesToServiceContext")] public List AppliesToServiceContext = new(); + /// + /// Flag if requirement is needed on evidence harvester + /// [DataMember(Name = "requiredOnEvidenceHarvester")] public bool RequiredOnEvidenceHarvester = true; + /// + /// This causes Json.NET to skip serializing AppliesToServiceContext if it's empty, as it + /// may be confusing that this being empty means it applies to _all_ service contexts + /// public bool ShouldSerializeAppliesToServiceContext() { // This causes Json.NET to skip serializing AppliesToServiceContext if it's empty, as it diff --git a/Dan.Common/Models/ServiceContext.cs b/Dan.Common/Models/ServiceContext.cs index 79f1403..e8f7949 100644 --- a/Dan.Common/Models/ServiceContext.cs +++ b/Dan.Common/Models/ServiceContext.cs @@ -8,21 +8,39 @@ namespace Dan.Common.Models; [DataContract] public class ServiceContext { + /// + /// Name of the service context + /// [DataMember(Name = "name")] public string Name { get; set; } = string.Empty; + /// + /// Identifier of the service context + /// [DataMember(Name = "id")] public string Id { get; set; } = string.Empty; + /// + /// Description of the service context + /// [DataMember(Name = "description")] public string? Description { get; set; } + /// + /// List of languages that are valid for the service context + /// [DataMember(Name = "validLanguages")] public List ValidLanguages { get; set; } = new(); + /// + /// List of requirements needed to access datasets in the service context + /// [DataMember(Name = "authorizationRequirements")] public List AuthorizationRequirements { get; set; } = new(); + /// + /// Text templates with localised values for the service context + /// [DataMember(Name = "serviceContextTextTemplate")] public IServiceContextTextTemplate? ServiceContextTextTemplate { get; set; } } \ No newline at end of file diff --git a/Dan.Common/Models/SimpleEntityRegistryUnit.cs b/Dan.Common/Models/SimpleEntityRegistryUnit.cs index 86d1d14..c9abcfe 100644 --- a/Dan.Common/Models/SimpleEntityRegistryUnit.cs +++ b/Dan.Common/Models/SimpleEntityRegistryUnit.cs @@ -1,4 +1,6 @@ namespace Dan.Common.Models; + +#pragma warning disable 1591 public class SimpleEntityRegistryUnit { public string OrganizationNumber { get; set; } = string.Empty; @@ -9,3 +11,4 @@ public class SimpleEntityRegistryUnit public List? IndustrialCodes { get; set; } public bool IsDeleted { get; set; } } +#pragma warning restore 1591 \ No newline at end of file diff --git a/Dan.Common/Models/Subject.cs b/Dan.Common/Models/Subject.cs index 95568f8..6d42671 100644 --- a/Dan.Common/Models/Subject.cs +++ b/Dan.Common/Models/Subject.cs @@ -1,8 +1,14 @@ namespace Dan.Common.Models; +/// +/// Model to get subject from http request +/// [DataContract] public class Subject { + /// + /// Subject identifier + /// [DataMember(Name = "subject")] public string? SubjectId { get; set; } } \ No newline at end of file diff --git a/Dan.Common/Models/WhiteListFromConfigRequirement.cs b/Dan.Common/Models/WhiteListFromConfigRequirement.cs index 1845f50..ac74268 100644 --- a/Dan.Common/Models/WhiteListFromConfigRequirement.cs +++ b/Dan.Common/Models/WhiteListFromConfigRequirement.cs @@ -6,14 +6,23 @@ [DataContract] public class WhiteListFromConfigRequirement : Requirement { + /// + /// Owner requirement configuration + /// [DataMember(Name = "ownerConfigKey")] [Required] public string? OwnerConfigKey { get; set; } + /// + /// Config for valid requestors + /// [DataMember(Name = "requestorConfigKey")] [Required] public string? RequestorConfigKey { get; set; } + /// + /// Config for valid subjects + /// [DataMember(Name = "subjectConfigKey")] [Required] public string? SubjectConfigKey { get; set; } diff --git a/Dan.Common/Models/WhiteListRequirement.cs b/Dan.Common/Models/WhiteListRequirement.cs index 649f536..2c63334 100644 --- a/Dan.Common/Models/WhiteListRequirement.cs +++ b/Dan.Common/Models/WhiteListRequirement.cs @@ -14,6 +14,9 @@ public class WhiteListRequirement : Requirement [Required] public List> AllowedParties { get; set; } + /// + /// Default constructor, sets AllowedParties to new List + /// public WhiteListRequirement() { AllowedParties = new List>(); diff --git a/Dan.Common/Services/DefaultEntityRegistryApiClientService.cs b/Dan.Common/Services/DefaultEntityRegistryApiClientService.cs index 49d2b25..c099d53 100644 --- a/Dan.Common/Services/DefaultEntityRegistryApiClientService.cs +++ b/Dan.Common/Services/DefaultEntityRegistryApiClientService.cs @@ -2,15 +2,24 @@ using Dan.Common.Interfaces; namespace Dan.Common.Services; +/// +/// Default implementation of IEntityRegistryApiClientService +/// public class DefaultEntityRegistryApiClientService : IEntityRegistryApiClientService { private readonly IHttpClientFactory _clientFactory; + /// + /// Default constructor, sets _clientfactory to provided IHttpClientFactory + /// public DefaultEntityRegistryApiClientService(IHttpClientFactory clientFactory) { _clientFactory = clientFactory; } + /// + /// Get entity registry unit + /// public async Task GetUpstreamEntityRegistryUnitAsync(Uri registryApiUri) { var client = _clientFactory.CreateClient("entityRegistryClient"); diff --git a/Dan.Common/Services/EntityRegistryService.cs b/Dan.Common/Services/EntityRegistryService.cs index 87ad32f..c05046f 100644 --- a/Dan.Common/Services/EntityRegistryService.cs +++ b/Dan.Common/Services/EntityRegistryService.cs @@ -2,13 +2,31 @@ using Dan.Common.Interfaces; namespace Dan.Common.Services; +/// +/// Default implementation of IEntityRegistryService +/// public class EntityRegistryService : IEntityRegistryService { private readonly IEntityRegistryApiClientService _entityRegistryApiClientService; + + /// + /// Flag to set if using PpeProxyMainUnitLookupEndpoint or MainUnitLookupEndpoint + /// public bool UseCoreProxy { get; set; } = true; + + /// + /// Flag to set if allowed to look up synthetic users + /// public bool AllowTestCcrLookup { get; set; } = false; + /// + /// CCR proxy main unit dataset name + /// public const string CcrProxyMainUnitDatasetName = "_ccrproxymain"; + + /// + /// CCR proxy sub unit dataset name + /// public const string CcrProxySubUnitDatasetName = "_ccrproxysub"; private const string MainUnitLookupEndpoint = "https://data.brreg.no/enhetsregisteret/api/enheter/{0}"; @@ -37,18 +55,30 @@ private enum UnitType SubUnit }; + /// + /// Default constructor + /// public EntityRegistryService(IEntityRegistryApiClientService entityRegistryApiClientService) { _entityRegistryApiClientService = entityRegistryApiClientService; } + /// + /// Gets simple entity registry unit + /// public async Task Get(string organizationNumber, bool attemptSubUnitLookupIfNotFound = true, bool nestToAndReturnMainUnit = false, bool subUnitOnly = false) => MapToEntityRegistryUnit(await GetFull(organizationNumber, attemptSubUnitLookupIfNotFound, nestToAndReturnMainUnit, subUnitOnly)); + /// + /// Gets simple entity registry main unit + /// public async Task GetMainUnit(string organizationNumber) => await Get(organizationNumber, attemptSubUnitLookupIfNotFound: false, nestToAndReturnMainUnit: true); + /// + /// Get full entity registry unit + /// public async Task GetFull(string organizationNumber, bool attemptSubUnitLookupIfNotFound = true, bool nestToAndReturnMainUnit = false, bool subUnitOnly = false) { @@ -99,35 +129,58 @@ public EntityRegistryService(IEntityRegistryApiClientService entityRegistryApiCl return unit; } + /// + /// Get full entity registry main unit + /// public async Task GetFullMainUnit(string organizationNumber) => await GetFull(organizationNumber, attemptSubUnitLookupIfNotFound: false, nestToAndReturnMainUnit: true); + /// + /// Checks if an entity registry unit is a main unit + /// public bool IsMainUnit(SimpleEntityRegistryUnit unit) { return !IsSubUnit(unit); } + /// + /// Checks if an entity registry unit is a main unit + /// public bool IsMainUnit(EntityRegistryUnit unit) => IsMainUnit(MapToEntityRegistryUnit(unit)!); + /// + /// Checks if an entity registry unit is a main unit + /// public async Task IsMainUnit(string organizationNumber) { var unit = await Get(organizationNumber, attemptSubUnitLookupIfNotFound: false); return unit != null && IsMainUnit(unit); } + /// + /// Checks if an entity registry unit is a sub unit + /// public bool IsSubUnit(SimpleEntityRegistryUnit unit) { return !string.IsNullOrEmpty(unit.ParentUnit); } + /// + /// Checks if an entity registry unit is a sub unit + /// public bool IsSubUnit(EntityRegistryUnit unit) => IsSubUnit(MapToEntityRegistryUnit(unit)!); - + /// + /// Checks if an entity registry unit is a sub unit + /// public async Task IsSubUnit(string organizationNumber) { var unit = await Get(organizationNumber, subUnitOnly: true); return unit != null && IsSubUnit(unit); } + /// + /// Checks if an entity registry unit is a public agency + /// public bool IsPublicAgency(SimpleEntityRegistryUnit unit) { return PublicSectorUnitTypes.Contains(unit.OrganizationForm) @@ -136,8 +189,14 @@ public bool IsPublicAgency(SimpleEntityRegistryUnit unit) || PublicSectorOrganizations.Contains(unit.OrganizationNumber); } + /// + /// Checks if an entity registry unit is a public agency + /// public bool IsPublicAgency(EntityRegistryUnit unit) => IsPublicAgency(MapToEntityRegistryUnit(unit)!); + /// + /// Checks if an entity registry unit is a public agency + /// public async Task IsPublicAgency(string organizationNumber) { var unit = await Get(organizationNumber); diff --git a/Dan.Common/Util/DateFormatConverter.cs b/Dan.Common/Util/DateFormatConverter.cs index 8abbb03..c228cbf 100644 --- a/Dan.Common/Util/DateFormatConverter.cs +++ b/Dan.Common/Util/DateFormatConverter.cs @@ -1,6 +1,13 @@ namespace Dan.Common.Util; + +/// +/// IsoDateTimeConverter +/// public class DateFormatConverter : IsoDateTimeConverter { + /// + /// Constructor for setting DateTimeFormat for IsoDateTimeConverter + /// public DateFormatConverter(string format) { DateTimeFormat = format; diff --git a/Dan.Common/Util/EvidenceSourceResponse.cs b/Dan.Common/Util/EvidenceSourceResponse.cs index 1c0160e..f4ff9fa 100644 --- a/Dan.Common/Util/EvidenceSourceResponse.cs +++ b/Dan.Common/Util/EvidenceSourceResponse.cs @@ -9,6 +9,9 @@ namespace Dan.Common.Util; public static class EvidenceSourceResponse { + /// + /// Returns an evidence value response + /// public static async Task CreateResponse(HttpRequestData req, Func>> func) { try diff --git a/Dan.Common/Util/KeyedLock.cs b/Dan.Common/Util/KeyedLock.cs index 66f9a1e..afc2d51 100644 --- a/Dan.Common/Util/KeyedLock.cs +++ b/Dan.Common/Util/KeyedLock.cs @@ -3,6 +3,8 @@ namespace Dan.Common.Util; +//Obsolete, not adding descriptions +#pragma warning disable 1591 [Obsolete("Please use AsyncKeyedLocker instead.")] public class KeyedLock where TKey : notnull { @@ -39,4 +41,5 @@ public bool Wait(TKey key, int millisecondsTimeout, [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Wait(TKey key, CancellationToken cancellationToken = default) => Wait(key, Timeout.Infinite, cancellationToken); -} \ No newline at end of file +} +#pragma warning restore 1591 \ No newline at end of file From 807b2404ed885bc2f1e20d24667efba344ec4e0f Mon Sep 17 00:00:00 2001 From: Sondre Jahrsengene Date: Tue, 21 Jan 2025 13:13:35 +0100 Subject: [PATCH 2/2] feat: make explicit model for dataset alias --- Dan.Common/Models/DatasetAlias.cs | 17 +++++++++++++++++ Dan.Common/Models/EvidenceCode.cs | 4 ++-- .../AvailableEvidenceCodesServiceTest.cs | 6 +++--- .../Services/AvailableEvidenceCodesService.cs | 10 +++++----- Dan.PluginTest/Metadata.cs | 6 +++--- 5 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 Dan.Common/Models/DatasetAlias.cs diff --git a/Dan.Common/Models/DatasetAlias.cs b/Dan.Common/Models/DatasetAlias.cs new file mode 100644 index 0000000..399f51e --- /dev/null +++ b/Dan.Common/Models/DatasetAlias.cs @@ -0,0 +1,17 @@ +namespace Dan.Common.Models; + +/// +/// Model for alias for a dataset +/// +public class DatasetAlias +{ + /// + /// Which service context this alias applies to + /// + public string ServiceContext { get; set; } = string.Empty; + + /// + /// Alias name + /// + public string DatasetAliasName { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/Dan.Common/Models/EvidenceCode.cs b/Dan.Common/Models/EvidenceCode.cs index 3cb217e..4b33f24 100644 --- a/Dan.Common/Models/EvidenceCode.cs +++ b/Dan.Common/Models/EvidenceCode.cs @@ -147,10 +147,10 @@ public class EvidenceCode public string? License { get; set; } /// - /// Optional setting for aliases. Key is service context, value is Dataset name + /// Optional setting for aliases /// Allows for the same dataset to be shared between service contexts with different names. /// [DataMember(Name = "datasetAliases")] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public Dictionary? DatasetAliases { get; set; } + public List? DatasetAliases { get; set; } } \ No newline at end of file diff --git a/Dan.Core.UnitTest/AvailableEvidenceCodesServiceTest.cs b/Dan.Core.UnitTest/AvailableEvidenceCodesServiceTest.cs index 4bf0786..135c637 100644 --- a/Dan.Core.UnitTest/AvailableEvidenceCodesServiceTest.cs +++ b/Dan.Core.UnitTest/AvailableEvidenceCodesServiceTest.cs @@ -61,10 +61,10 @@ public class AvailableEvidenceCodesServiceTest { EvidenceCodeName = "ec3", BelongsToServiceContexts = new List { "sc1", "sc2" }, - DatasetAliases = new Dictionary + DatasetAliases = new List { - {"sc1", "a1"}, - {"sc2", "a2"} + new() {ServiceContext = "sc1", DatasetAliasName = "a1"}, + new() {ServiceContext = "sc2", DatasetAliasName = "a2"} }, AuthorizationRequirements = new List { diff --git a/Dan.Core/Services/AvailableEvidenceCodesService.cs b/Dan.Core/Services/AvailableEvidenceCodesService.cs index d3ffc39..3cba656 100644 --- a/Dan.Core/Services/AvailableEvidenceCodesService.cs +++ b/Dan.Core/Services/AvailableEvidenceCodesService.cs @@ -105,7 +105,7 @@ public Dictionary GetAliases() { foreach (var alias in aliasedEvidenceCode.DatasetAliases!) { - aliases.Add(alias.Value, aliasedEvidenceCode.EvidenceCodeName); + aliases.Add(alias.DatasetAliasName, aliasedEvidenceCode.EvidenceCodeName); } } @@ -270,15 +270,15 @@ private static List SplitAliases(IEnumerable evidenc foreach (var alias in evidenceCode.DatasetAliases!) { var aliasedEvidenceCode = evidenceCode.DeepCopy(); - aliasedEvidenceCode.ServiceContext = alias.Key; - aliasedEvidenceCode.BelongsToServiceContexts = [alias.Key]; - aliasedEvidenceCode.EvidenceCodeName = alias.Value; + aliasedEvidenceCode.ServiceContext = alias.ServiceContext; + aliasedEvidenceCode.BelongsToServiceContexts = [alias.ServiceContext]; + aliasedEvidenceCode.EvidenceCodeName = alias.DatasetAliasName; aliasedEvidenceCode.DatasetAliases = null; aliasedEvidenceCode.AuthorizationRequirements = aliasedEvidenceCode .AuthorizationRequirements .Where(a => a.AppliesToServiceContext.Count == 0 || - a.AppliesToServiceContext.Contains(alias.Key)) + a.AppliesToServiceContext.Contains(alias.ServiceContext)) .ToList(); splitEvidenceCodes.Add(aliasedEvidenceCode); diff --git a/Dan.PluginTest/Metadata.cs b/Dan.PluginTest/Metadata.cs index 418421c..09926e0 100644 --- a/Dan.PluginTest/Metadata.cs +++ b/Dan.PluginTest/Metadata.cs @@ -36,10 +36,10 @@ public List GetEvidenceCodes() EvidenceCodeName = PluginConstants.DatasetOne, EvidenceSource = PluginConstants.Source, BelongsToServiceContexts = _serviceContexts, - DatasetAliases = new Dictionary() + DatasetAliases = new List() { - { DanTest, "AliasOne" }, - { AltinnStudioApps, "AliasTwo" }, + new (){ ServiceContext = DanTest, DatasetAliasName = "AliasOne" }, + new (){ ServiceContext = AltinnStudioApps, DatasetAliasName = "AliasTwo" }, }, Values = [