Add typed settings areas to the REST API
/api/v1/settings/router/firewall, .../router/lans/<name>, .../system, down to a single option: GET reads, PUT replaces, PATCH merges, DELETE removes, with the settings' ETag/If-Match and the same limits as the whole-document edit (editSettings is now shared). Values are checked against a JSON Schema made from the option documentation (schema.go reads the types, which nixosOptionsDoc describes in words); a wrong type, a value out of range or an unknown key is refused with its place. The OpenAPI document has the area paths with their schemas; the API reference page lists every area's options. Tests: unit tests for the type reader, the validator and the paths; the real option file and a router's own settings validate (ROUTER_OPTIONS_JSON, LIVE_SETTINGS_JSON); a subtest in apply. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
@@ -31,5 +31,34 @@
|
||||
</section>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<section class="panel">
|
||||
<h2>Settings areas</h2>
|
||||
<p>The settings are a tree, and every part of it has its own path below <code>/api/v1/settings</code>:
|
||||
<code>router/firewall</code>, <code>router/lans/lan</code> (one LAN, by its name), <code>router/dns/hosts</code>,
|
||||
<code>system</code>, down to a single option like <code>router/wan/interface</code> (lists are replaced whole; their
|
||||
elements have no paths). The OpenAPI document describes each with the type of its value.</p>
|
||||
<ul>
|
||||
<li><code>GET</code> reads the part (404 when it is not set and the defaults apply); the <code>ETag</code> header is the
|
||||
settings' version.</li>
|
||||
<li><code>PUT</code> replaces it, <code>PATCH</code> merges a JSON merge patch into it (objects only), <code>DELETE</code> removes
|
||||
it. They need <code>If-Match</code> with the ETag, need a change token, and are refused (400, with the place) when a value
|
||||
does not fit its option's type or a key is not an option.</li>
|
||||
<li>Like every edit through the API they are saved, never applied; <code>GET /api/v1/settings/check</code> evaluates them.</li>
|
||||
</ul>
|
||||
<pre class="log">curl -sk -H "Authorization: Bearer $TOKEN" https://{{.Host}}/api/v1/settings/router/dns
|
||||
curl -sk -X PUT -H "Authorization: Bearer $TOKEN" -H 'If-Match: "ETAG"' \
|
||||
-d '{"domain":"home.example.org","dynamicLeases":true}' https://{{.Host}}/api/v1/settings/router/dns</pre>
|
||||
</section>
|
||||
{{range .Areas}}
|
||||
<section class="panel">
|
||||
<h2><code>{{.Path}}</code></h2>
|
||||
<div class="scroll"><table class="opts">
|
||||
<tr><th>Option</th><th>Type</th><th>Default</th><th>Description</th></tr>
|
||||
{{range .Options}}<tr><td><code>{{.Name}}</code></td><td>{{.Type}}</td><td>{{with .Default}}<code>{{.}}</code>{{end}}</td><td>{{.Description}}</td></tr>{{end}}
|
||||
</table></div>
|
||||
<p class="hint"><code><name></code> is the key of an entry in a map, <code>*</code> an element of a list.</p>
|
||||
</section>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user