All checks were successful
## What & why First half of **S-12c** (behandel-portal backend), per **ADR-0013** (decisions recorded in #84): - **BFF multi-realm auth.** A second JWT bearer scheme (`medewerker`) alongside the default `digid` scheme. On validation it lifts Keycloak's `realm_access.roles` onto the principal, and a `behandelaar` policy (medewerker scheme + `behandelaar` role) gates `/behandel/*`. Self-service keeps the digid scheme. - **Werkbak = Flowable tasks.** The domain `Werkbak` query reads the open `Beoordelen` tasks (§8.2, S-12b's `IUserTaskClient`) and enriches each with its aggregate's bsn + status; `GET /behandel/werkbak` (domain) is proxied by the BFF `GET /behandel/werkbak` behind the behandelaar policy. The read projection stays the anonymous openbaar model (no premature `IN_BEHANDELING`/personal-data plumbing — deferred in ADR-0008). Behavior: `/behandel/werkbak` is **401** without a token, **403** for a medewerker lacking the role, **200 + werkbak** for a behandelaar. **S-12c-2** (next): `POST /behandel/registrations/{id}/decide` → domain decision + complete the Flowable task. ## Definition of Done - [x] Linked issue: #13 (umbrella, `refs`); closes the adr-proposal #84 - [x] Tests first; red → green per layer - [x] Unit + acceptance green (`make unit`): domain 78, bff 23, acceptance 9 (+ acl/event-subscriber unaffected) - [x] api-client `test` green; openapi.json regenerated (drift guard passes) - [x] Mutation ≥ break(90): **domain 100%, bff 100%** - [x] ADR-0013 added; `Keycloak__MedewerkerAuthority` wired into compose - [ ] CI green (pending) Part of #13. closes #84 Reviewed-on: #85
58 lines
1.9 KiB
C#
58 lines
1.9 KiB
C#
using System.Net;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
using Bff.Api;
|
|
|
|
namespace Bff.Tests;
|
|
|
|
/// <summary>
|
|
/// The behandel werkbak endpoint (S-12c): reached only with a medewerker-realm token that carries the
|
|
/// <c>behandelaar</c> role. A missing token is 401; an authenticated medewerker without the role is
|
|
/// 403; a behandelaar gets the werkbak (staff view, incl. bsn).
|
|
/// </summary>
|
|
public class BehandelEndpointTests
|
|
{
|
|
private static HttpRequestMessage Werkbak(string? bearer)
|
|
{
|
|
var request = new HttpRequestMessage(HttpMethod.Get, "/behandel/werkbak");
|
|
if (bearer is not null)
|
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearer);
|
|
return request;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Rejects_the_werkbak_without_a_token()
|
|
{
|
|
using var factory = new BffFactory();
|
|
|
|
var response = await factory.CreateClient().SendAsync(Werkbak(bearer: null));
|
|
|
|
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Rejects_a_medewerker_without_the_behandelaar_role()
|
|
{
|
|
using var factory = new BffFactory();
|
|
|
|
var response = await factory.CreateClient().SendAsync(Werkbak(TestTokens.Medewerker("teamlead")));
|
|
|
|
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Serves_the_werkbak_to_a_behandelaar()
|
|
{
|
|
using var factory = new BffFactory();
|
|
factory.Domain.Werkbak.Add(new WerkbakItem("reg-1", "123456782", "InBehandeling"));
|
|
|
|
var response = await factory.CreateClient().SendAsync(Werkbak(TestTokens.Medewerker("behandelaar")));
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
var items = await response.Content.ReadFromJsonAsync<List<WerkbakItem>>();
|
|
var item = Assert.Single(items!);
|
|
Assert.Equal("reg-1", item.RegistrationId);
|
|
Assert.Equal("123456782", item.Bsn);
|
|
}
|
|
}
|