refactor(acl): resolve the objecttype's highest published version (refs #149)
Counting the `versions` URLs assumed a contiguous, all-published list. Read the objecttype's versions collection instead and take the highest one whose status is `published`, so a draft version — whose schema is still being shaped — is never written against.
This commit is contained in:
@@ -41,7 +41,7 @@ public sealed class ObjectenGateway(HttpClient http, ObjectenOptions options, IC
|
||||
private RecordDto NewRecord(int typeVersion, RecordDataDto data) =>
|
||||
new(typeVersion, data, clock.Today.ToString("yyyy-MM-dd"));
|
||||
|
||||
/// <summary>The URL + latest version number of the configured objecttype, read from Objecttypen.</summary>
|
||||
/// <summary>The URL + latest published version of the configured objecttype, read from Objecttypen.</summary>
|
||||
private async Task<Objecttype> ResolveObjecttypeAsync(CancellationToken ct)
|
||||
{
|
||||
var page = await GetAsync<ObjecttypePage>(
|
||||
@@ -52,10 +52,16 @@ public sealed class ObjectenGateway(HttpClient http, ObjectenOptions options, IC
|
||||
?? throw new InvalidOperationException(
|
||||
$"No objecttype '{options.ObjecttypeName}' registered in Objecttypen — is the RegisterRecord seed applied?");
|
||||
|
||||
// `versions` lists the objecttype's version URLs; the count is the latest version number.
|
||||
var version = match.Versions?.Count
|
||||
?? throw new InvalidOperationException($"Objecttype '{options.ObjecttypeName}' has no published version");
|
||||
return new Objecttype(new Uri(match.Url), version);
|
||||
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();
|
||||
if (latest == 0)
|
||||
throw new InvalidOperationException($"Objecttype '{options.ObjecttypeName}' has no published version");
|
||||
|
||||
return new Objecttype(url, latest);
|
||||
}
|
||||
|
||||
/// <summary>The URL of the object already holding this registration's record, or null if there is none.</summary>
|
||||
@@ -115,8 +121,11 @@ 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("versions")] IReadOnlyList<string>? Versions);
|
||||
[property: JsonPropertyName("name")] string? Name);
|
||||
|
||||
private sealed record ObjecttypeVersionDto(
|
||||
[property: JsonPropertyName("version")] int Version,
|
||||
[property: JsonPropertyName("status")] string? Status);
|
||||
|
||||
private sealed record ObjectPage(
|
||||
[property: JsonPropertyName("results")] IReadOnlyList<ObjectDto>? Results);
|
||||
|
||||
Reference in New Issue
Block a user