feat(10.1-01): run registered widget actions through a cabana-owned route
- pact: AdminClientAssets, AdminAction, AdminActionInput, AdminActionResult,
HasAdminActions and AdminPartialData contracts
- fields.yaml type: widget with widget, action and fill keys; boot checks the
plugin tag prefix, the registered action and writable scalar fill fields
- POST .../widgets/{field} behind requireAjax, controller and action
permissions, scoped non-locking record read and a server-side fill filter
- typed OpenAPI operation, inventories and an acme conformance case
This commit is contained in:
@@ -1,6 +1,34 @@
|
||||
{
|
||||
"components": {
|
||||
"schemas": {
|
||||
"cabana.AdminActionRequest": {
|
||||
"properties": {
|
||||
"record_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"values": {
|
||||
"additionalProperties": {},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.AdminActionResult": {
|
||||
"properties": {
|
||||
"fill": {
|
||||
"additionalProperties": {},
|
||||
"type": "object"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"fill",
|
||||
"message"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.AdminIDsRequest": {
|
||||
"properties": {
|
||||
"ids": {
|
||||
@@ -196,6 +224,21 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.Envelope-cabana_AdminActionResult": {
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/cabana.AdminActionResult"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/cabana.SuccessMeta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data",
|
||||
"meta"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.Envelope-cabana_AdminLoginData": {
|
||||
"properties": {
|
||||
"data": {
|
||||
@@ -394,6 +437,14 @@
|
||||
},
|
||||
"cabana.FormField": {
|
||||
"properties": {
|
||||
"action": {
|
||||
"description": "Action names the controller action the widget runs (pact.HasAdminActions).",
|
||||
"type": "string"
|
||||
},
|
||||
"actionLabel": {
|
||||
"description": "ActionLabel is the action's Label, localized per request.",
|
||||
"type": "string"
|
||||
},
|
||||
"attributes": {
|
||||
"additionalProperties": {
|
||||
"$ref": "#/components/schemas/cabana.jsonScalar"
|
||||
@@ -412,6 +463,13 @@
|
||||
"emptyOption": {
|
||||
"type": "string"
|
||||
},
|
||||
"fill": {
|
||||
"description": "Fill lists the fields of the same form the action writes back (D-07).",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -450,6 +508,10 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"widget": {
|
||||
"description": "Widget is the custom-element tag of a `type: widget` field (D-06).",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2668,6 +2730,121 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/{vendor}/{plugin}/{controller}/widgets/{field}": {
|
||||
"post": {
|
||||
"description": "Runs the controller action a `type: widget` field declares. The record is loaded through the controller's form scope (404 when out of scope); only the field's fill keys with scalar values reach the action and the response.",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Vendor",
|
||||
"in": "path",
|
||||
"name": "vendor",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Plugin",
|
||||
"in": "path",
|
||||
"name": "plugin",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Controller",
|
||||
"in": "path",
|
||||
"name": "controller",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Widget field name",
|
||||
"in": "path",
|
||||
"name": "field",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.AdminActionRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Record id and fill snapshot",
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.Envelope-cabana_AdminActionResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "OK"
|
||||
},
|
||||
"401": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Unauthorized"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Not Found"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Unprocessable Entity"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"BackendBearer": []
|
||||
}
|
||||
],
|
||||
"summary": "Run a widget action",
|
||||
"tags": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/{vendor}/{plugin}/{controller}/{id}": {
|
||||
"delete": {
|
||||
"parameters": [
|
||||
|
||||
113
admin/src/api/schema.d.ts
vendored
113
admin/src/api/schema.d.ts
vendored
@@ -1237,6 +1237,95 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/{vendor}/{plugin}/{controller}/widgets/{field}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/**
|
||||
* Run a widget action
|
||||
* @description Runs the controller action a `type: widget` field declares. The record is loaded through the controller's form scope (404 when out of scope); only the field's fill keys with scalar values reach the action and the response.
|
||||
*/
|
||||
post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
/** @description Vendor */
|
||||
vendor: string;
|
||||
/** @description Plugin */
|
||||
plugin: string;
|
||||
/** @description Controller */
|
||||
controller: string;
|
||||
/** @description Widget field name */
|
||||
field: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
/** @description Record id and fill snapshot */
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.AdminActionRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.Envelope-cabana_AdminActionResult"];
|
||||
};
|
||||
};
|
||||
/** @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"];
|
||||
};
|
||||
};
|
||||
/** @description Unprocessable Entity */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.ErrorEnvelope"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/{vendor}/{plugin}/{controller}/{id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1812,6 +1901,18 @@ export interface paths {
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
schemas: {
|
||||
"cabana.AdminActionRequest": {
|
||||
record_id?: number;
|
||||
values?: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
};
|
||||
"cabana.AdminActionResult": {
|
||||
fill: {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
message: string;
|
||||
};
|
||||
"cabana.AdminIDsRequest": {
|
||||
ids: number[];
|
||||
};
|
||||
@@ -1864,6 +1965,10 @@ export interface components {
|
||||
data: components["schemas"]["cabana.SettingsEntry"][];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_AdminActionResult": {
|
||||
data: components["schemas"]["cabana.AdminActionResult"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_AdminLoginData": {
|
||||
data: components["schemas"]["cabana.AdminLoginData"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
@@ -1919,6 +2024,10 @@ export interface components {
|
||||
value: string;
|
||||
};
|
||||
"cabana.FormField": {
|
||||
/** @description Action names the controller action the widget runs (pact.HasAdminActions). */
|
||||
action?: string;
|
||||
/** @description ActionLabel is the action's Label, localized per request. */
|
||||
actionLabel?: string;
|
||||
attributes?: {
|
||||
[key: string]: components["schemas"]["cabana.jsonScalar"];
|
||||
};
|
||||
@@ -1926,6 +2035,8 @@ export interface components {
|
||||
context?: components["schemas"]["cabana.fieldContext"];
|
||||
default?: components["schemas"]["cabana.jsonScalar"];
|
||||
emptyOption?: string;
|
||||
/** @description Fill lists the fields of the same form the action writes back (D-07). */
|
||||
fill?: string[];
|
||||
label?: string;
|
||||
multiple?: boolean;
|
||||
name: string;
|
||||
@@ -1938,6 +2049,8 @@ export interface components {
|
||||
span?: string;
|
||||
tab?: string;
|
||||
type: string;
|
||||
/** @description Widget is the custom-element tag of a `type: widget` field (D-06). */
|
||||
widget?: string;
|
||||
};
|
||||
"cabana.FormMessages": {
|
||||
create: components["schemas"]["cabana.MessageForms"];
|
||||
|
||||
Reference in New Issue
Block a user