diff --git a/src/Altinn.Profile.Core/Integrations/IUnitProfileClient.cs b/src/Altinn.Profile.Core/Integrations/IUnitProfileClient.cs
new file mode 100644
index 0000000..500783f
--- /dev/null
+++ b/src/Altinn.Profile.Core/Integrations/IUnitProfileClient.cs
@@ -0,0 +1,17 @@
+using Altinn.Profile.Core.Unit.ContactPoints;
+
+namespace Altinn.Profile.Core.Integrations
+{
+ ///
+ /// Interface describing a client for the user profile service
+ ///
+ public interface IUnitProfileClient
+ {
+ ///
+ /// Provides a list of user registered contact points based on the lookup criteria
+ ///
+ /// Lookup object containing a list of organizations and a resource
+ /// A list of unit contact points
+ Task> GetUserRegisteredContactPoints(UnitContactPointLookup lookup);
+ }
+}
diff --git a/src/Altinn.Profile.Core/ServiceCollectionExtensions.cs b/src/Altinn.Profile.Core/ServiceCollectionExtensions.cs
index 0b3d3af..da1f54d 100644
--- a/src/Altinn.Profile.Core/ServiceCollectionExtensions.cs
+++ b/src/Altinn.Profile.Core/ServiceCollectionExtensions.cs
@@ -1,4 +1,5 @@
using Altinn.Profile.Core;
+using Altinn.Profile.Core.Unit.ContactPoints;
using Altinn.Profile.Core.User;
using Altinn.Profile.Core.User.ContactPoints;
@@ -24,6 +25,7 @@ public static void AddCoreServices(this IServiceCollection services, IConfigurat
.AddMemoryCache()
.AddSingleton()
.AddSingleton()
- .Decorate();
+ .Decorate()
+ .AddSingleton();
}
}
diff --git a/src/Altinn.Profile.Core/Unit.ContactPoints/IUnitContactPoints.cs b/src/Altinn.Profile.Core/Unit.ContactPoints/IUnitContactPoints.cs
new file mode 100644
index 0000000..3aec836
--- /dev/null
+++ b/src/Altinn.Profile.Core/Unit.ContactPoints/IUnitContactPoints.cs
@@ -0,0 +1,16 @@
+using Altinn.Profile.Core.Unit.ContactPoints;
+
+namespace Altinn.Profile.Core.User.ContactPoints;
+
+///
+/// Class describing the methods required for user contact point service
+///
+public interface IUnitContactPoints
+{
+ ///
+ /// Method for retriveing user registered contact points for a unit
+ ///
+ /// A lookup object containing a list of organisation numbers and the resource to lookup contact points for
+ /// The users' contact points and reservation status or a boolean if failure.
+ Task> GetUserRegisteredContactPoints(UnitContactPointLookup lookup);
+}
diff --git a/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPointLookup.cs b/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPointLookup.cs
new file mode 100644
index 0000000..6993da6
--- /dev/null
+++ b/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPointLookup.cs
@@ -0,0 +1,17 @@
+namespace Altinn.Profile.Core.Unit.ContactPoints
+{ ///
+ /// A class describing the query model for contact points for units
+ ///
+ public class UnitContactPointLookup
+ {
+ ///
+ /// Gets or sets the list of organisation numbers to lookup contact points for
+ ///
+ public List OrganizationNumbers { get; set; } = [];
+
+ ///
+ /// Gets or sets the resource id to filter the contact points by
+ ///
+ public string ResourceId { get; set; } = string.Empty;
+ }
+}
diff --git a/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPointService.cs b/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPointService.cs
new file mode 100644
index 0000000..a16ca10
--- /dev/null
+++ b/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPointService.cs
@@ -0,0 +1,28 @@
+using Altinn.Profile.Core.Integrations;
+using Altinn.Profile.Core.User.ContactPoints;
+
+namespace Altinn.Profile.Core.Unit.ContactPoints
+{
+ ///
+ /// Implementation of the interface using a REST client to retrieve profile data "/>
+ ///
+ public class UnitContactPointService : IUnitContactPoints
+ {
+ private readonly IUnitProfileClient _unitClient;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public UnitContactPointService(IUnitProfileClient unitClient)
+ {
+ _unitClient = unitClient;
+ }
+
+ ///
+ public async Task> GetUserRegisteredContactPoints(UnitContactPointLookup lookup)
+ {
+ Result result = await _unitClient.GetUserRegisteredContactPoints(lookup);
+ return result;
+ }
+ }
+}
diff --git a/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPoints.cs b/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPoints.cs
new file mode 100644
index 0000000..320aaf2
--- /dev/null
+++ b/src/Altinn.Profile.Core/Unit.ContactPoints/UnitContactPoints.cs
@@ -0,0 +1,36 @@
+using Altinn.Profile.Core.User.ContactPoints;
+
+namespace Altinn.Profile.Core.Unit.ContactPoints
+{
+ ///
+ /// Class describing the user registered contact points for a unit
+ ///
+ public class UnitContactPoints
+ {
+ ///
+ /// Gets or sets the organization number of the organization.
+ ///
+ public string OrganizationNumber { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the party id of the organization.
+ ///
+ public int PartyId { get; set; }
+
+ ///
+ /// Gets or sets a list of multiple contanct points associated with the organisation.
+ ///
+ public List UserContactPoints { get; set; } = [];
+ }
+
+ ///
+ /// A list representation of
+ ///
+ public class UnitContactPointsList
+ {
+ ///
+ /// A list containing contact points for users
+ ///
+ public List ContactPointsList { get; set; } = [];
+ }
+}
diff --git a/src/Altinn.Profile.Core/User.ContactPoints/UserContactPoints.cs b/src/Altinn.Profile.Core/User.ContactPoints/UserContactPoints.cs
index e7e335c..f705bfe 100644
--- a/src/Altinn.Profile.Core/User.ContactPoints/UserContactPoints.cs
+++ b/src/Altinn.Profile.Core/User.ContactPoints/UserContactPoints.cs
@@ -1,7 +1,7 @@
namespace Altinn.Profile.Core.User.ContactPoints;
///
-/// Class describing the availability of contact points for a user
+/// Class describing the contact points for a user
///
public class UserContactPoints
{
diff --git a/src/Altinn.Profile.Integrations/SblBridge/PartyNotificationContactPoints.cs b/src/Altinn.Profile.Integrations/SblBridge/PartyNotificationContactPoints.cs
new file mode 100644
index 0000000..3424883
--- /dev/null
+++ b/src/Altinn.Profile.Integrations/SblBridge/PartyNotificationContactPoints.cs
@@ -0,0 +1,52 @@
+namespace Altinn.Profile.Integrations.SblBridge
+{
+ ///
+ /// Model describing a container for a list of contact points.
+ ///
+ public class PartyNotificationContactPoints
+ {
+ ///
+ /// Gets or sets the party id of the organisation.
+ ///
+ public Guid? PartyId { get; set; }
+
+ ///
+ /// Gets or sets the legacy id of the organisation.
+ ///
+ public int LegacyPartyId { get; set; }
+
+ ///
+ /// Gets or sets the organization number of the organisation.
+ ///
+ public string OrganizationNumber { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets a list of multiple contanct points associated with the organisation.
+ ///
+ public List ContactPoints { get; set; } = new List();
+ }
+
+ ///
+ /// Model describing the contact information that a user has associated with a party they can represent.
+ ///
+ public class UserRegisteredContactPoint
+ {
+ ///
+ /// Gets or sets the legacy user id for the owner of this party notification endpoint.
+ ///
+ ///
+ /// This was named as legacy for consistency. Property for UUID will probably never be added.
+ ///
+ public int LegacyUserId { get; set; }
+
+ ///
+ /// Gets or sets the email address for this contact point.
+ ///
+ public string Email { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the mobile number for this contact point.
+ ///
+ public string MobileNumber { get; set; } = string.Empty;
+ }
+}
diff --git a/src/Altinn.Profile.Integrations/SblBridge/UnitProfileClient.cs b/src/Altinn.Profile.Integrations/SblBridge/UnitProfileClient.cs
new file mode 100644
index 0000000..e3bcf65
--- /dev/null
+++ b/src/Altinn.Profile.Integrations/SblBridge/UnitProfileClient.cs
@@ -0,0 +1,79 @@
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+using Altinn.Profile.Core;
+using Altinn.Profile.Core.Integrations;
+using Altinn.Profile.Core.Unit.ContactPoints;
+using Altinn.Profile.Core.User.ContactPoints;
+
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Altinn.Profile.Integrations.SblBridge;
+
+///
+/// Represents an implementation of using SBLBridge to obtain unit profile information.
+///
+public class UnitProfileClient : IUnitProfileClient
+{
+ private readonly ILogger _logger;
+ private readonly HttpClient _client;
+ private readonly JsonSerializerOptions _serializerOptions;
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ /// HttpClient from default http client factory
+ /// the logger
+ /// the sbl bridge settings
+ public UnitProfileClient(
+ HttpClient httpClient,
+ ILogger logger,
+ IOptions settings)
+ {
+ _logger = logger;
+ _client = httpClient;
+ _client.BaseAddress = new Uri(settings.Value.ApiProfileEndpoint);
+
+ _serializerOptions = new JsonSerializerOptions
+ {
+ WriteIndented = true,
+ PropertyNameCaseInsensitive = true,
+ Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
+ };
+ }
+
+ ///
+ public async Task> GetUserRegisteredContactPoints(UnitContactPointLookup lookup)
+ {
+ string endpoint = $"units/contactpointslookup";
+
+ StringContent requestBody = new StringContent(JsonSerializer.Serialize(lookup), Encoding.UTF8, "application/json");
+
+ HttpResponseMessage response = await _client.PostAsync(endpoint, requestBody);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ _logger.LogError("// UnitClient // GetUserRegisteredContactPoints // An error occured when retrieving unit contact points. Failed with {statusCode}", response.StatusCode);
+ return false;
+ }
+
+ string content = await response.Content.ReadAsStringAsync();
+ List partyNotificationEndpoints = JsonSerializer.Deserialize>(content, _serializerOptions)!;
+
+ List contactPoints = partyNotificationEndpoints.Select(partyNotificationEndpoint => new UnitContactPoints
+ {
+ OrganizationNumber = partyNotificationEndpoint.OrganizationNumber,
+ PartyId = partyNotificationEndpoint.LegacyPartyId,
+ UserContactPoints = partyNotificationEndpoint.ContactPoints.Select(contactPoint => new UserContactPoints
+ {
+ UserId = contactPoint.LegacyUserId,
+ Email = contactPoint.Email,
+ MobileNumber = contactPoint.MobileNumber
+ }).ToList()
+ }).ToList();
+
+ return new UnitContactPointsList() { ContactPointsList = contactPoints };
+ }
+}
diff --git a/src/Altinn.Profile.Integrations/ServiceCollectionExtensions.cs b/src/Altinn.Profile.Integrations/ServiceCollectionExtensions.cs
index f1ee636..703128c 100644
--- a/src/Altinn.Profile.Integrations/ServiceCollectionExtensions.cs
+++ b/src/Altinn.Profile.Integrations/ServiceCollectionExtensions.cs
@@ -22,8 +22,8 @@ public static void AddSblBridgeClients(this IServiceCollection services, IConfig
.Get()
?? throw new ArgumentNullException(nameof(config), "Required SblBridgeSettings is missing from application configuration");
- services
- .Configure(config.GetSection(nameof(SblBridgeSettings)))
- .AddHttpClient();
+ services.Configure(config.GetSection(nameof(SblBridgeSettings)));
+ services.AddHttpClient();
+ services.AddHttpClient();
}
}
diff --git a/src/Altinn.Profile/Controllers/UnitContactPointController.cs b/src/Altinn.Profile/Controllers/UnitContactPointController.cs
new file mode 100644
index 0000000..ca87761
--- /dev/null
+++ b/src/Altinn.Profile/Controllers/UnitContactPointController.cs
@@ -0,0 +1,45 @@
+using System.Threading.Tasks;
+
+using Altinn.Profile.Core;
+using Altinn.Profile.Core.Unit.ContactPoints;
+using Altinn.Profile.Core.User.ContactPoints;
+
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Altinn.Profile.Controllers
+{
+ ///
+ /// Controller for unit profile contact point API endpoints for internal consumption (e.g. Notifications) requiring neither authenticated user token nor access token authorization.
+ ///
+ [Route("profile/api/v1/units/contactpoint")]
+ [ApiExplorerSettings(IgnoreApi = true)]
+ [Consumes("application/json")]
+ [Produces("application/json")]
+ public class UnitContactPointController : ControllerBase
+ {
+ private readonly IUnitContactPoints _contactPointService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public UnitContactPointController(IUnitContactPoints contactPointsService)
+ {
+ _contactPointService = contactPointsService;
+ }
+
+ ///
+ /// Endpoint looking up the contact points for the units provided in the lookup object in the request body
+ ///
+ /// Returns an overview of the user registered contact points for the provided units and given resource
+ [HttpPost("lookup")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ public async Task> PostLookup([FromBody] UnitContactPointLookup unitContactPointLookup)
+ {
+ Result result = await _contactPointService.GetUserRegisteredContactPoints(unitContactPointLookup);
+ return result.Match>(
+ success => Ok(success),
+ _ => Problem("Could not retrieve contact points"));
+ }
+ }
+}
diff --git a/src/Altinn.Profile/Controllers/UserContactPointController.cs b/src/Altinn.Profile/Controllers/UserContactPointController.cs
index c11722f..d45d328 100644
--- a/src/Altinn.Profile/Controllers/UserContactPointController.cs
+++ b/src/Altinn.Profile/Controllers/UserContactPointController.cs
@@ -2,6 +2,7 @@
using Altinn.Profile.Core;
using Altinn.Profile.Core.User.ContactPoints;
+using Altinn.Profile.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
diff --git a/src/Altinn.Profile.Core/User.ContactPoints/UserContactPointLookup.cs b/src/Altinn.Profile/Models/UserContactPointLookup.cs
similarity index 82%
rename from src/Altinn.Profile.Core/User.ContactPoints/UserContactPointLookup.cs
rename to src/Altinn.Profile/Models/UserContactPointLookup.cs
index f3db92f..1451e30 100644
--- a/src/Altinn.Profile.Core/User.ContactPoints/UserContactPointLookup.cs
+++ b/src/Altinn.Profile/Models/UserContactPointLookup.cs
@@ -1,4 +1,6 @@
-namespace Altinn.Profile.Core.User.ContactPoints;
+using System.Collections.Generic;
+
+namespace Altinn.Profile.Models;
///
/// A class respresenting a user contact point lookup object
diff --git a/test/Altinn.Profile.Tests/IntegrationTests/API/Controllers/UserContactPointControllerTests.cs b/test/Altinn.Profile.Tests/IntegrationTests/API/Controllers/UserContactPointControllerTests.cs
index beea3ee..4fd4299 100644
--- a/test/Altinn.Profile.Tests/IntegrationTests/API/Controllers/UserContactPointControllerTests.cs
+++ b/test/Altinn.Profile.Tests/IntegrationTests/API/Controllers/UserContactPointControllerTests.cs
@@ -9,6 +9,7 @@
using Altinn.Profile.Controllers;
using Altinn.Profile.Core.User.ContactPoints;
using Altinn.Profile.Integrations.SblBridge;
+using Altinn.Profile.Models;
using Altinn.Profile.Tests.IntegrationTests.Mocks;
using Altinn.Profile.Tests.IntegrationTests.Utils;
using Altinn.Profile.Tests.Testdata;