feat(12.2-02): add file removal, caption, reorder and protected downloads

- DELETE, PUT and POST reorder under .../{id}/files/{field}, each scoped by one parent query (404 for a foreign file)
- protected download and thumb routes: is_public=false only, nosniff, private no-store, sandbox CSP, inline only for jpeg/png/gif/webp
- the save applies deferred removals, replaces attachOne files and rechecks maxFiles and required
- blobs of deleted files are removed after commit
- swagger2openapi emits binary content for file responses
- admin OpenAPI, TS types, conformance, README and attachments docs
This commit is contained in:
Jakub Zych
2026-10-02 18:11:56 +02:00
parent 044e0450ef
commit e54fd257ee
17 changed files with 2237 additions and 82 deletions

View File

@@ -234,3 +234,18 @@ func TestConvertFormData(t *testing.T) {
t.Fatalf("form schema = %#v", schema)
}
}
func TestConvertFileResponse(t *testing.T) {
res := convertResponses(decode(t, `{
"200": {"description": "OK", "schema": {"type": "file"}},
"404": {"description": "Not Found", "schema": {"$ref": "#/definitions/acme.Error"}}
}`), []string{"application/octet-stream"})
ok := res["200"].(map[string]any)["content"].(map[string]any)
if !reflect.DeepEqual(ok, map[string]any{"application/octet-stream": map[string]any{"schema": map[string]any{"type": "string", "format": "binary"}}}) {
t.Fatalf("file response = %#v", ok)
}
missing := res["404"].(map[string]any)["content"].(map[string]any)
if _, ok := missing["application/json"]; !ok || len(missing) != 1 {
t.Fatalf("error response next to a binary success = %#v", missing)
}
}