feat(registratie): WP-36 — admin cases page + admin delete
Admin-only overview of all cases across owners + an admin delete, gated by a new
`cases:manage` capability (Authz role→cap + CanManageCases + CasesAdmin gate;
FE capability + guard + nav + role.interceptor prefix — the org-template/stamdata
recipe). Backend adds ApplicationStore.ListAll()/DeleteAny() and GET /admin/cases +
DELETE /admin/cases/{id}; admin delete removes ANY case incl. submitted. Page lives
in registratie/ui (owns the Aanvraag aggregate; reuses aanvraag-view + parse),
routed /beheer/zaken; delete guarded by a native confirm, optimistic with rollback.
Typed client regenerated (documents the new endpoints + owner field).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using BigRegister.Api.Contracts;
|
||||
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<TestWebApplicationFactory>
|
||||
{
|
||||
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<ApplicationDetailDto> Create(string type)
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/applications", new { type });
|
||||
Assert.Equal(HttpStatusCode.Created, res.StatusCode);
|
||||
return (await res.Content.ReadFromJsonAsync<ApplicationDetailDto>())!;
|
||||
}
|
||||
|
||||
[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<List<ApplicationSummaryDto>>())!;
|
||||
var mine = cases.Single(x => x.Id == a.Id);
|
||||
Assert.False(string.IsNullOrEmpty(mine.Owner)); // admin list carries the 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);
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ public class OrgTemplateEndpointTests(TestWebApplicationFactory factory) : IClas
|
||||
{
|
||||
var res = await _client.SendAsync(Req(HttpMethod.Get, "/api/v1/me", role: "admin"));
|
||||
var me = await res.Content.ReadFromJsonAsync<MeDto>();
|
||||
Assert.Equal(new[] { "orgtemplate:edit", "stamdata:edit" }, me!.Capabilities);
|
||||
Assert.Equal(new[] { "orgtemplate:edit", "stamdata:edit", "cases:manage" }, me!.Capabilities);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user