Files
mic-check/src/api/MicCheck.Api/Common/Security/ApiKeys/ApiKeyEndpoints.cs
T
James Wampler 87113ccdcd
CI / build-and-push (push) Successful in 54s
CI / deploy-qa (push) Successful in 12s
CI / smoke-qa (push) Successful in 24s
Add unit tests for Environments, Audit, and Webhooks namespaces (#6)
## Summary
- Add missing unit test coverage for the Environments, Audit, and Webhooks namespaces (raises them from ~0-62% to 91-100%)
- Exclude WebhookBackgroundService/WebhookRetryBackgroundService from coverage (require live DI/DB, disallowed by CLAUDE.md's no-InMemory/WebApplicationFactory rule)

## Test plan
- [x] `dotnet test` full suite passes (646/646)
- [x] Coverage report confirms Environments ~99.5%, Audit 100%, Webhooks ~91%

Reviewed-on: #6
2026-07-05 15:07:26 -07:00

39 lines
1.8 KiB
C#
Executable File

using System.Diagnostics.CodeAnalysis;
using MicCheck.Api.Common.Security.Authorization;
namespace MicCheck.Api.Common.Security.ApiKeys;
[ExcludeFromCodeCoverage(Justification = "Minimal-API route registration; requires a live HTTP pipeline to exercise, which CLAUDE.md disallows (no WebApplicationFactory/InMemory). Branch logic is covered via ApiKeyService unit tests.")]
public static class ApiKeyEndpoints
{
public static void MapApiKeyEndpoints(this WebApplication app)
{
var group = app
.MapGroup("/api/v1/organisation/{organizationId:int}")
.RequireAuthorization(AuthorizationPolicies.OrganizationAdmin)
.WithTags("ApiKeys");
group.MapPost("/api-keys", async (int organizationId, CreateApiKeyRequest request, ApiKeyService apiKeyService, CancellationToken ct) =>
{
var result = await apiKeyService.CreateAsync(organizationId, request.Name, request.ExpiresAt, ct);
return Results.Ok(new CreateApiKeyResponse(result.Key.Id, result.Key.Name, result.RawKey, result.Key.Prefix, result.Key.ExpiresAt));
}).WithName("CreateApiKey");
group.MapGet("/api-keys", async (int organizationId, ApiKeyService apiKeyService, CancellationToken ct) =>
{
var keys = await apiKeyService.ListAsync(organizationId, ct);
return Results.Ok(keys.Select(k => new ApiKeyResponse(k.Id, k.Name, k.Prefix, k.IsActive, k.ExpiresAt, k.CreatedAt)));
}).WithName("ListApiKeys");
group.MapDelete("/api-key/{keyId:int}", async (int organizationId, int keyId, ApiKeyService apiKeyService, CancellationToken ct) =>
{
await apiKeyService.RevokeAsync(organizationId, keyId, ct);
return Results.NoContent();
}).WithName("RevokeApiKey");
}
}