fix(acl): read each objecttype version instead of the versions collection (refs #149)
The version resolve assumed `GET {objecttype}/versions` returns a bare list.
Every other collection in the Objecttypen API returns a paginated envelope, and
nothing in the repo exercises that endpoint, so the shape was a guess. Follow
the path infra/registerrecord-check.py already proves against the real API
instead: read the `versions` URLs off the objecttype and fetch each for its
status. Costs a request per version, once per gateway instance.
ACL mutation score 92.23% (baseline 91.37%).
This commit is contained in:
@@ -52,16 +52,23 @@ public sealed class ObjectenGateway(HttpClient http, ObjectenOptions options, IC
|
||||
?? throw new InvalidOperationException(
|
||||
$"No objecttype '{options.ObjecttypeName}' registered in Objecttypen — is the RegisterRecord seed applied?");
|
||||
|
||||
var url = new Uri(match.Url);
|
||||
// Write against the highest *published* version: a draft version's schema is still being
|
||||
// shaped, and objects written against it would be validated by a moving target.
|
||||
var versions = await GetAsync<IReadOnlyList<ObjecttypeVersionDto>>(
|
||||
new Uri(url + "/versions"), options.ObjecttypenToken, crs: false, "objecttype versions", ct);
|
||||
var latest = versions.Where(v => v.Status == "published").Select(v => v.Version).DefaultIfEmpty(0).Max();
|
||||
// shaped, and objects written against it would be validated by a moving target. The objecttype
|
||||
// carries its versions as URLs, so each is fetched for its status (the collection response
|
||||
// gives no status) — once per gateway instance, alongside the lookup above.
|
||||
var latest = 0;
|
||||
foreach (var versionUrl in match.Versions ?? [])
|
||||
{
|
||||
var version = await GetAsync<ObjecttypeVersionDto>(
|
||||
new Uri(versionUrl), options.ObjecttypenToken, crs: false, "objecttype version", ct);
|
||||
if (version.Status == "published" && version.Version > latest)
|
||||
latest = version.Version;
|
||||
}
|
||||
|
||||
if (latest == 0)
|
||||
throw new InvalidOperationException($"Objecttype '{options.ObjecttypeName}' has no published version");
|
||||
|
||||
return new Objecttype(url, latest);
|
||||
return new Objecttype(new Uri(match.Url), latest);
|
||||
}
|
||||
|
||||
/// <summary>The URL of the object already holding this registration's record, or null if there is none.</summary>
|
||||
@@ -121,7 +128,8 @@ public sealed class ObjectenGateway(HttpClient http, ObjectenOptions options, IC
|
||||
|
||||
private sealed record ObjecttypeDto(
|
||||
[property: JsonPropertyName("url")] string Url,
|
||||
[property: JsonPropertyName("name")] string? Name);
|
||||
[property: JsonPropertyName("name")] string? Name,
|
||||
[property: JsonPropertyName("versions")] IReadOnlyList<string>? Versions);
|
||||
|
||||
private sealed record ObjecttypeVersionDto(
|
||||
[property: JsonPropertyName("version")] int Version,
|
||||
|
||||
Reference in New Issue
Block a user