Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/STIL.ServiceClient/BaseStilBpiServiceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,38 @@

namespace STIL.ServiceClient;

/// <summary>
/// Base class for clients that talk to the STIL BPI (Brugerdatabasen Programmatisk Interface) SOAP services.
/// </summary>
public abstract class BaseStilBpiServiceClient
{
/// <summary>
/// The base URL of the BPI service.
/// </summary>
protected readonly Uri _baseUrl;

/// <summary>
/// The certificate used to sign outgoing SOAP requests.
/// </summary>
protected readonly X509Certificate2 _signingCertificate;

/// <summary>
/// The client used to send SOAP requests and parse the responses.
/// </summary>
protected readonly ISoapServiceClient _soapServiceClient;

/// <summary>
/// The generator used to build signed BPI SOAP requests.
/// </summary>
protected readonly BpiSoapRequestGenerator _requestGenerator;

/// <summary>
/// Initializes a new instance of the <see cref="BaseStilBpiServiceClient"/> class.
/// </summary>
/// <param name="baseUrl">The base URL of the BPI service.</param>
/// <param name="systemId">The BPI system identifier ("udbydersystem id") to authenticate as.</param>
/// <param name="signingCertificate">The certificate used to sign outgoing SOAP requests.</param>
/// <param name="soapServiceClient">The client used to send SOAP requests and parse the responses.</param>
protected BaseStilBpiServiceClient(string baseUrl, string systemId, X509Certificate2 signingCertificate, ISoapServiceClient soapServiceClient)
{
_baseUrl = new Uri(baseUrl);
Expand All @@ -20,13 +45,23 @@ protected BaseStilBpiServiceClient(string baseUrl, string systemId, X509Certific
_requestGenerator = new BpiSoapRequestGenerator(baseUrl, systemId);
}

/// <summary>
/// Calls the BPI "hello world" operation to verify that the configured certificate is accepted by the service.
/// </summary>
/// <param name="messageId">An optional message identifier to use for the request; a new one is generated when omitted.</param>
/// <returns>A task that completes once the ping request has succeeded.</returns>
public async Task Ping(Guid? messageId = null)
{
helloWorldWithCertificateResponse response = await _soapServiceClient.SendSoapRequest<helloWorldWithCertificateResponse, AuthentificationError>(
_baseUrl,
_requestGenerator.GetSignedRequest(new helloWorldWithCertificate(), _signingCertificate, messageId));
}

/// <summary>
/// Retrieves the data agreements ("dataaftaler") associated with the configured BPI system.
/// </summary>
/// <param name="messageId">An optional message identifier to use for the request; a new one is generated when omitted.</param>
/// <returns>The data agreements response returned by the BPI service.</returns>
public async Task<hentDataAftalerResponse> hentDataAftaler(Guid? messageId = null)
{
hentDataAftalerResponse response = await _soapServiceClient.SendSoapRequest<hentDataAftalerResponse, AuthentificationError>(
Expand Down
12 changes: 12 additions & 0 deletions src/STIL.ServiceClient/BasicSoapRequestGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,20 @@

namespace STIL.ServiceClient;

/// <summary>
/// Builds and signs SOAP requests that only require a body, a binary security token, and a timestamp,
/// without any WS-Addressing or BPI-specific headers.
/// </summary>
public class BasicSoapRequestGenerator
{
/// <summary>
/// Builds a SOAP envelope for <paramref name="requestObject"/> and signs it with <paramref name="signingCertificate"/>.
/// </summary>
/// <typeparam name="TRequest">The type of the request body to serialize into the SOAP envelope.</typeparam>
/// <param name="requestObject">The request body to serialize into the SOAP envelope.</param>
/// <param name="signingCertificate">The certificate used to sign the request.</param>
/// <param name="messageId">An optional message identifier to use for the request; a new one is generated when omitted.</param>
/// <returns>The signed SOAP request as an XML string.</returns>
public string GetSignedRequest<TRequest>(TRequest requestObject, X509Certificate2 signingCertificate, Guid? messageId = null)
{
SoapRequestBuilder<TRequest> builder = new(messageId ?? Guid.NewGuid());
Expand Down
28 changes: 28 additions & 0 deletions src/STIL.ServiceClient/BpiSoapRequestGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,36 @@

namespace STIL.ServiceClient;

/// <summary>
/// Builds and signs SOAP requests for the STIL BPI services, adding the WS-Addressing and
/// BPI-specific ("udbydersystem id") headers those services require in addition to the SOAP body.
/// </summary>
public class BpiSoapRequestGenerator
{
private readonly string _serviceUrl;
private readonly string _systemId;

/// <summary>
/// Initializes a new instance of the <see cref="BpiSoapRequestGenerator"/> class.
/// </summary>
/// <param name="serviceUrl">The base URL of the BPI service, used to build the WS-Addressing action.</param>
/// <param name="systemId">The BPI system identifier ("udbydersystem id") to include in signed requests.</param>
public BpiSoapRequestGenerator(string serviceUrl, string systemId)
{
_serviceUrl = serviceUrl;
_systemId = systemId;
}

/// <summary>
/// Builds a SOAP envelope for <paramref name="requestObject"/>, adds the WS-Addressing and BPI headers,
/// and signs it with <paramref name="signingCertificate"/>.
/// </summary>
/// <typeparam name="TRequest">The type of the request body to serialize into the SOAP envelope.</typeparam>
/// <param name="requestObject">The request body to serialize into the SOAP envelope.</param>
/// <param name="action">The WS-Addressing action name, appended to the service URL.</param>
/// <param name="signingCertificate">The certificate used to sign the request.</param>
/// <param name="messageId">An optional message identifier to use for the request; a new one is generated when omitted.</param>
/// <returns>The signed SOAP request as an XML string.</returns>
public string GetSignedRequest<TRequest>(TRequest requestObject,
string action,
X509Certificate2 signingCertificate,
Expand Down Expand Up @@ -46,10 +65,19 @@
return requestXml;
}

/// <summary>
/// Builds a SOAP envelope for <paramref name="requestObject"/>, adds the WS-Addressing and BPI headers,
/// and signs it with <paramref name="signingCertificate"/>, using the request object's type name as the WS-Addressing action.
/// </summary>
/// <typeparam name="TRequest">The type of the request body to serialize into the SOAP envelope.</typeparam>
/// <param name="requestObject">The request body to serialize into the SOAP envelope.</param>
/// <param name="signingCertificate">The certificate used to sign the request.</param>
/// <param name="messageId">An optional message identifier to use for the request; a new one is generated when omitted.</param>
/// <returns>The signed SOAP request as an XML string.</returns>
public string GetSignedRequest<TRequest>(TRequest requestObject,
X509Certificate2 signingCertificate,
Guid? messageId = null)
{
return GetSignedRequest(requestObject, requestObject.GetType().Name, signingCertificate, messageId);

Check warning on line 81 in src/STIL.ServiceClient/BpiSoapRequestGenerator.cs

View workflow job for this annotation

GitHub Actions / build & test

Dereference of a possibly null reference.
}
}
30 changes: 30 additions & 0 deletions src/STIL.ServiceClient/DTOs/BPI/Common/Ansatrolle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,44 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The Ansatrolle enum.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public enum Ansatrolle
{
/// <summary>
/// The Lærer value.
/// </summary>
Lærer,

/// <summary>
/// The Pædagog value.
/// </summary>
Pædagog,

/// <summary>
/// The Vikar value.
/// </summary>
Vikar,

/// <summary>
/// The Leder value.
/// </summary>
Leder,

/// <summary>
/// The Ledelse value.
/// </summary>
Ledelse,

/// <summary>
/// The TAP value.
/// </summary>
TAP,

/// <summary>
/// The Konsulent value.
/// </summary>
Konsulent,
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The AuthentificationError class.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class AuthentificationError
{
/// <summary>
/// Gets or sets the <see cref="type"/> value.
/// </summary>
[XmlElement(Order=0)]
public AuthentificationErrorType type { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,34 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The AuthentificationErrorType enum.
/// </summary>
[XmlType(AnonymousType=true, Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public enum AuthentificationErrorType
{
/// <summary>
/// The Signatur value.
/// </summary>
Signatur,

/// <summary>
/// The SignaturMangler value.
/// </summary>
SignaturMangler,

/// <summary>
/// The UdbydersytemIdMangler value.
/// </summary>
UdbydersytemIdMangler,

/// <summary>
/// The BrugeridEllerPassword value.
/// </summary>
BrugeridEllerPassword,

/// <summary>
/// The Rettigheder value.
/// </summary>
Rettigheder,
}
10 changes: 10 additions & 0 deletions src/STIL.ServiceClient/DTOs/BPI/Common/Eksternrolle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The Eksternrolle enum.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public enum Eksternrolle
{
/// <summary>
/// The Praktikant value.
/// </summary>
Praktikant,

/// <summary>
/// The Ekstern value.
/// </summary>
Ekstern,
}
14 changes: 14 additions & 0 deletions src/STIL.ServiceClient/DTOs/BPI/Common/Elevrolle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,24 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The Elevrolle enum.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public enum Elevrolle
{
/// <summary>
/// The Barn value.
/// </summary>
Barn,

/// <summary>
/// The Elev value.
/// </summary>
Elev,

/// <summary>
/// The Studerende value.
/// </summary>
Studerende,
}
6 changes: 6 additions & 0 deletions src/STIL.ServiceClient/DTOs/BPI/Common/HelloWorldResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The HelloWorldResponse class.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class HelloWorldResponse
{
/// <summary>
/// Gets or sets the <see cref="helloWorldResult"/> value.
/// </summary>
[XmlElement(Order=0)]
public string helloWorldResult { get; set; }
}
3 changes: 3 additions & 0 deletions src/STIL.ServiceClient/DTOs/BPI/Common/NoArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The NoArgs class.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class NoArgs
{
Expand Down
6 changes: 6 additions & 0 deletions src/STIL.ServiceClient/DTOs/BPI/Common/UdbydersystemIdType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The UdbydersystemIdType class.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class UdbydersystemIdType
{
/// <summary>
/// Gets or sets the <see cref="Value"/> value.
/// </summary>
[XmlText(DataType="token")]
public string Value { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System.Xml.Serialization;

namespace STIL.ServiceClient.DTOs.BPI.Common;

[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class helloWorldWithCertificate
{
}
using System.Xml.Serialization;

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The helloWorldWithCertificate class.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class helloWorldWithCertificate
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The helloWorldWithCertificateRequest class.
/// </summary>
public class helloWorldWithCertificateRequest
{
/// <summary>
/// Gets or sets the <see cref="helloWorldWithCertificate"/> value.
/// </summary>
[MessageBodyMember(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3", Order=0)]
public NoArgs helloWorldWithCertificate { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The helloWorldWithCertificateResponse class.
/// </summary>
public class helloWorldWithCertificateResponse
{
/// <summary>
/// Gets or sets the <see cref="helloWorldWithCertificateResponse1"/> value.
/// </summary>
[MessageBodyMember(Name="helloWorldWithCertificateResponse", Namespace="https://brugerdatabasen.stil.dk/bpi/common/3", Order=0)]
public HelloWorldResponse helloWorldWithCertificateResponse1 { get; set; }
}
19 changes: 11 additions & 8 deletions src/STIL.ServiceClient/DTOs/BPI/Common/hentDataAftaler.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System.Xml.Serialization;

namespace STIL.ServiceClient.DTOs.BPI.Common;

[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class hentDataAftaler
{
}
using System.Xml.Serialization;

namespace STIL.ServiceClient.DTOs.BPI.Common;

/// <summary>
/// The hentDataAftaler class.
/// </summary>
[XmlType(Namespace="https://brugerdatabasen.stil.dk/bpi/common/3")]
public class hentDataAftaler
{
}
Loading
Loading