From edbfcf2bbd8f104aafbcc0bf01f77740a03cb7c0 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 25 Mar 2024 16:02:22 +0100 Subject: [PATCH 01/31] RegisterService client added --- src/Storage/Altinn.Platform.Storage.csproj | 2 + src/Storage/Configuration/GeneralSettings.cs | 5 + src/Storage/Configuration/PlatformSettings.cs | 31 +++++ .../Exceptions/PlatformHttpException.cs | 40 +++++++ src/Storage/Extensions/HttpClientExtension.cs | 56 +++++++++ src/Storage/Program.cs | 3 +- src/Storage/Services/IRegisterService.cs | 26 ++++ src/Storage/Services/RegisterService.cs | 113 ++++++++++++++++++ 8 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 src/Storage/Configuration/PlatformSettings.cs create mode 100644 src/Storage/Exceptions/PlatformHttpException.cs create mode 100644 src/Storage/Extensions/HttpClientExtension.cs create mode 100644 src/Storage/Services/IRegisterService.cs create mode 100644 src/Storage/Services/RegisterService.cs diff --git a/src/Storage/Altinn.Platform.Storage.csproj b/src/Storage/Altinn.Platform.Storage.csproj index 85fed13e..268aef0b 100644 --- a/src/Storage/Altinn.Platform.Storage.csproj +++ b/src/Storage/Altinn.Platform.Storage.csproj @@ -10,6 +10,8 @@ + + diff --git a/src/Storage/Configuration/GeneralSettings.cs b/src/Storage/Configuration/GeneralSettings.cs index 799ae824..49c01975 100644 --- a/src/Storage/Configuration/GeneralSettings.cs +++ b/src/Storage/Configuration/GeneralSettings.cs @@ -47,5 +47,10 @@ public class GeneralSettings /// Gets or sets the cache lifetime for application metadata document. /// public int AppMetadataCacheLifeTimeInSeconds { get; set; } + + /// + /// Name of the cookie for where JWT is stored + /// + public string JwtCookieName { get; set; } } } diff --git a/src/Storage/Configuration/PlatformSettings.cs b/src/Storage/Configuration/PlatformSettings.cs new file mode 100644 index 00000000..971c55b4 --- /dev/null +++ b/src/Storage/Configuration/PlatformSettings.cs @@ -0,0 +1,31 @@ +using System.Runtime.Serialization; + +namespace Altinn.Platform.Storage.Configuration +{ + /// + /// Represents a set of configuration options when communicating with the platform API. + /// Instances of this class is initialised with values from app settings. Some values can be overridden by environment variables. + /// + public class PlatformSettings + { + /// + /// Gets or sets the url for the Register API endpoint. + /// + public string ApiRegisterEndpoint { get; set; } + + /// + /// Gets or sets the url for the Profile API endpoint + /// + public string ApiProfileEndpoint { get; set; } + + /// + /// Gets or sets the apps domain used to match events source + /// + public string AppsDomain { get; set; } + + /// + /// The lifetime to cache subscriptions + /// + public int SubscriptionCachingLifetimeInSeconds { get; set; } + } +} diff --git a/src/Storage/Exceptions/PlatformHttpException.cs b/src/Storage/Exceptions/PlatformHttpException.cs new file mode 100644 index 00000000..ffbdd696 --- /dev/null +++ b/src/Storage/Exceptions/PlatformHttpException.cs @@ -0,0 +1,40 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Altinn.Platform.Storage.Exceptions +{ + /// + /// Exception class to hold exceptions when talking to the platform REST services + /// + public class PlatformHttpException : Exception + { + /// + /// Responsible for holding an http request exception towards platform. + /// + public HttpResponseMessage Response { get; } + + /// + /// Creates a platform exception + /// + /// The http response + /// A PlatformHttpException + public static async Task CreateAsync(HttpResponseMessage response) + { + string content = await response.Content.ReadAsStringAsync(); + string message = $"{(int)response.StatusCode} - {response.ReasonPhrase} - {content}"; + + return new PlatformHttpException(response, message); + } + + /// + /// Copy the response for further investigations + /// + /// the response + /// the message + public PlatformHttpException(HttpResponseMessage response, string message) : base(message) + { + this.Response = response; + } + } +} diff --git a/src/Storage/Extensions/HttpClientExtension.cs b/src/Storage/Extensions/HttpClientExtension.cs new file mode 100644 index 00000000..bd5b18ba --- /dev/null +++ b/src/Storage/Extensions/HttpClientExtension.cs @@ -0,0 +1,56 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Altinn.Platform.Storage.Extensions +{ + /// + /// This extension is created to make it easy to add a bearer token to a HttpRequests. + /// + public static class HttpClientExtension + { + /// + /// Extension that add authorization header to request + /// + /// The HttpClient + /// the authorization token (jwt) + /// The request Uri + /// The http content + /// The platformAccess tokens + /// A HttpResponseMessage + public static Task PostAsync(this HttpClient httpClient, string authorizationToken, string requestUri, HttpContent content, string platformAccessToken = null) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(requestUri, UriKind.Relative)); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + request.Content = content; + + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); + } + + return httpClient.SendAsync(request, CancellationToken.None); + } + + /// + /// Extension that add authorization header to request + /// + /// The HttpClient + /// the authorization token (jwt) + /// The request Uri + /// The platformAccess tokens + /// A HttpResponseMessage + public static Task GetAsync(this HttpClient httpClient, string authorizationToken, string requestUri, string platformAccessToken = null) + { + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); + } + + return httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, CancellationToken.None); + } + } +} diff --git a/src/Storage/Program.cs b/src/Storage/Program.cs index f8c36c1c..e2a3eb47 100644 --- a/src/Storage/Program.cs +++ b/src/Storage/Program.cs @@ -189,12 +189,13 @@ void ConfigureServices(IServiceCollection services, IConfiguration config) services.AddHealthChecks().AddCheck("storage_health_check"); services.AddHttpClient(); + services.AddHttpClient(); services.Configure(config.GetSection("AzureStorageConfiguration")); services.Configure(config.GetSection("GeneralSettings")); services.Configure(config.GetSection("kvSetting")); services.Configure(config.GetSection("PepSettings")); - services.Configure(config.GetSection("PlatformSettings")); + services.Configure(config.GetSection("PlatformSettings")); services.Configure(config.GetSection("QueueStorageSettings")); services.Configure(config.GetSection("AccessTokenSettings")); services.Configure(config.GetSection("PostgreSqlSettings")); diff --git a/src/Storage/Services/IRegisterService.cs b/src/Storage/Services/IRegisterService.cs new file mode 100644 index 00000000..047537e3 --- /dev/null +++ b/src/Storage/Services/IRegisterService.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Altinn.Platform.Register.Models; + +namespace Altinn.Platform.Storage.Services +{ + /// + /// Interface to handle services exposed in Platform Register + /// + public interface IRegisterService + { + /// + /// Returns party information + /// + /// The partyId + /// The party for the given partyId + Task GetParty(int partyId); + + /// + /// Party lookup + /// + /// organisation number + /// f or d number + /// + Task PartyLookup(string orgNo, string person); + } +} diff --git a/src/Storage/Services/RegisterService.cs b/src/Storage/Services/RegisterService.cs new file mode 100644 index 00000000..c022391f --- /dev/null +++ b/src/Storage/Services/RegisterService.cs @@ -0,0 +1,113 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Platform.Register.Models; +using Altinn.Platform.Storage.Configuration; +using Altinn.Platform.Storage.Exceptions; +using Altinn.Platform.Storage.Extensions; + +using AltinnCore.Authentication.Utils; + +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Altinn.Platform.Storage.Services +{ + /// + /// Handles register service + /// + public class RegisterService : IRegisterService + { + private readonly HttpClient _client; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly GeneralSettings _generalSettings; + private readonly IAccessTokenGenerator _accessTokenGenerator; + private readonly ILogger _logger; + + private readonly JsonSerializerOptions _serializerOptions; + + /// + /// Initializes a new instance of the class. + /// + public RegisterService( + HttpClient httpClient, + IHttpContextAccessor httpContextAccessor, + IAccessTokenGenerator accessTokenGenerator, + IOptions generalSettings, + IOptions platformSettings, + ILogger logger) + { + httpClient.BaseAddress = new Uri(platformSettings.Value.ApiRegisterEndpoint); + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _client = httpClient; + _httpContextAccessor = httpContextAccessor; + _generalSettings = generalSettings.Value; + _accessTokenGenerator = accessTokenGenerator; + _logger = logger; + + _serializerOptions = new() + { + PropertyNameCaseInsensitive = true, + Converters = { new JsonStringEnumConverter() } + }; + } + + /// + public async Task GetParty(int partyId) + { + Party party = null; + + string endpointUrl = $"parties/{partyId}"; + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _generalSettings.JwtCookieName); + string accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "events"); + + HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, accessToken); + if (response.StatusCode == HttpStatusCode.OK) + { + party = await response.Content.ReadFromJsonAsync(_serializerOptions); + } + else + { + _logger.LogError("// Getting party with partyID {partyId} failed with statuscode {response.StatusCode}", partyId, response.StatusCode); + } + + return party; + } + + /// + public async Task PartyLookup(string orgNo, string person) + { + string endpointUrl = "parties/lookup"; + + PartyLookup partyLookup = new PartyLookup() { Ssn = person, OrgNo = orgNo }; + + string bearerToken = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _generalSettings.JwtCookieName); + string accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "events"); + + StringContent content = new StringContent(JsonSerializer.Serialize(partyLookup)); + content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); + + HttpResponseMessage response = await _client.PostAsync(bearerToken, endpointUrl, content, accessToken); + if (response.StatusCode == HttpStatusCode.OK) + { + Party party = await response.Content.ReadFromJsonAsync(_serializerOptions); + return party.PartyId; + } + else + { + string reason = await response.Content.ReadAsStringAsync(); + _logger.LogError("// RegisterService // PartyLookup // Failed to lookup party in platform register. Response {response}. \n Reason {reason}.", response, reason); + + throw await PlatformHttpException.CreateAsync(response); + } + } + } +} From 88e9138815e7a0ab585500fd46c113014077166c Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 28 Mar 2024 13:45:19 +0100 Subject: [PATCH 02/31] Party ID look up with register service client --- .../Controllers/InstancesController.cs | 23 ++++++++++++- src/Storage/Helpers/InstanceHelper.cs | 33 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Storage/Controllers/InstancesController.cs b/src/Storage/Controllers/InstancesController.cs index ced7099e..78195254 100644 --- a/src/Storage/Controllers/InstancesController.cs +++ b/src/Storage/Controllers/InstancesController.cs @@ -46,6 +46,7 @@ public class InstancesController : ControllerBase private readonly IInstanceEventService _instanceEventService; private readonly string _storageBaseAndHost; private readonly GeneralSettings _generalSettings; + private readonly IRegisterService _registerService; /// /// Initializes a new instance of the class @@ -56,6 +57,7 @@ public class InstancesController : ControllerBase /// the logger /// the authorization service. /// the instance event service. + /// the instance register service. /// the general settings. public InstancesController( IInstanceRepository instanceRepository, @@ -64,6 +66,7 @@ public InstancesController( ILogger logger, IAuthorization authorizationService, IInstanceEventService instanceEventService, + IRegisterService registerService, IOptions settings) { _instanceRepository = instanceRepository; @@ -73,6 +76,7 @@ public InstancesController( _storageBaseAndHost = $"{settings.Value.Hostname}/storage/api/v1/"; _authorizationService = authorizationService; _instanceEventService = instanceEventService; + _registerService = registerService; _generalSettings = settings.Value; } @@ -86,6 +90,7 @@ public InstancesController( /// Process end state. /// Process ended value. /// Instance owner id. + /// Instance owner identifier, i.e. Person:PersonNumber, Organisation: OrganisationNumber, Username:Username. /// Last changed date. /// Created time. /// The visible after date time. @@ -111,6 +116,7 @@ public async Task>> GetInstances( [FromQuery(Name = "process.endEvent")] string processEndEvent, [FromQuery(Name = "process.ended")] string processEnded, [FromQuery(Name = "instanceOwner.partyId")] int? instanceOwnerPartyId, + [FromHeader(Name = "X-Ai-InstanceOwnerIdentifier")] string instanceOwnerIdentifier, [FromQuery] string lastChanged, [FromQuery] string created, [FromQuery(Name = "visibleAfter")] string visibleAfter, @@ -155,7 +161,22 @@ public async Task>> GetInstances( { if (instanceOwnerPartyId == null) { - return BadRequest("InstanceOwnerPartyId must be defined."); + if (string.IsNullOrEmpty(instanceOwnerIdentifier)) + { + return BadRequest("Either InstanceOwnerPartyId or InstanceOwnerIdentifier must need to be defined."); + } + + (string instanceOwnerIdType, string instanceOwnerIdValue) = InstanceHelper.GetIdentifierFromInstanceOwnerIdentifier(instanceOwnerIdentifier); + + if (string.IsNullOrEmpty(instanceOwnerIdType) || string.IsNullOrEmpty(instanceOwnerIdValue)) + { + return BadRequest("Invalid InstanceOwnerIdentifier."); + } + + string orgNo = instanceOwnerIdType == "organization" ? instanceOwnerIdValue : string.Empty; + string person = instanceOwnerIdType == "person" ? instanceOwnerIdValue : string.Empty; + + instanceOwnerPartyId = await _registerService.PartyLookup(orgNo, person); } } else diff --git a/src/Storage/Helpers/InstanceHelper.cs b/src/Storage/Helpers/InstanceHelper.cs index e620e239..3dcf1636 100644 --- a/src/Storage/Helpers/InstanceHelper.cs +++ b/src/Storage/Helpers/InstanceHelper.cs @@ -246,5 +246,38 @@ private static bool HideOnCurrentTask(HideSettings hideSettings, ProcessElementI return hideSettings.HideOnTask.Contains(currentTask.ElementId); } + + /// + /// Parsing instanceOwnerIdentifier string and find the number type and value. + /// + /// The list of applications + public static (string InstanceOwnerIdType, string InstanceOwnerIdValue) GetIdentifierFromInstanceOwnerIdentifier(string instanceOwnerIdentifier) + { + string partyType = null; + string partyNumber = null; + + if (string.IsNullOrEmpty(instanceOwnerIdentifier)) + { + return (string.Empty, string.Empty); + } + + string[] parts = instanceOwnerIdentifier.Split(':'); + if (parts.Length != 2) + { + return (string.Empty, string.Empty); + } + + partyType = parts[0]; + partyNumber = parts[1]; + + string[] partyTypeHayStack = ["person", "organization", "username"]; + + if (Array.IndexOf(partyTypeHayStack, partyType.ToLower()) != -1) + { + return (partyType.ToLower(), partyNumber); + } + + return (string.Empty, string.Empty); + } } } From b98d9edb1a69cbf1263dcee7917eb0cf4e2a152c Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 4 Apr 2024 12:31:58 +0200 Subject: [PATCH 03/31] Fixed issues and typos --- src/Storage/Controllers/InstancesController.cs | 2 +- src/Storage/Helpers/InstanceHelper.cs | 2 +- src/Storage/Services/RegisterService.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Storage/Controllers/InstancesController.cs b/src/Storage/Controllers/InstancesController.cs index 78195254..7a73bbef 100644 --- a/src/Storage/Controllers/InstancesController.cs +++ b/src/Storage/Controllers/InstancesController.cs @@ -90,7 +90,7 @@ public InstancesController( /// Process end state. /// Process ended value. /// Instance owner id. - /// Instance owner identifier, i.e. Person:PersonNumber, Organisation: OrganisationNumber, Username:Username. + /// Instance owner identifier, i.e. Person:PersonNumber, Organisation:OrganisationNumber, Username:Username. /// Last changed date. /// Created time. /// The visible after date time. diff --git a/src/Storage/Helpers/InstanceHelper.cs b/src/Storage/Helpers/InstanceHelper.cs index 3dcf1636..4bab4d7f 100644 --- a/src/Storage/Helpers/InstanceHelper.cs +++ b/src/Storage/Helpers/InstanceHelper.cs @@ -274,7 +274,7 @@ public static (string InstanceOwnerIdType, string InstanceOwnerIdValue) GetIdent if (Array.IndexOf(partyTypeHayStack, partyType.ToLower()) != -1) { - return (partyType.ToLower(), partyNumber); + return (partyType.ToLower(), partyNumber.Replace(" ", string.Empty)); } return (string.Empty, string.Empty); diff --git a/src/Storage/Services/RegisterService.cs b/src/Storage/Services/RegisterService.cs index c022391f..f91814fc 100644 --- a/src/Storage/Services/RegisterService.cs +++ b/src/Storage/Services/RegisterService.cs @@ -90,7 +90,7 @@ public async Task PartyLookup(string orgNo, string person) PartyLookup partyLookup = new PartyLookup() { Ssn = person, OrgNo = orgNo }; string bearerToken = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _generalSettings.JwtCookieName); - string accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "events"); + string accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "storage"); StringContent content = new StringContent(JsonSerializer.Serialize(partyLookup)); content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); From 695a52135324d02f9a5d3e307ce34affc7b9ce22 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 4 Apr 2024 12:43:15 +0200 Subject: [PATCH 04/31] IAccessTokenGenerator added as singleton --- src/Storage/Program.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Storage/Program.cs b/src/Storage/Program.cs index e2a3eb47..a81d264e 100644 --- a/src/Storage/Program.cs +++ b/src/Storage/Program.cs @@ -6,6 +6,7 @@ using Altinn.Common.AccessToken; using Altinn.Common.AccessToken.Configuration; using Altinn.Common.AccessToken.Services; +using Altinn.Common.AccessTokenClient.Services; using Altinn.Common.PEP.Authorization; using Altinn.Common.PEP.Clients; using Altinn.Common.PEP.Configuration; @@ -251,6 +252,7 @@ void ConfigureServices(IServiceCollection services, IConfiguration config) services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddSingleton(); services.AddTransient(); services.AddTransient(); services.AddTransient(); From 54a45fecade594018c18a5f08ab4ee385e889814 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 4 Apr 2024 13:11:51 +0200 Subject: [PATCH 05/31] RegisterService test added --- .../TestingServices/RegisterServiceTest.cs | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 test/UnitTest/TestingServices/RegisterServiceTest.cs diff --git a/test/UnitTest/TestingServices/RegisterServiceTest.cs b/test/UnitTest/TestingServices/RegisterServiceTest.cs new file mode 100644 index 00000000..5a749ea6 --- /dev/null +++ b/test/UnitTest/TestingServices/RegisterServiceTest.cs @@ -0,0 +1,183 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Platform.Register.Enums; +using Altinn.Platform.Register.Models; +using Altinn.Platform.Storage.Configuration; +using Altinn.Platform.Storage.Exceptions; +using Altinn.Platform.Storage.Services; + +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +using Moq; +using Moq.Protected; + +using Xunit; + +namespace Altinn.Platform.Storage.UnitTest.TestingServices +{ + public class RegisterServiceTest + { + private readonly Mock> _platformSettings; + private readonly Mock> _generalSettings; + private readonly Mock _handlerMock; + private readonly Mock _contextAccessor; + private readonly Mock _accessTokenGenerator; + + public RegisterServiceTest() + { + _platformSettings = new Mock>(); + _generalSettings = new Mock>(); + _handlerMock = new Mock(MockBehavior.Strict); + _contextAccessor = new Mock(); + _accessTokenGenerator = new Mock(); + } + + [Fact] + public async Task PartyLookup_MatchFound_IdReturned() + { + // Arrange + Party party = new Party + { + PartyId = 500000, + OrgNumber = "897069650", + PartyTypeName = PartyType.Organisation + }; + int expected = 500000; + HttpResponseMessage httpResponseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(JsonSerializer.Serialize(party), Encoding.UTF8, "application/json") + }; + + HttpRequestMessage actualRequest = null; + void SetRequest(HttpRequestMessage request) => actualRequest = request; + InitializeMocks(httpResponseMessage, SetRequest); + + HttpClient httpClient = new HttpClient(_handlerMock.Object); + + RegisterService target = new RegisterService( + httpClient, + _contextAccessor.Object, + _accessTokenGenerator.Object, + _generalSettings.Object, + _platformSettings.Object, + new Mock>().Object); + + // Act + int actual = await target.PartyLookup("897069650", null); + + // Assert + Assert.Equal(expected, actual); + } + + [Fact] + public async Task GetParty_SuccessResponse_PartyTypeDeserializedSuccessfully() + { + // Arrange + PartyType expectedPartyType = PartyType.Organisation; + + string repsonseString = "{\"partyId\": 500000," + + "\"partyTypeName\": \"Organisation\"," + + "\"orgNumber\": \"897069650\"," + + "\"unitType\": \"AS\"," + + "\"name\": \"DDG Fitness\"," + + "\"isDeleted\": false," + + "\"onlyHierarchyElementWithNoAccess\": false," + + "\"organization\": {\"orgNumber\": \"897069650\",\"name\": \"DDG Fitness\",\"unitType\": \"AS\",\"telephoneNumber\": \"12345678\",\"mobileNumber\": \"92010000\",\"faxNumber\": \"92110000\",\"eMailAddress\": \"central@ddgfitness.no\",\"internetAddress\": \"http://ddgfitness.no\",\"mailingAddress\": \"Sofies Gate 1\",\"mailingPostalCode\": \"0170\",\"mailingPostalCity\": \"Oslo\",\"businessAddress\": \"Sofies Gate 1\",\"businessPostalCode\": \"0170\",\"businessPostalCity\": \"By\",\"unitStatus\": null},\"childParties\": null\r\n}"; + + HttpResponseMessage httpResponseMessage = new() + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(repsonseString, Encoding.UTF8, "application/json") + }; + + HttpRequestMessage actualRequest = null; + void SetRequest(HttpRequestMessage request) => actualRequest = request; + InitializeMocks(httpResponseMessage, SetRequest); + + HttpClient httpClient = new HttpClient(_handlerMock.Object); + + RegisterService target = new RegisterService( + httpClient, + _contextAccessor.Object, + _accessTokenGenerator.Object, + _generalSettings.Object, + _platformSettings.Object, + new Mock>().Object); + + // Act + Party actual = await target.GetParty(500000); + + // Assert + Assert.Equal(expectedPartyType, actual.PartyTypeName); + } + + [Fact] + public async Task PartyLookup_ResponseIsNotSuccessful_PlatformExceptionThrown() + { + // Arrange + HttpResponseMessage httpResponseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.NotFound, + Content = new StringContent(string.Empty) + }; + + HttpRequestMessage actualRequest = null; + void SetRequest(HttpRequestMessage request) => actualRequest = request; + InitializeMocks(httpResponseMessage, SetRequest); + + HttpClient httpClient = new HttpClient(_handlerMock.Object); + + RegisterService target = new RegisterService( + httpClient, + _contextAccessor.Object, + _accessTokenGenerator.Object, + _generalSettings.Object, + _platformSettings.Object, + new Mock>().Object); + + // Act & Assert + await Assert.ThrowsAsync(async () => { await target.PartyLookup("16069412345", null); }); + } + + private void InitializeMocks(HttpResponseMessage httpResponseMessage, Action callback) + { + PlatformSettings platformSettings = new PlatformSettings + { + ApiRegisterEndpoint = "http://localhost:5101/register/api/v1/" + }; + + _platformSettings.Setup(s => s.Value).Returns(platformSettings); + + GeneralSettings generalSettings = new GeneralSettings + { + JwtCookieName = "AltinnStudioRuntime" + }; + + _generalSettings.Setup(s => s.Value).Returns(generalSettings); + + _contextAccessor.Setup(s => s.HttpContext).Returns(new DefaultHttpContext()); + + _accessTokenGenerator.Setup(s => s.GenerateAccessToken(It.IsAny(), It.IsAny())) + .Returns(string.Empty); + + _handlerMock.Protected() + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny()) + .Callback((request, _) => callback(request)) + .ReturnsAsync(httpResponseMessage) + .Verifiable(); + } + } +} From fe36cb652c4263d6c98a570af7c17aa493345e39 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 4 Apr 2024 13:22:34 +0200 Subject: [PATCH 06/31] Username removed from haystack --- src/Storage/Helpers/InstanceHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Helpers/InstanceHelper.cs b/src/Storage/Helpers/InstanceHelper.cs index 4bab4d7f..b82fcf46 100644 --- a/src/Storage/Helpers/InstanceHelper.cs +++ b/src/Storage/Helpers/InstanceHelper.cs @@ -270,7 +270,7 @@ public static (string InstanceOwnerIdType, string InstanceOwnerIdValue) GetIdent partyType = parts[0]; partyNumber = parts[1]; - string[] partyTypeHayStack = ["person", "organization", "username"]; + string[] partyTypeHayStack = ["person", "organization"]; if (Array.IndexOf(partyTypeHayStack, partyType.ToLower()) != -1) { From e800c383f6bbc305476b2b6824a6e7dda2e771ba Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 4 Apr 2024 13:49:01 +0200 Subject: [PATCH 07/31] Tests added for GetIdentifierFromInstanceOwnerIdentifier --- src/Storage/Helpers/InstanceHelper.cs | 2 +- .../HelperTests/InstanceHelperTest.cs | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Storage/Helpers/InstanceHelper.cs b/src/Storage/Helpers/InstanceHelper.cs index b82fcf46..7599a6f8 100644 --- a/src/Storage/Helpers/InstanceHelper.cs +++ b/src/Storage/Helpers/InstanceHelper.cs @@ -272,7 +272,7 @@ public static (string InstanceOwnerIdType, string InstanceOwnerIdValue) GetIdent string[] partyTypeHayStack = ["person", "organization"]; - if (Array.IndexOf(partyTypeHayStack, partyType.ToLower()) != -1) + if (Array.IndexOf(partyTypeHayStack, partyType.ToLower().Replace(" ", string.Empty)) != -1) { return (partyType.ToLower(), partyNumber.Replace(" ", string.Empty)); } diff --git a/test/UnitTest/HelperTests/InstanceHelperTest.cs b/test/UnitTest/HelperTests/InstanceHelperTest.cs index b6dfc2c9..9dd8f4f0 100644 --- a/test/UnitTest/HelperTests/InstanceHelperTest.cs +++ b/test/UnitTest/HelperTests/InstanceHelperTest.cs @@ -539,5 +539,27 @@ public void ConvertToSBLInstanceEvent_SingleEvent_AllPropertiesMapped() Assert.Equal(1337, actual.User.UserId); Assert.Equal("test.event", actual.EventType); } + + [Theory] + [InlineData(null, "", "")] + [InlineData("", "", "")] + [InlineData("person12345", "", "")] + [InlineData("invalid:12345", "", "")] + [InlineData("PERSON:12345", "person", "12345")] + [InlineData("organization: 12345 ", "organization", "12345")] + [InlineData(" person:12345", "person", "12345")] + [InlineData("Person:12345", "person", "12345")] + [InlineData("organization: 123 45", "organization", "12345")] + [InlineData("organization:12345", "organization", "12345")] + [InlineData("Organization:67890", "organization", "67890")] + [InlineData(" Organization : 456 78", "organization", "45678")] + public void GetIdentifierFromInstanceOwnerIdentifier_ValidInput_ReturnsCorrectTuple(string instanceOwnerIdentifier, string expectedType, string expectedValue) + { + // Act + var result = InstanceHelper.GetIdentifierFromInstanceOwnerIdentifier(instanceOwnerIdentifier); + + // Assert + Assert.Equal((expectedType, expectedValue), result); + } } } From ab22b0aa74b011cc37d8a839da89fee47fa6028e Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 4 Apr 2024 13:59:24 +0200 Subject: [PATCH 08/31] GetIdentifierFromInstanceOwnerIdentifier refactored --- src/Storage/Helpers/InstanceHelper.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Storage/Helpers/InstanceHelper.cs b/src/Storage/Helpers/InstanceHelper.cs index 7599a6f8..53687f77 100644 --- a/src/Storage/Helpers/InstanceHelper.cs +++ b/src/Storage/Helpers/InstanceHelper.cs @@ -261,7 +261,7 @@ public static (string InstanceOwnerIdType, string InstanceOwnerIdValue) GetIdent return (string.Empty, string.Empty); } - string[] parts = instanceOwnerIdentifier.Split(':'); + string[] parts = instanceOwnerIdentifier.Replace(" ", string.Empty).ToLower().Split(':'); if (parts.Length != 2) { return (string.Empty, string.Empty); @@ -272,9 +272,9 @@ public static (string InstanceOwnerIdType, string InstanceOwnerIdValue) GetIdent string[] partyTypeHayStack = ["person", "organization"]; - if (Array.IndexOf(partyTypeHayStack, partyType.ToLower().Replace(" ", string.Empty)) != -1) + if (Array.IndexOf(partyTypeHayStack, partyType) != -1) { - return (partyType.ToLower(), partyNumber.Replace(" ", string.Empty)); + return (partyType, partyNumber); } return (string.Empty, string.Empty); From e0ccd484c42688ceb3ebe244c5aa14ec7a943db8 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 10:19:31 +0200 Subject: [PATCH 09/31] ApiRegisterEndpoint value added for test --- src/Storage/appsettings.json | 1 + test/UnitTest/appsettings.unittest.json | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Storage/appsettings.json b/src/Storage/appsettings.json index bf372f59..e082448c 100644 --- a/src/Storage/appsettings.json +++ b/src/Storage/appsettings.json @@ -29,6 +29,7 @@ "InstanceReadScope": [ "altinn:serviceowner/instances.read" ] }, "PlatformSettings": { + "ApiRegisterEndpoint": "http://localhost:5101/register/api/v1/", "ApiAuthorizationEndpoint": "http://localhost:5050/authorization/api/v1/", "SubscriptionKey": "replace-with-apim-subscriptionkey" diff --git a/test/UnitTest/appsettings.unittest.json b/test/UnitTest/appsettings.unittest.json index 2c9005ce..07bc7d97 100644 --- a/test/UnitTest/appsettings.unittest.json +++ b/test/UnitTest/appsettings.unittest.json @@ -28,6 +28,7 @@ "UsePostgreSQL": "false" }, "PlatformSettings": { + "ApiRegisterEndpoint": "http://localhost:5101/register/api/v1/", "ApiAuthorizationEndpoint": "http://localhost:5050/authorization/api/v1/" }, "PepSettings": { From 61bb327fab5e4ac778fcd039fd153d36326798cb Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 10:55:45 +0200 Subject: [PATCH 10/31] JwtCookieName value added to appsettings --- src/Storage/appsettings.json | 1 + test/UnitTest/appsettings.unittest.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Storage/appsettings.json b/src/Storage/appsettings.json index e082448c..8d007fa8 100644 --- a/src/Storage/appsettings.json +++ b/src/Storage/appsettings.json @@ -26,6 +26,7 @@ "TextResourceCacheLifeTimeInSeconds": 3600, "AppTitleCacheLifeTimeInSeconds": 3600, "AppMetadataCacheLifeTimeInSeconds": 300, + "JwtCookieName": "AltinnStudioRuntime", "InstanceReadScope": [ "altinn:serviceowner/instances.read" ] }, "PlatformSettings": { diff --git a/test/UnitTest/appsettings.unittest.json b/test/UnitTest/appsettings.unittest.json index 07bc7d97..abbd646c 100644 --- a/test/UnitTest/appsettings.unittest.json +++ b/test/UnitTest/appsettings.unittest.json @@ -25,7 +25,8 @@ "AppTitleCacheLifeTimeInSeconds": 60, "AppMetadataCacheLifeTimeInSeconds": 60, "TextResourceCacheLifeTimeInSeconds": 60, - "UsePostgreSQL": "false" + "UsePostgreSQL": "false", + "JwtCookieName": "AltinnStudioRuntime" }, "PlatformSettings": { "ApiRegisterEndpoint": "http://localhost:5101/register/api/v1/", From 9de8c87a4ba950f3aa1f2bd93a5bb7b7b071dd69 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 13:25:52 +0200 Subject: [PATCH 11/31] Fixed the namespace for platform settings --- src/Storage/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Program.cs b/src/Storage/Program.cs index a81d264e..676a2ff8 100644 --- a/src/Storage/Program.cs +++ b/src/Storage/Program.cs @@ -196,7 +196,7 @@ void ConfigureServices(IServiceCollection services, IConfiguration config) services.Configure(config.GetSection("GeneralSettings")); services.Configure(config.GetSection("kvSetting")); services.Configure(config.GetSection("PepSettings")); - services.Configure(config.GetSection("PlatformSettings")); + services.Configure(config.GetSection("PlatformSettings")); services.Configure(config.GetSection("QueueStorageSettings")); services.Configure(config.GetSection("AccessTokenSettings")); services.Configure(config.GetSection("PostgreSqlSettings")); From 44db59837967db31f9b14a575530dfacf3c5f20f Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 13:34:41 +0200 Subject: [PATCH 12/31] Changed expected text in the test --- test/UnitTest/TestingControllers/InstancesControllerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/UnitTest/TestingControllers/InstancesControllerTests.cs b/test/UnitTest/TestingControllers/InstancesControllerTests.cs index f77e81b1..8e30d69d 100644 --- a/test/UnitTest/TestingControllers/InstancesControllerTests.cs +++ b/test/UnitTest/TestingControllers/InstancesControllerTests.cs @@ -478,7 +478,7 @@ public async Task GetMany_UserRequestsInstancesNoPartyIdDefined_ReturnsBadReques HttpClient client = GetTestClient(); string token = PrincipalUtil.GetToken(3, 1337); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); - string expected = "InstanceOwnerPartyId must be defined."; + string expected = "Either InstanceOwnerPartyId or InstanceOwnerIdentifier must need to be defined."; // Act HttpResponseMessage response = await client.GetAsync(requestUri); From e077c92f6e2af292e47edc67cec35001ca73370e Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 14:24:15 +0200 Subject: [PATCH 13/31] SonarCloud issue fix --- src/Storage/Services/RegisterService.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Storage/Services/RegisterService.cs b/src/Storage/Services/RegisterService.cs index f91814fc..caefeb38 100644 --- a/src/Storage/Services/RegisterService.cs +++ b/src/Storage/Services/RegisterService.cs @@ -43,7 +43,7 @@ public RegisterService( IAccessTokenGenerator accessTokenGenerator, IOptions generalSettings, IOptions platformSettings, - ILogger logger) + ILogger logger) { httpClient.BaseAddress = new Uri(platformSettings.Value.ApiRegisterEndpoint); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); @@ -70,13 +70,15 @@ public async Task GetParty(int partyId) string accessToken = _accessTokenGenerator.GenerateAccessToken("platform", "events"); HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, accessToken); - if (response.StatusCode == HttpStatusCode.OK) + HttpStatusCode responseHttpStatusCode = response.StatusCode; + + if (responseHttpStatusCode == HttpStatusCode.OK) { party = await response.Content.ReadFromJsonAsync(_serializerOptions); } else { - _logger.LogError("// Getting party with partyID {partyId} failed with statuscode {response.StatusCode}", partyId, response.StatusCode); + _logger.LogError("// Getting party with partyID {partyId} failed with statuscode {responseHttpStatusCode}", partyId, responseHttpStatusCode); } return party; From 0f25bc7ac3fa20c99b87cc7e7a4365635bae65bf Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 15:05:59 +0200 Subject: [PATCH 14/31] Test added for GetParty --- .../TestingServices/RegisterServiceTest.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/UnitTest/TestingServices/RegisterServiceTest.cs b/test/UnitTest/TestingServices/RegisterServiceTest.cs index 5a749ea6..965ff788 100644 --- a/test/UnitTest/TestingServices/RegisterServiceTest.cs +++ b/test/UnitTest/TestingServices/RegisterServiceTest.cs @@ -31,6 +31,7 @@ public class RegisterServiceTest private readonly Mock _handlerMock; private readonly Mock _contextAccessor; private readonly Mock _accessTokenGenerator; + private readonly Mock> _loggerRegisterService; public RegisterServiceTest() { @@ -39,6 +40,7 @@ public RegisterServiceTest() _handlerMock = new Mock(MockBehavior.Strict); _contextAccessor = new Mock(); _accessTokenGenerator = new Mock(); + _loggerRegisterService = new Mock>(); } [Fact] @@ -121,6 +123,51 @@ public async Task GetParty_SuccessResponse_PartyTypeDeserializedSuccessfully() Assert.Equal(expectedPartyType, actual.PartyTypeName); } + [Fact] + public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWithHttpStatusCode() + { + // Arrange + string repsonseString = "{\"partyId\": 500000," + + "\"partyTypeName\": \"Organisation\"," + + "\"orgNumber\": \"897069650\"," + + "\"unitType\": \"AS\"," + + "\"name\": \"DDG Fitness\"," + + "\"isDeleted\": false," + + "\"onlyHierarchyElementWithNoAccess\": false," + + "\"organization\": {\"orgNumber\": \"897069650\",\"name\": \"DDG Fitness\",\"unitType\": \"AS\",\"telephoneNumber\": \"12345678\",\"mobileNumber\": \"92010000\",\"faxNumber\": \"92110000\",\"eMailAddress\": \"central@ddgfitness.no\",\"internetAddress\": \"http://ddgfitness.no\",\"mailingAddress\": \"Sofies Gate 1\",\"mailingPostalCode\": \"0170\",\"mailingPostalCity\": \"Oslo\",\"businessAddress\": \"Sofies Gate 1\",\"businessPostalCode\": \"0170\",\"businessPostalCity\": \"By\",\"unitStatus\": null},\"childParties\": null\r\n}"; + + HttpResponseMessage httpResponseMessage = new() + { + StatusCode = HttpStatusCode.BadRequest, + Content = new StringContent(repsonseString, Encoding.UTF8, "application/json") + }; + + HttpRequestMessage actualRequest = null; + void SetRequest(HttpRequestMessage request) => actualRequest = request; + InitializeMocks(httpResponseMessage, SetRequest); + + HttpClient httpClient = new HttpClient(_handlerMock.Object); + + RegisterService target = new RegisterService( + httpClient, + _contextAccessor.Object, + _accessTokenGenerator.Object, + _generalSettings.Object, + _platformSettings.Object, + _loggerRegisterService.Object); + + // Act + Party actual = await target.GetParty(500000); + + // Assert + _loggerRegisterService.Verify( + x => x.LogError( + It.Is(s => s == repsonseString), + "500000", + HttpStatusCode.BadRequest), + Times.Once); + } + [Fact] public async Task PartyLookup_ResponseIsNotSuccessful_PlatformExceptionThrown() { From 6dae234488a48c03a90aa4c32e73e33c89654e4e Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Mon, 8 Apr 2024 15:27:02 +0200 Subject: [PATCH 15/31] Test fixed with proper arguments --- .../TestingServices/RegisterServiceTest.cs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/test/UnitTest/TestingServices/RegisterServiceTest.cs b/test/UnitTest/TestingServices/RegisterServiceTest.cs index 965ff788..82ddc90c 100644 --- a/test/UnitTest/TestingServices/RegisterServiceTest.cs +++ b/test/UnitTest/TestingServices/RegisterServiceTest.cs @@ -127,19 +127,12 @@ public async Task GetParty_SuccessResponse_PartyTypeDeserializedSuccessfully() public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWithHttpStatusCode() { // Arrange - string repsonseString = "{\"partyId\": 500000," + - "\"partyTypeName\": \"Organisation\"," + - "\"orgNumber\": \"897069650\"," + - "\"unitType\": \"AS\"," + - "\"name\": \"DDG Fitness\"," + - "\"isDeleted\": false," + - "\"onlyHierarchyElementWithNoAccess\": false," + - "\"organization\": {\"orgNumber\": \"897069650\",\"name\": \"DDG Fitness\",\"unitType\": \"AS\",\"telephoneNumber\": \"12345678\",\"mobileNumber\": \"92010000\",\"faxNumber\": \"92110000\",\"eMailAddress\": \"central@ddgfitness.no\",\"internetAddress\": \"http://ddgfitness.no\",\"mailingAddress\": \"Sofies Gate 1\",\"mailingPostalCode\": \"0170\",\"mailingPostalCity\": \"Oslo\",\"businessAddress\": \"Sofies Gate 1\",\"businessPostalCode\": \"0170\",\"businessPostalCity\": \"By\",\"unitStatus\": null},\"childParties\": null\r\n}"; + int partyId = 500000; + string loggedMessasge = "// Getting party with partyID 500000 failed with statuscode 400"; HttpResponseMessage httpResponseMessage = new() { - StatusCode = HttpStatusCode.BadRequest, - Content = new StringContent(repsonseString, Encoding.UTF8, "application/json") + StatusCode = HttpStatusCode.BadRequest }; HttpRequestMessage actualRequest = null; @@ -157,13 +150,13 @@ public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWith _loggerRegisterService.Object); // Act - Party actual = await target.GetParty(500000); + Party actual = await target.GetParty(partyId); // Assert _loggerRegisterService.Verify( x => x.LogError( - It.Is(s => s == repsonseString), - "500000", + It.Is(s => s == loggedMessasge), + partyId, HttpStatusCode.BadRequest), Times.Once); } From e74295762b0910d4dafb101fe01a7c2c97697704 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Tue, 9 Apr 2024 09:25:10 +0200 Subject: [PATCH 16/31] Test update --- test/UnitTest/TestingServices/RegisterServiceTest.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/UnitTest/TestingServices/RegisterServiceTest.cs b/test/UnitTest/TestingServices/RegisterServiceTest.cs index 82ddc90c..0ecd95b6 100644 --- a/test/UnitTest/TestingServices/RegisterServiceTest.cs +++ b/test/UnitTest/TestingServices/RegisterServiceTest.cs @@ -154,11 +154,13 @@ public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWith // Assert _loggerRegisterService.Verify( - x => x.LogError( - It.Is(s => s == loggedMessasge), - partyId, - HttpStatusCode.BadRequest), - Times.Once); + x => x.Log( + LogLevel.Error, + It.IsAny(), + It.Is((o, t) => o.ToString().Equals(loggedMessasge)), + It.IsAny(), + It.IsAny>()), + Times.Once); } [Fact] From 209a887a55c033f9f5a2c9db887dd019976b457c Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Tue, 9 Apr 2024 18:39:34 +0200 Subject: [PATCH 17/31] Contains firxed the test issue --- test/UnitTest/TestingServices/RegisterServiceTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/UnitTest/TestingServices/RegisterServiceTest.cs b/test/UnitTest/TestingServices/RegisterServiceTest.cs index 0ecd95b6..6985cd7b 100644 --- a/test/UnitTest/TestingServices/RegisterServiceTest.cs +++ b/test/UnitTest/TestingServices/RegisterServiceTest.cs @@ -128,7 +128,7 @@ public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWith { // Arrange int partyId = 500000; - string loggedMessasge = "// Getting party with partyID 500000 failed with statuscode 400"; + string partOfLoggedMessasge = "// Getting party with partyID 500000 failed with statuscode "; HttpResponseMessage httpResponseMessage = new() { @@ -157,7 +157,7 @@ public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWith x => x.Log( LogLevel.Error, It.IsAny(), - It.Is((o, t) => o.ToString().Equals(loggedMessasge)), + It.Is((o, t) => o.ToString().Contains(partOfLoggedMessasge)), It.IsAny(), It.IsAny>()), Times.Once); From 2ec69052ccb7062d051a79c2ad49b79ee46ead2c Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Tue, 9 Apr 2024 19:10:51 +0200 Subject: [PATCH 18/31] Test for log error passed --- test/UnitTest/TestingServices/RegisterServiceTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/UnitTest/TestingServices/RegisterServiceTest.cs b/test/UnitTest/TestingServices/RegisterServiceTest.cs index 6985cd7b..1ac6f4df 100644 --- a/test/UnitTest/TestingServices/RegisterServiceTest.cs +++ b/test/UnitTest/TestingServices/RegisterServiceTest.cs @@ -128,7 +128,7 @@ public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWith { // Arrange int partyId = 500000; - string partOfLoggedMessasge = "// Getting party with partyID 500000 failed with statuscode "; + string loggedMessasge = "// Getting party with partyID 500000 failed with statuscode BadRequest"; HttpResponseMessage httpResponseMessage = new() { @@ -157,7 +157,7 @@ public async Task GetParty_BadRequestResponse_PartyTypeDeserializationFailedWith x => x.Log( LogLevel.Error, It.IsAny(), - It.Is((o, t) => o.ToString().Contains(partOfLoggedMessasge)), + It.Is((o, t) => o.ToString().Equals(loggedMessasge)), It.IsAny(), It.IsAny>()), Times.Once); From fd47008e8351cc5e40cc82758abae33796ec5884 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Tue, 9 Apr 2024 20:50:37 +0200 Subject: [PATCH 19/31] Party ID update on the query parameters --- src/Storage/Controllers/InstancesController.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Storage/Controllers/InstancesController.cs b/src/Storage/Controllers/InstancesController.cs index 7a73bbef..0aa7c46e 100644 --- a/src/Storage/Controllers/InstancesController.cs +++ b/src/Storage/Controllers/InstancesController.cs @@ -24,6 +24,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; +using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; @@ -191,6 +192,10 @@ public async Task>> GetInstances( } Dictionary queryParams = QueryHelpers.ParseQuery(Request.QueryString.Value); + if (instanceOwnerPartyId.HasValue || !instanceOwnerIdentifier.IsNullOrEmpty()) + { + queryParams["instanceOwner.partyId"] = new StringValues(instanceOwnerPartyId.ToString()); + } // filter out hard deleted instances if it isn't appOwner requesting instances if (!appOwnerRequestingInstances) From 1f3f4355119ef48e1a53d7b2c765e455dfdf1901 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Wed, 10 Apr 2024 08:40:56 +0200 Subject: [PATCH 20/31] Party ID update logic specified to only instance owner ID --- src/Storage/Controllers/InstancesController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Controllers/InstancesController.cs b/src/Storage/Controllers/InstancesController.cs index 0aa7c46e..31ad8007 100644 --- a/src/Storage/Controllers/InstancesController.cs +++ b/src/Storage/Controllers/InstancesController.cs @@ -192,7 +192,7 @@ public async Task>> GetInstances( } Dictionary queryParams = QueryHelpers.ParseQuery(Request.QueryString.Value); - if (instanceOwnerPartyId.HasValue || !instanceOwnerIdentifier.IsNullOrEmpty()) + if (!instanceOwnerIdentifier.IsNullOrEmpty()) { queryParams["instanceOwner.partyId"] = new StringValues(instanceOwnerPartyId.ToString()); } From 8dad9bff23f08361df9991767ab1ec08bc7874ea Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Wed, 10 Apr 2024 11:49:30 +0200 Subject: [PATCH 21/31] Tests added for HttpClientExtension --- .../Extensions/HttpClientExtensionTest.cs | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test/UnitTest/Extensions/HttpClientExtensionTest.cs diff --git a/test/UnitTest/Extensions/HttpClientExtensionTest.cs b/test/UnitTest/Extensions/HttpClientExtensionTest.cs new file mode 100644 index 00000000..e15001e4 --- /dev/null +++ b/test/UnitTest/Extensions/HttpClientExtensionTest.cs @@ -0,0 +1,93 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Platform.Storage.Configuration; + +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; + +using Moq; +using Moq.Protected; + +using Xunit; + +namespace Altinn.Platform.Storage.Tests.Extensions +{ + public class HttpClientExtensionTest + { + [Fact] + public async Task PostAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMessage() + { + // Arrange + HttpResponseMessage httpResponseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent("dummyData", Encoding.UTF8, "application/json") + }; + + Mock handlerMock = new Mock(MockBehavior.Strict); + + HttpRequestMessage actualRequest = null; + void SetRequest(HttpRequestMessage request) => actualRequest = request; + handlerMock + .Protected() + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny()) + .Callback((request, _) => SetRequest(request)) + .ReturnsAsync(httpResponseMessage); + + HttpClient httpClient = new HttpClient(handlerMock.Object); + string requestUri = "http://example.com/api/resource"; + HttpContent content = new StringContent("dummyContent"); + + // Act + var response = await httpClient.PostAsync(requestUri, content); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("StringContent", response.Content.GetType().Name); + } + + [Fact] + public async Task GetAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMessage() + { + // Arrange + HttpResponseMessage httpResponseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent("dummyData", Encoding.UTF8, "application/json") + }; + + Mock handlerMock = new Mock(MockBehavior.Strict); + + HttpRequestMessage actualRequest = null; + void SetRequest(HttpRequestMessage request) => actualRequest = request; + handlerMock + .Protected() + .Setup>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny()) + .Callback((request, _) => SetRequest(request)) + .ReturnsAsync(httpResponseMessage); + + HttpClient httpClient = new HttpClient(handlerMock.Object); + string requestUri = "http://example.com/api/resource"; + HttpContent content = new StringContent("dummyContent"); + + // Act + var response = await httpClient.GetAsync(requestUri); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("StringContent", response.Content.GetType().Name); + } + } +} From fc5d176952451a96222f90ea28cc77f461343e96 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Wed, 10 Apr 2024 12:19:09 +0200 Subject: [PATCH 22/31] Tests for PlatformAccessToken in HttpClientExtension added --- .../Extensions/HttpClientExtensionTest.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/UnitTest/Extensions/HttpClientExtensionTest.cs b/test/UnitTest/Extensions/HttpClientExtensionTest.cs index e15001e4..f8289a7a 100644 --- a/test/UnitTest/Extensions/HttpClientExtensionTest.cs +++ b/test/UnitTest/Extensions/HttpClientExtensionTest.cs @@ -4,12 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; - -using Altinn.Common.AccessTokenClient.Services; -using Altinn.Platform.Storage.Configuration; - -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; +using Altinn.Platform.Storage.Extensions; using Moq; using Moq.Protected; @@ -44,11 +39,12 @@ public async Task PostAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMes .ReturnsAsync(httpResponseMessage); HttpClient httpClient = new HttpClient(handlerMock.Object); - string requestUri = "http://example.com/api/resource"; + httpClient.BaseAddress = new Uri("http://localhost:5101/register/api/v1/"); + string requestUri = "/api/resource"; HttpContent content = new StringContent("dummyContent"); // Act - var response = await httpClient.PostAsync(requestUri, content); + var response = await httpClient.PostAsync("dummyAuthorizationToken", requestUri, content, "dummyPlatformAccessToken"); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -79,11 +75,12 @@ public async Task GetAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMess .ReturnsAsync(httpResponseMessage); HttpClient httpClient = new HttpClient(handlerMock.Object); - string requestUri = "http://example.com/api/resource"; + httpClient.BaseAddress = new Uri("http://localhost:5101/register/api/v1/"); + string requestUri = "/api/resource"; HttpContent content = new StringContent("dummyContent"); // Act - var response = await httpClient.GetAsync(requestUri); + var response = await httpClient.GetAsync("dummyAuthorizationToken", requestUri, "dummyPlatformAccessToken"); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); From 938aa16ea006a335518944a6add0a15e5838ceeb Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Wed, 10 Apr 2024 13:00:34 +0200 Subject: [PATCH 23/31] Test added for no party ID but wrong instance owner ID --- .../InstancesControllerTests.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/UnitTest/TestingControllers/InstancesControllerTests.cs b/test/UnitTest/TestingControllers/InstancesControllerTests.cs index 8e30d69d..823139ec 100644 --- a/test/UnitTest/TestingControllers/InstancesControllerTests.cs +++ b/test/UnitTest/TestingControllers/InstancesControllerTests.cs @@ -489,6 +489,31 @@ public async Task GetMany_UserRequestsInstancesNoPartyIdDefined_ReturnsBadReques Assert.Contains(expected, responseMessage); } + /// + /// Test case: Get Multiple instances without specifying instance owner partyId. + /// Expected: Returns status bad request. + /// + [Fact] + public async Task GetMany_UserRequestsInstancesNoPartyIdButWithWrongInstanceOwnerIdDefined_ReturnsBadRequest() + { + // Arrange + string requestUri = $"{BasePath}"; + + HttpClient client = GetTestClient(); + string token = PrincipalUtil.GetToken(3, 1337); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + client.DefaultRequestHeaders.Add("X-Ai-InstanceOwnerIdentifier", "something:3312321321"); + string expected = "Invalid InstanceOwnerIdentifier."; + + // Act + HttpResponseMessage response = await client.GetAsync(requestUri); + string responseMessage = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + Assert.Contains(expected, responseMessage); + } + /// /// Test case: Get Multiple instances and specifying status.isHardDeleted=true. /// Expected: No instances included in response. From 3e6fd3ab8c4b86a59d76bf02fa4c87b2893ce3ec Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 09:47:15 +0200 Subject: [PATCH 24/31] Suggestion implemented for error message --- src/Storage/Controllers/InstancesController.cs | 2 +- test/UnitTest/TestingControllers/InstancesControllerTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Storage/Controllers/InstancesController.cs b/src/Storage/Controllers/InstancesController.cs index 31ad8007..7e5674be 100644 --- a/src/Storage/Controllers/InstancesController.cs +++ b/src/Storage/Controllers/InstancesController.cs @@ -164,7 +164,7 @@ public async Task>> GetInstances( { if (string.IsNullOrEmpty(instanceOwnerIdentifier)) { - return BadRequest("Either InstanceOwnerPartyId or InstanceOwnerIdentifier must need to be defined."); + return BadRequest("Either InstanceOwnerPartyId or InstanceOwnerIdentifier need to be defined."); } (string instanceOwnerIdType, string instanceOwnerIdValue) = InstanceHelper.GetIdentifierFromInstanceOwnerIdentifier(instanceOwnerIdentifier); diff --git a/test/UnitTest/TestingControllers/InstancesControllerTests.cs b/test/UnitTest/TestingControllers/InstancesControllerTests.cs index 823139ec..4b16878d 100644 --- a/test/UnitTest/TestingControllers/InstancesControllerTests.cs +++ b/test/UnitTest/TestingControllers/InstancesControllerTests.cs @@ -478,7 +478,7 @@ public async Task GetMany_UserRequestsInstancesNoPartyIdDefined_ReturnsBadReques HttpClient client = GetTestClient(); string token = PrincipalUtil.GetToken(3, 1337); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); - string expected = "Either InstanceOwnerPartyId or InstanceOwnerIdentifier must need to be defined."; + string expected = "Either InstanceOwnerPartyId or InstanceOwnerIdentifier need to be defined."; // Act HttpResponseMessage response = await client.GetAsync(requestUri); From ae951b5a6ef07eb18fea8c3f4ff9c9e2c759da75 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 09:53:03 +0200 Subject: [PATCH 25/31] Logic enhanced for updating instance owner party ID --- src/Storage/Controllers/InstancesController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Controllers/InstancesController.cs b/src/Storage/Controllers/InstancesController.cs index 7e5674be..cb237900 100644 --- a/src/Storage/Controllers/InstancesController.cs +++ b/src/Storage/Controllers/InstancesController.cs @@ -192,7 +192,7 @@ public async Task>> GetInstances( } Dictionary queryParams = QueryHelpers.ParseQuery(Request.QueryString.Value); - if (!instanceOwnerIdentifier.IsNullOrEmpty()) + if (instanceOwnerPartyId > 0) { queryParams["instanceOwner.partyId"] = new StringValues(instanceOwnerPartyId.ToString()); } From fb60579394feb6aab7755494c5ad455cb40fdb40 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 13:23:31 +0200 Subject: [PATCH 26/31] Delegating handler stub added for testing http client --- .../Extensions/HttpClientExtensionTest.cs | 90 ------------------- .../Extensions/HttpClientExtensionTests.cs | 52 +++++++++++ test/UnitTest/Stubs/DelegatingHandlerStub.cs | 28 ++++++ 3 files changed, 80 insertions(+), 90 deletions(-) delete mode 100644 test/UnitTest/Extensions/HttpClientExtensionTest.cs create mode 100644 test/UnitTest/Extensions/HttpClientExtensionTests.cs create mode 100644 test/UnitTest/Stubs/DelegatingHandlerStub.cs diff --git a/test/UnitTest/Extensions/HttpClientExtensionTest.cs b/test/UnitTest/Extensions/HttpClientExtensionTest.cs deleted file mode 100644 index f8289a7a..00000000 --- a/test/UnitTest/Extensions/HttpClientExtensionTest.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Altinn.Platform.Storage.Extensions; - -using Moq; -using Moq.Protected; - -using Xunit; - -namespace Altinn.Platform.Storage.Tests.Extensions -{ - public class HttpClientExtensionTest - { - [Fact] - public async Task PostAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMessage() - { - // Arrange - HttpResponseMessage httpResponseMessage = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent("dummyData", Encoding.UTF8, "application/json") - }; - - Mock handlerMock = new Mock(MockBehavior.Strict); - - HttpRequestMessage actualRequest = null; - void SetRequest(HttpRequestMessage request) => actualRequest = request; - handlerMock - .Protected() - .Setup>( - "SendAsync", - ItExpr.IsAny(), - ItExpr.IsAny()) - .Callback((request, _) => SetRequest(request)) - .ReturnsAsync(httpResponseMessage); - - HttpClient httpClient = new HttpClient(handlerMock.Object); - httpClient.BaseAddress = new Uri("http://localhost:5101/register/api/v1/"); - string requestUri = "/api/resource"; - HttpContent content = new StringContent("dummyContent"); - - // Act - var response = await httpClient.PostAsync("dummyAuthorizationToken", requestUri, content, "dummyPlatformAccessToken"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("StringContent", response.Content.GetType().Name); - } - - [Fact] - public async Task GetAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMessage() - { - // Arrange - HttpResponseMessage httpResponseMessage = new HttpResponseMessage - { - StatusCode = HttpStatusCode.OK, - Content = new StringContent("dummyData", Encoding.UTF8, "application/json") - }; - - Mock handlerMock = new Mock(MockBehavior.Strict); - - HttpRequestMessage actualRequest = null; - void SetRequest(HttpRequestMessage request) => actualRequest = request; - handlerMock - .Protected() - .Setup>( - "SendAsync", - ItExpr.IsAny(), - ItExpr.IsAny()) - .Callback((request, _) => SetRequest(request)) - .ReturnsAsync(httpResponseMessage); - - HttpClient httpClient = new HttpClient(handlerMock.Object); - httpClient.BaseAddress = new Uri("http://localhost:5101/register/api/v1/"); - string requestUri = "/api/resource"; - HttpContent content = new StringContent("dummyContent"); - - // Act - var response = await httpClient.GetAsync("dummyAuthorizationToken", requestUri, "dummyPlatformAccessToken"); - - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Equal("StringContent", response.Content.GetType().Name); - } - } -} diff --git a/test/UnitTest/Extensions/HttpClientExtensionTests.cs b/test/UnitTest/Extensions/HttpClientExtensionTests.cs new file mode 100644 index 00000000..885e9dab --- /dev/null +++ b/test/UnitTest/Extensions/HttpClientExtensionTests.cs @@ -0,0 +1,52 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Altinn.Platform.Storage.Extensions; +using Altinn.Platform.Storage.Tests.Stubs; + +using Xunit; + +namespace Altinn.Platform.Storage.Tests.Extensions +{ + public class HttpClientExtensionTests + { + private readonly HttpClient _httpClient; + private HttpRequestMessage _httpRequest; + + public HttpClientExtensionTests() + { + var httpMessageHandler = new DelegatingHandlerStub(async (request, token) => + { + _httpRequest = request; + return new HttpResponseMessage(HttpStatusCode.OK); + }); + + _httpClient = new HttpClient(httpMessageHandler); + _httpClient.BaseAddress = new Uri("http://localhost:5101/register/api/v1/"); + } + + [Fact] + public async Task PostAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMessage() + { + // Arrange + HttpContent content = new StringContent("dummyContent"); + + // Act + _ = await _httpClient.PostAsync("dummyAuthorizationToken", "/api/resource", content, "dummyPlatformAccessToken"); + + // Assert + Assert.True(_httpRequest.Headers.Contains("PlatformAccessToken")); + } + + [Fact] + public async Task GetAsync_ShouldAddAuthorizationHeaderAndReturnHttpResponseMessage() + { + // Act + _ = await _httpClient.GetAsync("dummyAuthorizationToken", "/api/resource", "dummyPlatformAccessToken"); + + // Assert + Assert.True(_httpRequest.Headers.Contains("PlatformAccessToken")); + } + } +} diff --git a/test/UnitTest/Stubs/DelegatingHandlerStub.cs b/test/UnitTest/Stubs/DelegatingHandlerStub.cs new file mode 100644 index 00000000..70ec3559 --- /dev/null +++ b/test/UnitTest/Stubs/DelegatingHandlerStub.cs @@ -0,0 +1,28 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Altinn.Platform.Storage.Tests.Stubs +{ + public class DelegatingHandlerStub : DelegatingHandler + { + private readonly Func> _handlerFunc; + + public DelegatingHandlerStub() + { + _handlerFunc = (request, cancellationToken) => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)); + } + + public DelegatingHandlerStub(Func> handlerFunc) + { + _handlerFunc = handlerFunc; + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + return _handlerFunc(request, cancellationToken); + } + } +} From 86e684464465d55fe6ded3b70f94c06c8ae63720 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 13:36:29 +0200 Subject: [PATCH 27/31] Await keyword added to async function in the test --- test/UnitTest/Extensions/HttpClientExtensionTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/UnitTest/Extensions/HttpClientExtensionTests.cs b/test/UnitTest/Extensions/HttpClientExtensionTests.cs index 885e9dab..157c033d 100644 --- a/test/UnitTest/Extensions/HttpClientExtensionTests.cs +++ b/test/UnitTest/Extensions/HttpClientExtensionTests.cs @@ -19,6 +19,7 @@ public HttpClientExtensionTests() var httpMessageHandler = new DelegatingHandlerStub(async (request, token) => { _httpRequest = request; + await Task.Yield(); return new HttpResponseMessage(HttpStatusCode.OK); }); From 59ca0da2c4f43b189ac816cbc5a305479d39669f Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 13:54:42 +0200 Subject: [PATCH 28/31] PascalCase fixed for the logged error message --- src/Storage/Services/RegisterService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Services/RegisterService.cs b/src/Storage/Services/RegisterService.cs index caefeb38..a735c786 100644 --- a/src/Storage/Services/RegisterService.cs +++ b/src/Storage/Services/RegisterService.cs @@ -78,7 +78,7 @@ public async Task GetParty(int partyId) } else { - _logger.LogError("// Getting party with partyID {partyId} failed with statuscode {responseHttpStatusCode}", partyId, responseHttpStatusCode); + _logger.LogError("// Getting party with partyID {PartyId} failed with statuscode {ResponseHttpStatusCode}", partyId, responseHttpStatusCode); } return party; From 15cb1f4c0908f52e3b61bb7646bd314487c58fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=CA=9C=E1=B4=80=C9=B4?= Date: Thu, 11 Apr 2024 13:58:08 +0200 Subject: [PATCH 29/31] Update test/UnitTest/Extensions/HttpClientExtensionTests.cs Co-authored-by: Terje Holene --- test/UnitTest/Extensions/HttpClientExtensionTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/UnitTest/Extensions/HttpClientExtensionTests.cs b/test/UnitTest/Extensions/HttpClientExtensionTests.cs index 157c033d..40d8d675 100644 --- a/test/UnitTest/Extensions/HttpClientExtensionTests.cs +++ b/test/UnitTest/Extensions/HttpClientExtensionTests.cs @@ -19,8 +19,7 @@ public HttpClientExtensionTests() var httpMessageHandler = new DelegatingHandlerStub(async (request, token) => { _httpRequest = request; - await Task.Yield(); - return new HttpResponseMessage(HttpStatusCode.OK); + return await Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)); }); _httpClient = new HttpClient(httpMessageHandler); From 18660c0510a113811e8f72e8923ea61fa2a784e3 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 14:03:48 +0200 Subject: [PATCH 30/31] PascalCase fixed for another issue in the RegisterService --- src/Storage/Services/RegisterService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Services/RegisterService.cs b/src/Storage/Services/RegisterService.cs index a735c786..6b04302b 100644 --- a/src/Storage/Services/RegisterService.cs +++ b/src/Storage/Services/RegisterService.cs @@ -106,7 +106,7 @@ public async Task PartyLookup(string orgNo, string person) else { string reason = await response.Content.ReadAsStringAsync(); - _logger.LogError("// RegisterService // PartyLookup // Failed to lookup party in platform register. Response {response}. \n Reason {reason}.", response, reason); + _logger.LogError("// RegisterService // PartyLookup // Failed to lookup party in platform register. Response {Response}. \n Reason {Reason}.", response, reason); throw await PlatformHttpException.CreateAsync(response); } From d902e2709146c8a0ae5fb456d1c1c43db77c8be8 Mon Sep 17 00:00:00 2001 From: "Khan Mohammad R." Date: Thu, 11 Apr 2024 14:09:12 +0200 Subject: [PATCH 31/31] Reponse status code added insted of full reponse in party lookup --- src/Storage/Services/RegisterService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storage/Services/RegisterService.cs b/src/Storage/Services/RegisterService.cs index 6b04302b..e9d574a6 100644 --- a/src/Storage/Services/RegisterService.cs +++ b/src/Storage/Services/RegisterService.cs @@ -106,7 +106,7 @@ public async Task PartyLookup(string orgNo, string person) else { string reason = await response.Content.ReadAsStringAsync(); - _logger.LogError("// RegisterService // PartyLookup // Failed to lookup party in platform register. Response {Response}. \n Reason {Reason}.", response, reason); + _logger.LogError("// RegisterService // PartyLookup // Failed to lookup party in platform register. Response status code is {StatusCode}. \n Reason {Reason}.", response.StatusCode, reason); throw await PlatformHttpException.CreateAsync(response); }