feat(10.1-01): render header and form partials into an allowlisted node tree
- fields.yaml type: partial with a bare path name and config_list.yaml
headerPartial resolve to {ConfigDir}/_{name}.htm, parsed at boot; the
controller must implement pact.AdminPartialData
- html/template render against a curated view model, then x/net/html
ParseFragment and a tag, attribute and URL allowlist with 64 KiB, 2000-node
and depth-32 caps; the model type and trusted template types are refused
- GET .../partials/{name} with optional ?id= loaded through the form scope
- golang.org/x/net becomes a direct requirement (D-18), no new module
This commit is contained in:
103
admin/src/api/schema.d.ts
vendored
103
admin/src/api/schema.d.ts
vendored
@@ -1025,6 +1025,84 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/{vendor}/{plugin}/{controller}/partials/{name}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/**
|
||||
* Render a controller partial
|
||||
* @description Renders a declared header partial or form partial with html/template against the controller's view model and returns it as an allowlisted node tree: no HTML string. Without id the view model gets no record; id is accepted only for form partials and is loaded through the controller's form scope.
|
||||
*/
|
||||
get: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description Record id for a form partial */
|
||||
id?: number;
|
||||
};
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Vendor */
|
||||
vendor: string;
|
||||
/** @description Plugin */
|
||||
plugin: string;
|
||||
/** @description Controller */
|
||||
controller: string;
|
||||
/** @description Partial name */
|
||||
name: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.Envelope-cabana_PartialView"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
/** @description Forbidden */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
/** @description Not Found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/{vendor}/{plugin}/{controller}/schema/form": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -2090,6 +2168,10 @@ export interface components {
|
||||
data: components["schemas"]["cabana.ListSchema"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_PartialView": {
|
||||
data: components["schemas"]["cabana.PartialView"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_RelationMutationResult": {
|
||||
data: components["schemas"]["cabana.RelationMutationResult"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
@@ -2135,6 +2217,11 @@ export interface components {
|
||||
name: string;
|
||||
nameFrom?: string;
|
||||
options?: components["schemas"]["cabana.FormOption"][];
|
||||
/**
|
||||
* @description Path names the controller partial of a `type: partial` field: the
|
||||
* template {ConfigDir}/_{path}.htm (D-09).
|
||||
*/
|
||||
path?: string;
|
||||
readOnly?: boolean;
|
||||
relation?: string;
|
||||
required?: boolean;
|
||||
@@ -2245,6 +2332,11 @@ export interface components {
|
||||
columns: components["schemas"]["cabana.ListColumn"][];
|
||||
defaultSort?: components["schemas"]["cabana.ListSort"];
|
||||
filters: components["schemas"]["cabana.ListFilter"][];
|
||||
/**
|
||||
* @description HeaderPartial names the controller partial rendered above the list
|
||||
* (config_list.yaml headerPartial, D-11).
|
||||
*/
|
||||
headerPartial?: string;
|
||||
/**
|
||||
* @description Messages is the list's copy (D-13). The cached schema carries each
|
||||
* phrase key as its own form; a response resolves them in its locale.
|
||||
@@ -2286,6 +2378,17 @@ export interface components {
|
||||
order: number;
|
||||
sideMenu: components["schemas"]["cabana.NavigationEntry"][];
|
||||
};
|
||||
"cabana.PartialNode": {
|
||||
attrs?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
children?: components["schemas"]["cabana.PartialNode"][];
|
||||
tag?: string;
|
||||
text?: string;
|
||||
};
|
||||
"cabana.PartialView": {
|
||||
nodes: components["schemas"]["cabana.PartialNode"][];
|
||||
};
|
||||
"cabana.RecordEnvelope": {
|
||||
data: components["schemas"]["cabana.AdminRecord"];
|
||||
meta: components["schemas"]["cabana.RecordMeta"];
|
||||
|
||||
Reference in New Issue
Block a user