Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ namespace NHS.CohortManager.DemographicServices;
using System.Text;
using DataServices.Core;
using Model;
using NHS.CohortManager.DemographicServices;

public class ManageCaasSubscription
{
private readonly ILogger<ManageCaasSubscription> _logger;
private readonly ICreateResponse _createResponse;
private readonly IOptions<ManageCaasSubscriptionConfig> _config;
private readonly ManageCaasSubscriptionConfig _config;
private readonly IMeshSendCaasSubscribe _meshSendCaasSubscribe;
private readonly IRequestHandler<NemsSubscription> _requestHandler;
private readonly IDataServiceAccessor<NemsSubscription> _nemsSubscriptionAccessor;
Expand All @@ -33,7 +34,7 @@ public ManageCaasSubscription(
{
_logger = logger;
_createResponse = createResponse;
_config = config;
_config = config.Value;
_meshSendCaasSubscribe = meshSendCaasSubscribe;
_requestHandler = requestHandler;
_nemsSubscriptionAccessor = nemsSubscriptionAccessor;
Expand All @@ -46,22 +47,17 @@ public async Task<HttpResponseData> Subscribe([HttpTrigger(AuthorizationLevel.An
try
{
var nhsNumber = req.Query["nhsNumber"];
if (!ValidationHelper.ValidateNHSNumber(nhsNumber))
if (!ValidationHelper.ValidateNHSNumber(nhsNumber!))
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, "NHS number is required and must be valid format.");
}

// Forward to MeshSendCaasSubscribeStub (Shared)
long.TryParse(nhsNumber, out var nhsNo);
var toMailbox = _config.Value.CaasToMailbox;
var fromMailbox = _config.Value.CaasFromMailbox;
if (string.IsNullOrWhiteSpace(toMailbox) || string.IsNullOrWhiteSpace(fromMailbox))
{
_logger.LogError("CAAS mailbox configuration missing. CaasToMailbox or CaasFromMailbox not set.");
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.InternalServerError, req, "CAAS mailbox configuration missing.");
}
var nhsNo = long.Parse(nhsNumber!);
var toMailbox = _config.CaasToMailbox!;
var fromMailbox = _config.CaasFromMailbox!;
var messageId = await _meshSendCaasSubscribe.SendSubscriptionRequest(nhsNo, toMailbox, fromMailbox);
_logger.LogInformation("CAAS Subscribe forwarded to Mesh stub. NHS: {Nhs}, MessageId: {Msg}", nhsNo, messageId);
_logger.LogInformation("CAAS Subscribe forwarded to Mesh stub. MessageId: {Msg}", messageId);
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.OK, req, $"Subscription request accepted. MessageId: {messageId}");
}
catch (Exception ex)
Expand All @@ -75,12 +71,12 @@ public async Task<HttpResponseData> Subscribe([HttpTrigger(AuthorizationLevel.An
public async Task<HttpResponseData> Unsubscribe([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
var nhsNumber = req.Query["nhsNumber"];
if (!ValidationHelper.ValidateNHSNumber(nhsNumber))
if (!ValidationHelper.ValidateNHSNumber(nhsNumber!))
{
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, "NHS number is required and must be valid format.");
}

_logger.LogInformation("[CAAS-Stub] Unsubscribe called for NHS: {Nhs}", nhsNumber);
_logger.LogInformation("[CAAS-Stub] Unsubscribe called");
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.OK, req, "Stub: CAAS subscription would be removed.");
}

Expand All @@ -93,7 +89,7 @@ public async Task<HttpResponseData> CheckSubscriptionStatus([HttpTrigger(Authori

string? nhsNumber = req.Query["nhsNumber"];

if (!ValidationHelper.ValidateNHSNumber(nhsNumber))
if (!ValidationHelper.ValidateNHSNumber(nhsNumber!))
{
_logger.LogError("NHS number is required and must be valid format");
return await _createResponse.CreateHttpResponseWithBodyAsync(HttpStatusCode.BadRequest, req, "NHS number is required and must be valid format.");
Expand Down Expand Up @@ -135,7 +131,7 @@ public async Task<HttpResponseData> NemsSubscriptionDataService([HttpTrigger(Aut
[Function("PollMeshMailbox")]
public async Task RunAsync([TimerTrigger("59 23 * * *")] TimerInfo myTimer)
{
await _meshPoller.ExecuteHandshake(_config.Value.CaasFromMailbox);
await _meshPoller.ExecuteHandshake(_config.CaasFromMailbox!);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace NHS.CohortManager.DemographicServices;

using System.ComponentModel.DataAnnotations;

// Minimal config object for ManageCaasSubscription.
// Intentionally no [Required] attributes so binding does not fail if unset.
public class ManageCaasSubscriptionConfig
{
// Optional URL for pass-through to the existing NEMS data service
Expand All @@ -19,9 +20,10 @@ public class ManageCaasSubscriptionConfig
public string? MeshCaasKeyPassword { get; set; }
public string? MeshCaasPassword { get; set; }
public required string MeshCaasSharedKey { get; set; }
public required string CaasToMailbox { get; set; }
public required string CaasFromMailbox { get; set; }

[Required]
public string? CaasToMailbox { get; set; }
[Required]
public string? CaasFromMailbox { get; set; }

// Controls whether shared implementations should use stubbed behavior
public bool IsStubbed { get; set; } = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace NHS.CohortManager.Tests.UnitTests.DemographicServicesTests;
using System.Net.Http;
using DataServices.Core;
using Model;
using System.ComponentModel.DataAnnotations;
using System.Linq;

[TestClass]
public class ManageCaasSubscriptionTests
Expand All @@ -25,6 +27,7 @@ public class ManageCaasSubscriptionTests
private readonly Mock<IMeshSendCaasSubscribe> _mesh = new();
private readonly Mock<IRequestHandler<NemsSubscription>> _requestHandler = new();
private readonly Mock<IDataServiceAccessor<NemsSubscription>> _nemsAccessor = new();
private readonly Mock<IMeshPoller> _meshPoller = new();

public ManageCaasSubscriptionTests()
{
Expand Down Expand Up @@ -55,7 +58,8 @@ public ManageCaasSubscriptionTests()
_config.Object,
_mesh.Object,
_requestHandler.Object,
_nemsAccessor.Object
_nemsAccessor.Object,
_meshPoller.Object
);
}

Expand All @@ -75,35 +79,6 @@ public async Task Subscribe_Invalid_ReturnsBadRequest()
Assert.AreEqual(HttpStatusCode.BadRequest, res.StatusCode);
}

[TestMethod]
public async Task Subscribe_MissingMailboxes_ReturnsInternalServerError()
{
// Arrange: missing config values
_config.Setup(x => x.Value).Returns(new ManageCaasSubscriptionConfig
{
ManageNemsSubscriptionDataServiceURL = null,
CaasToMailbox = null,
CaasFromMailbox = null
});

var sutMissing = new ManageCaasSubscription(
_logger.Object,
_createResponse,
_config.Object,
_mesh.Object,
_requestHandler.Object,
_nemsAccessor.Object
);

var req = _setupRequest.Setup(null, new NameValueCollection { { "nhsNumber", "9000000009" } }, HttpMethod.Post);

// Act
var res = await sutMissing.Subscribe(req.Object);

// Assert
Assert.AreEqual(HttpStatusCode.InternalServerError, res.StatusCode);
}

[TestMethod]
public async Task Unsubscribe_Valid_ReturnsOk()
{
Expand Down Expand Up @@ -235,4 +210,40 @@ public async Task Subscribe_MeshThrows_ReturnsInternalServerError()
var res = await _sut.Subscribe(req.Object);
Assert.AreEqual(HttpStatusCode.InternalServerError, res.StatusCode);
}

[TestMethod]
public async Task PollMeshMailbox_UsesConfigFromMailbox()
{
// Ensure config has expected mailbox
_config.Setup(x => x.Value).Returns(new ManageCaasSubscriptionConfig
{
CaasFromMailbox = "TEST_FROM",
CaasToMailbox = "TEST_TO"
});

var sut = new ManageCaasSubscription(
_logger.Object,
_createResponse,
_config.Object,
_mesh.Object,
_requestHandler.Object,
_nemsAccessor.Object,
_meshPoller.Object
);

await sut.RunAsync(null);
_meshPoller.Verify(p => p.ExecuteHandshake("TEST_FROM"), Times.Once);
}

[TestMethod]
public void Config_MissingMailboxes_FailsValidation()
{
var cfg = new ManageCaasSubscriptionConfig();
var context = new ValidationContext(cfg);
var results = new System.Collections.Generic.List<ValidationResult>();
var isValid = Validator.TryValidateObject(cfg, context, results, validateAllProperties: true);
Assert.IsFalse(isValid);
Assert.IsTrue(results.Any(r => r.MemberNames.Contains("CaasToMailbox")));
Assert.IsTrue(results.Any(r => r.MemberNames.Contains("CaasFromMailbox")));
}
}
Loading