using System.Net; using System.Net.Http.Json; using BigRegister.Api.Contracts; using BigRegister.Api.Data; using Microsoft.AspNetCore.Mvc.Testing; namespace BigRegister.Tests; /// WP-36: admin cross-owner case list + admin delete, gated by `cases:manage`. public class AdminCasesTests(TestWebApplicationFactory factory) : IClassFixture { private readonly HttpClient _client = factory.CreateClient(); private HttpRequestMessage Admin(HttpMethod method, string path) { var req = new HttpRequestMessage(method, path); req.Headers.Add("X-Role", "admin"); return req; } private async Task Create(string type) { var res = await _client.PostAsJsonAsync("/api/v1/applications", new { type }); Assert.Equal(HttpStatusCode.Created, res.StatusCode); return (await res.Content.ReadFromJsonAsync())!; } [Fact] public async Task Admin_lists_every_case_with_its_owner() { var a = await Create("herregistratie"); try { var list = await _client.SendAsync(Admin(HttpMethod.Get, "/api/v1/admin/cases")); list.EnsureSuccessStatusCode(); var cases = (await list.Content.ReadFromJsonAsync>())!; var mine = cases.Single(x => x.Id == a.Id); // RB-03/BIO-003: the owner is carried, but masked — it is a BSN, and this list is // read by someone who is not the subject. Assert.Equal("******782", mine.Owner); Assert.DoesNotContain(DocumentStore.DemoOwner, mine.Owner); } finally { await _client.SendAsync(Admin(HttpMethod.Delete, $"/api/v1/admin/cases/{a.Id}")); } } [Fact] public async Task Non_admin_is_forbidden() { Assert.Equal(HttpStatusCode.Forbidden, (await _client.GetAsync("/api/v1/admin/cases")).StatusCode); Assert.Equal(HttpStatusCode.Forbidden, (await _client.DeleteAsync("/api/v1/admin/cases/anything")).StatusCode); } [Fact] public async Task Admin_can_delete_a_submitted_case() { var a = await Create("registratie"); (await _client.PostAsJsonAsync($"/api/v1/applications/{a.Id}/submit", new { diplomaHerkomst = "duo" })) .EnsureSuccessStatusCode(); // The user-facing DELETE refuses a submitted case (409); admin delete removes it. var del = await _client.SendAsync(Admin(HttpMethod.Delete, $"/api/v1/admin/cases/{a.Id}")); Assert.Equal(HttpStatusCode.NoContent, del.StatusCode); Assert.Equal(HttpStatusCode.NotFound, (await _client.GetAsync($"/api/v1/applications/{a.Id}")).StatusCode); } [Fact] public async Task Deleting_a_missing_case_is_not_found() { var del = await _client.SendAsync(Admin(HttpMethod.Delete, "/api/v1/admin/cases/does-not-exist")); Assert.Equal(HttpStatusCode.NotFound, del.StatusCode); } }