Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new internal api for fetching list of user profiles. #130

Merged
merged 7 commits into from
Feb 2, 2024
24 changes: 24 additions & 0 deletions src/Altinn.Profile/Controllers/UserProfileInternalController.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Altinn.Platform.Profile.Models;
using Altinn.Profile.Models;
Expand Down Expand Up @@ -71,5 +73,27 @@ public async Task<ActionResult<UserProfile>> Get([FromBody] UserProfileLookup us

return Ok(result);
}

/// <summary>
/// Gets a list of user profiles for a list of of users identified by userUuid.
/// </summary>
/// <param name="userUuidList">List of uuid identifying the users profiles to return</param>
/// <returns>List of user profiles</returns>
[HttpPost]
[Route("listbyuuid")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Consumes("application/json")]
[Produces("application/json")]
public async Task<ActionResult<List<UserProfile>>> GetList([FromBody] List<Guid> userUuidList)
{
if (userUuidList == null || userUuidList.Count == 0)
{
return BadRequest();
}

List<UserProfile> result = await _userProfilesWrapper.GetUserListByUuid(userUuidList);
return Ok(result);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using Altinn.Platform.Profile.Models;
Expand Down Expand Up @@ -99,6 +100,39 @@ public async Task<UserProfile> GetUserByUuid(Guid userUuid)
return user;
}

/// <inheritdoc />
public async Task<List<UserProfile>> GetUserListByUuid(List<Guid> userUuidList)
{
List<Guid> userUuidListNotInCache = new List<Guid>();
List<UserProfile> result = new List<UserProfile>();

foreach (Guid userUuid in userUuidList)
{
string uniqueCacheKey = $"User:UserUuid:{userUuid}";
if (_memoryCache.TryGetValue(uniqueCacheKey, out UserProfile user))
{
result.Add(user);
}
else
{
userUuidListNotInCache.Add(userUuid);
}
}

if (userUuidListNotInCache.Count > 0)
{
List<UserProfile> usersToCache = await _decoratedService.GetUserListByUuid(userUuidListNotInCache);
foreach (UserProfile user in usersToCache)
{
string uniqueCacheKey = $"User:UserUuid:{user.UserUuid}";
_memoryCache.Set(uniqueCacheKey, user, _cacheOptions);
result.Add(user);
}
}

return result;
}

/// <inheritdoc/>
public async Task<UserProfile> GetUserByUsername(string username)
{
Expand Down
21 changes: 21 additions & 0 deletions src/Altinn.Profile/Services/Implementation/UserProfilesWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
Expand Down Expand Up @@ -107,6 +108,26 @@ public async Task<UserProfile> GetUserByUuid(Guid userUuid)
return user;
}

/// <inheritdoc />
public async Task<List<UserProfile>> GetUserListByUuid(List<Guid> userUuidList)
{
Uri endpointUrl = new Uri($"{_generalSettings.BridgeApiEndpoint}users/byuuid");
StringContent requestBody = new StringContent(JsonSerializer.Serialize(userUuidList), Encoding.UTF8, "application/json");

HttpResponseMessage response = await _client.PostAsync(endpointUrl, requestBody);

if (!response.IsSuccessStatusCode)
{
_logger.LogError("Getting users failed with {statusCode}", response.StatusCode);
return new List<UserProfile>();
}

string content = await response.Content.ReadAsStringAsync();
List<UserProfile> users = JsonSerializer.Deserialize<List<UserProfile>>(content, _serializerOptions);

return users;
}

/// <inheritdoc />
public async Task<UserProfile> GetUserByUsername(string username)
{
Expand Down
10 changes: 9 additions & 1 deletion src/Altinn.Profile/Services/Interfaces/IUserProfiles.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using Altinn.Platform.Profile.Models;
Expand Down Expand Up @@ -28,9 +29,16 @@ public interface IUserProfiles
/// Method that fetches a user based on a user uuid
/// </summary>
/// <param name="userUuid">The user uuid</param>
/// <returns>User profile with given user id.</returns>
/// <returns>User profile with given user uuid.</returns>
Task<UserProfile> GetUserByUuid(Guid userUuid);

/// <summary>
/// Method that fetches a list of users based on a list of user uuid
/// </summary>
/// <param name="userUuidList">The list of user uuids</param>
/// <returns>List of User profiles with given user uuids</returns>
Task<List<UserProfile>> GetUserListByUuid(List<Guid> userUuidList);

/// <summary>
/// Method that fetches a user based on username.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
Expand All @@ -12,7 +13,6 @@
using Altinn.Profile.Tests.IntegrationTests.Utils;
using Altinn.Profile.Tests.Mocks;
using Altinn.Profile.Tests.Testdata;

using Microsoft.AspNetCore.Mvc.Testing;

using Xunit;
Expand Down Expand Up @@ -117,6 +117,112 @@ public async Task GetUserByUuid_SblBridgeFindsProfile_ResponseOk_ReturnsUserProf
Assert.Equal("nb", actualUser.ProfileSettingPreference.Language);
}

[Fact]
public async Task GetUserListByUuid_SblBridgeFindsProfile_ResponseOk_ReturnsUserProfileList()
{
// Arrange
List<Guid> userUuids = new List<Guid> { new("cc86d2c7-1695-44b0-8e82-e633243fdf31"), new("4c3b4909-eb17-45d5-bde1-256e065e196a") };

HttpRequestMessage sblRequest = null;
DelegatingHandlerStub messageHandler = new(async (request, token) =>
{
sblRequest = request;

List<UserProfile> userProfiles = new()
{
await TestDataLoader.Load<UserProfile>(userUuids[0].ToString()),
await TestDataLoader.Load<UserProfile>(userUuids[1].ToString())
};

return new HttpResponseMessage() { Content = JsonContent.Create(userProfiles) };
});
_webApplicationFactorySetup.SblBridgeHttpMessageHandler = messageHandler;

HttpRequestMessage httpRequestMessage = CreatePostRequest($"/profile/api/v1/internal/user/listbyuuid", userUuids);

HttpClient client = _webApplicationFactorySetup.GetTestServerClient();

// Act
HttpResponseMessage response = await client.SendAsync(httpRequestMessage);

// Assert
Assert.NotNull(sblRequest);
Assert.Equal(HttpMethod.Post, sblRequest.Method);
Assert.EndsWith($"sblbridge/profile/api/users/byuuid", sblRequest.RequestUri.ToString());

string responseContent = await response.Content.ReadAsStringAsync();

List<UserProfile> actualUsers = JsonSerializer.Deserialize<List<UserProfile>>(
responseContent, serializerOptionsCamelCase);

// These asserts check that deserializing with camel casing was successful.
Assert.Equal(userUuids[0], actualUsers[0].UserUuid);
Assert.Equal("LEO WILHELMSEN", actualUsers[0].Party.Name);
Assert.Equal("LEO", actualUsers[0].Party.Person.FirstName);
Assert.Equal("nb", actualUsers[0].ProfileSettingPreference.Language);

Assert.Equal(userUuids[1], actualUsers[1].UserUuid);
Assert.Equal("ELENA FJAR", actualUsers[1].Party.Name);
Assert.Equal("ELENA", actualUsers[1].Party.Person.FirstName);
Assert.Equal("nn", actualUsers[1].ProfileSettingPreference.Language);
}

[Fact]
public async Task GetUserListByUuid_SblBridgeFindsNoProfile_ResponseOk_ReturnsEmptyProfileList()
{
// Arrange
List<Guid> userUuids = new List<Guid> { new("cc86d2c7-1695-44b0-8e82-e633243fdf31"), new("4c3b4909-eb17-45d5-bde1-256e065e196a") };

HttpRequestMessage sblRequest = null;
DelegatingHandlerStub messageHandler = new((request, token) =>
{
sblRequest = request;

List<UserProfile> userProfiles = new List<UserProfile>();

return Task.FromResult(new HttpResponseMessage() { Content = JsonContent.Create(userProfiles) });
});
_webApplicationFactorySetup.SblBridgeHttpMessageHandler = messageHandler;

HttpRequestMessage httpRequestMessage = CreatePostRequest($"/profile/api/v1/internal/user/listbyuuid", userUuids);

HttpClient client = _webApplicationFactorySetup.GetTestServerClient();

// Act
HttpResponseMessage response = await client.SendAsync(httpRequestMessage);

// Assert
Assert.NotNull(sblRequest);
Assert.Equal(HttpMethod.Post, sblRequest.Method);
Assert.EndsWith($"sblbridge/profile/api/users/byuuid", sblRequest.RequestUri.ToString());

string responseContent = await response.Content.ReadAsStringAsync();

List<UserProfile> actualUsers = JsonSerializer.Deserialize<List<UserProfile>>(
responseContent, serializerOptionsCamelCase);

// These asserts check that deserializing with camel casing was successful.
Assert.NotNull(actualUsers);
Assert.Empty(actualUsers);
}

[Fact]
public async Task GetUserListByUuid_EmptyInput_ResponseBadRequest_ReturnsBadRequest()
{
// Arrange
List<Guid> userUuids = new List<Guid>();

HttpRequestMessage httpRequestMessage = CreatePostRequest($"/profile/api/v1/internal/user/listbyuuid", userUuids);

HttpClient client = _webApplicationFactorySetup.GetTestServerClient();

// Act
HttpResponseMessage response = await client.SendAsync(httpRequestMessage);

// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}

[Fact]
public async Task GetUserById_SblBridgeReturnsNotFound_ResponseNotFound()
{
Expand Down Expand Up @@ -488,5 +594,12 @@ private static HttpRequestMessage CreatePostRequest(string requestUri, UserProfi
httpRequestMessage.Content = new StringContent(JsonSerializer.Serialize(lookupRequest), Encoding.UTF8, "application/json");
return httpRequestMessage;
}

private static HttpRequestMessage CreatePostRequest(string requestUri, List<Guid> listRequest)
{
HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, requestUri);
httpRequestMessage.Content = new StringContent(JsonSerializer.Serialize(listRequest), Encoding.UTF8, "application/json");
return httpRequestMessage;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"UserId": 20000006,
"UserUUID": "4c3b4909-eb17-45d5-bde1-256e065e196a",
"UserType": 1,
"UserName": "",
"ExternalIdentity": "",
"PhoneNumber": null,
"Email": null,
"PartyId": 50002114,
"Party": {
"PartyTypeName": 1,
"SSN": "01025161013",
"OrgNumber": "",
"Person": {
"SSN": "01025161013",
"Name": "ELENA FJAR",
"FirstName": "ELENA",
"MiddleName": "",
"LastName": "FJAR",
"TelephoneNumber": "",
"MobileNumber": "",
"MailingAddress": " Søreidåsen 3 5252 SØREIDGREND",
"MailingPostalCode": "5252",
"MailingPostalCity": "SØREIDGREND",
"AddressMunicipalNumber": "",
"AddressMunicipalName": "",
"AddressStreetName": "",
"AddressHouseNumber": "",
"AddressHouseLetter": "",
"AddressPostalCode": "5252",
"AddressCity": "SØREIDGREND",
"DateOfDeath": null
},
"Organization": null,
"PartyId": 50002114,
"PartyUUID": "4c3b4909-eb17-45d5-bde1-256e065e196a",
"UnitType": null,
"Name": "ELENA FJAR",
"IsDeleted": false,
"OnlyHierarchyElementWithNoAccess": false,
"ChildParties": null
},
"ProfileSettingPreference": {
"Language": "nn",
"PreSelectedPartyId": 0,
"DoNotPromptForParty": false
}
}
Loading
Loading