using System.Net; using System.Net.Http.Json; using BigRegister.Api.Contracts; using BigRegister.Api.Zgw; using Microsoft.AspNetCore.Mvc.Testing; namespace BigRegister.Tests; /// The inbound Notificaties (NRC) webhook — auth accept/reject + the audit trail it /// writes via AuthzAuditStore (no Principal exists for an NRC caller, so this doesn't go /// through the Principal-shaped AuditAuthz helper the user-facing endpoints use). public class NotificatieTests(TestWebApplicationFactory factory) : IClassFixture { private readonly HttpClient _client = factory.CreateClient(); private static NotificatieDto Sample(string zaakUrl) => new( Kanaal: "zaken", HoofdObject: zaakUrl, Resource: "zaak", ResourceUrl: zaakUrl, Actie: "update", Aanmaakdatum: DateTimeOffset.UtcNow, Kenmerken: null); private async Task Post(string? authorization, string zaakUrl) { var req = new HttpRequestMessage(HttpMethod.Post, "/api/v1/zgw/notificaties") { Content = JsonContent.Create(Sample(zaakUrl)), }; if (authorization is not null) req.Headers.TryAddWithoutValidation("Authorization", authorization); return await _client.SendAsync(req); } private async Task> AuditLog() { var req = new HttpRequestMessage(HttpMethod.Get, "/api/v1/admin/audit"); req.Headers.Add("X-Role", "admin"); var res = await _client.SendAsync(req); res.EnsureSuccessStatusCode(); return (await res.Content.ReadFromJsonAsync>())!; } [Fact] public async Task Correct_shared_secret_is_accepted_and_recorded() { var zaak = $"https://open-zaak.example/zaken/api/v1/zaken/{Guid.NewGuid()}"; var res = await Post("test-nrc-secret", zaak); Assert.Equal(HttpStatusCode.NoContent, res.StatusCode); Assert.Contains(await AuditLog(), e => e.Action == "zgw:notificatie" && e.Resource == zaak && e.Decision == "allow" && e.Role == "nrc"); } [Fact] public async Task Wrong_secret_is_rejected_and_recorded() { var zaak = $"https://open-zaak.example/zaken/api/v1/zaken/{Guid.NewGuid()}"; var res = await Post("not-the-secret", zaak); Assert.Equal(HttpStatusCode.Unauthorized, res.StatusCode); Assert.Contains(await AuditLog(), e => e.Action == "zgw:notificatie" && e.Resource == zaak && e.Decision == "deny"); } [Fact] public async Task Missing_authorization_header_is_rejected() { var zaak = $"https://open-zaak.example/zaken/api/v1/zaken/{Guid.NewGuid()}"; Assert.Equal(HttpStatusCode.Unauthorized, (await Post(null, zaak)).StatusCode); } }