Skip to content

Commit ce86a64

Browse files
committed
fix: handle namespace retrieval errors in AnomaliesController and add corresponding unit tests
1 parent 536ef73 commit ce86a64

4 files changed

Lines changed: 50 additions & 2 deletions

File tree

services/api/src/ServiceHub.Api/Controllers/V1/AnomaliesController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ public async Task<ActionResult<AnomalyInfo>> GetById(
148148
// it was detected in. Return 404 (not 403) on mismatch to avoid leaking that
149149
// the anomaly ID exists.
150150
var namespaceResult = await _namespaceRepository.GetByIdAsync(result.Value.NamespaceId, cancellationToken);
151+
if (namespaceResult.IsFailure
152+
&& namespaceResult.Error.Type != ServiceHub.Shared.Results.ErrorType.NotFound)
153+
{
154+
return ToActionResult<AnomalyInfo>(namespaceResult.Error);
155+
}
156+
151157
if (namespaceResult.IsFailure
152158
|| !string.Equals(namespaceResult.Value.OwnerId, OwnerId, StringComparison.Ordinal))
153159
{

services/api/src/ServiceHub.Api/Middleware/EasyAuthMiddleware.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public EasyAuthMiddleware(
6565
{
6666
_logger.LogInformation(
6767
"EasyAuth is enabled in configuration but Azure Easy Auth is not detected " +
68-
"(WEBSITE_AUTH_ENABLED is not set). The X-MS-CLIENT-PRINCIPAL-ID header will be " +
68+
"(WEBSITE_AUTH_ENABLED is not set to 'True'). The X-MS-CLIENT-PRINCIPAL-ID header will be " +
6969
"ignored to prevent identity spoofing. If a trusted proxy strips and injects this " +
7070
"header on your platform, set Security:EasyAuth:TrustClientPrincipalHeader=true.");
7171
}

services/api/tests/ServiceHub.UnitTests/Api/Controllers/V1/AnomaliesControllerTests.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,47 @@ public async Task GetById_NamespaceOwnedByAnotherTenant_ShouldReturnNotFound()
224224
result.Result.Should().BeOfType<NotFoundObjectResult>();
225225
}
226226

227+
[Fact]
228+
public async Task GetById_NamespaceNotFound_ShouldReturnNotFound()
229+
{
230+
var anomaly = Anomaly.Create(
231+
Guid.NewGuid(),
232+
"test-queue",
233+
AnomalyType.HighMessageVolume,
234+
50,
235+
"Message volume anomaly");
236+
237+
_aiServiceClient.Setup(a => a.GetAnomalyByIdAsync(anomaly.Id, It.IsAny<CancellationToken>()))
238+
.ReturnsAsync(Result<Anomaly>.Success(anomaly));
239+
_namespaceRepository.Setup(r => r.GetByIdAsync(anomaly.NamespaceId, It.IsAny<CancellationToken>()))
240+
.ReturnsAsync(Result<Namespace>.Failure(Error.NotFound("NOT_FOUND", "Namespace not found")));
241+
242+
var result = await _controller.GetById(anomaly.Id);
243+
244+
result.Result.Should().BeOfType<NotFoundObjectResult>();
245+
}
246+
247+
[Fact]
248+
public async Task GetById_NamespaceLookupFails_ShouldPropagateError()
249+
{
250+
var anomaly = Anomaly.Create(
251+
Guid.NewGuid(),
252+
"test-queue",
253+
AnomalyType.HighMessageVolume,
254+
50,
255+
"Message volume anomaly");
256+
257+
_aiServiceClient.Setup(a => a.GetAnomalyByIdAsync(anomaly.Id, It.IsAny<CancellationToken>()))
258+
.ReturnsAsync(Result<Anomaly>.Success(anomaly));
259+
_namespaceRepository.Setup(r => r.GetByIdAsync(anomaly.NamespaceId, It.IsAny<CancellationToken>()))
260+
.ReturnsAsync(Result<Namespace>.Failure(Error.Internal("DB_ERR", "Database unavailable")));
261+
262+
var result = await _controller.GetById(anomaly.Id);
263+
264+
var objectResult = result.Result.Should().BeOfType<ObjectResult>().Subject;
265+
objectResult.StatusCode.Should().Be(StatusCodes.Status500InternalServerError);
266+
}
267+
227268
[Fact]
228269
public async Task GetById_NotFound_ShouldReturnNotFound()
229270
{

services/api/tests/ServiceHub.UnitTests/Api/Middleware/EasyAuthMiddlewareTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public async Task InvokeAsync_BehindAzureEasyAuth_ShouldAuthenticateFromHeader()
7676
{
7777
// Azure App Service sets WEBSITE_AUTH_ENABLED=True on the worker when
7878
// Easy Auth is active — the only environment where the header is unforgeable.
79+
var previousValue = Environment.GetEnvironmentVariable("WEBSITE_AUTH_ENABLED");
7980
Environment.SetEnvironmentVariable("WEBSITE_AUTH_ENABLED", "True");
8081
try
8182
{
@@ -92,7 +93,7 @@ public async Task InvokeAsync_BehindAzureEasyAuth_ShouldAuthenticateFromHeader()
9293
}
9394
finally
9495
{
95-
Environment.SetEnvironmentVariable("WEBSITE_AUTH_ENABLED", null);
96+
Environment.SetEnvironmentVariable("WEBSITE_AUTH_ENABLED", previousValue);
9697
}
9798
}
9899

0 commit comments

Comments
 (0)