feat(12.2-03): add parent-scoped child show, update, delete and pivot routes
- loadChild finds a child with one query carrying the parent predicate; a foreign child is 404
- GET/PUT .../records/{child} and POST .../delete (all or nothing) per relation kind
- hasMany link adopts NULL-key rows and unlink clears the key; pending created children are never candidates
- link accepts pivot values for one id through the pivot.form whitelist; GET/PUT .../pivot/{child}
- Link and Unlink share linkRelated/unlinkRelated for the deferred commit
This commit is contained in:
@@ -67,11 +67,19 @@ type ListEnvelope[T any] struct {
|
||||
type AdminRecord map[string]any
|
||||
|
||||
// AdminIDsRequest is the body of the id-list writes: bulk delete, relation
|
||||
// link and relation unlink.
|
||||
// unlink and relation child delete.
|
||||
type AdminIDsRequest struct {
|
||||
IDs []uint64 `json:"ids"`
|
||||
}
|
||||
|
||||
// AdminRelationLinkRequest is the body of the relation link route: the
|
||||
// related ids and, on a belongsToMany relation with a pivot form, the pivot
|
||||
// form values of exactly one linked id. Unknown keys are refused.
|
||||
type AdminRelationLinkRequest struct {
|
||||
IDs []uint64 `json:"ids"`
|
||||
Pivot map[string]any `json:"pivot,omitempty"`
|
||||
}
|
||||
|
||||
// AdminLoginRequest is the admin login body. Either login or email
|
||||
// identifies the backend user.
|
||||
type AdminLoginRequest struct {
|
||||
@@ -582,7 +590,7 @@ func AdminRelationCandidates() {}
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Param body body AdminIDsRequest true "Related record ids"
|
||||
// @Param body body AdminRelationLinkRequest true "Related record ids and optional pivot form values"
|
||||
// @Success 200 {object} Envelope[RelationMutationResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
@@ -635,6 +643,119 @@ func AdminRelationUnlink() {}
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/records [post]
|
||||
func AdminRelationChildCreate() {}
|
||||
|
||||
// AdminRelationChildShow documents the relation child show route.
|
||||
//
|
||||
// @Summary Show a related record
|
||||
// @Description One child of the owner, projected through the manage form when the relation declares the update button, else through the view form (view.form, or the top-level form). A record that is not a child of this owner (hasMany: its foreign key; belongsToMany: a pivot row) is 404. Without either form the route answers 403.
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Param child path integer true "Related record id"
|
||||
// @Success 200 {object} RecordEnvelope
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/records/{child} [get]
|
||||
func AdminRelationChildShow() {}
|
||||
|
||||
// AdminRelationChildUpdate documents the relation child update route.
|
||||
//
|
||||
// @Summary Update a related record
|
||||
// @Description Saves one child of the owner through the manage form, with the related model's rules and hooks. The view panel must declare the update toolbar button, otherwise 403. A record that is not a child of this owner is 404.
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Param child path integer true "Related record id"
|
||||
// @Param body body AdminRecord true "Field values of the manage form keyed by field name"
|
||||
// @Success 200 {object} RecordEnvelope
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 413 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/records/{child} [put]
|
||||
func AdminRelationChildUpdate() {}
|
||||
|
||||
// AdminRelationChildDelete documents the relation child delete route.
|
||||
//
|
||||
// @Summary Delete related records
|
||||
// @Description Deletes children of the owner through their model: a hasMany child is deleted (hooks and soft delete run); a belongsToMany record loses this owner's pivot row and is then deleted. Every id must be a child of this owner, otherwise the whole request is 404 and nothing is deleted. The view panel must declare the delete toolbar button, otherwise 403.
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Param body body AdminIDsRequest true "Related record ids"
|
||||
// @Success 200 {object} Envelope[BulkResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 413 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/delete [post]
|
||||
func AdminRelationChildDelete() {}
|
||||
|
||||
// AdminRelationPivotShow documents the pivot show route.
|
||||
//
|
||||
// @Summary Show the pivot values of a link
|
||||
// @Description The pivot form (pivot.form) values of the pivot row linking the owner and one related record, keyed by field name; id is the related record's id. Needs a pivot form and the link or update toolbar button (403 otherwise); a record not linked to this owner is 404.
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Param child path integer true "Related record id"
|
||||
// @Success 200 {object} Envelope[AdminRecord]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/pivot/{child} [get]
|
||||
func AdminRelationPivotShow() {}
|
||||
|
||||
// AdminRelationPivotUpdate documents the pivot update route.
|
||||
//
|
||||
// @Summary Update the pivot values of a link
|
||||
// @Description Saves pivot form values on the pivot row linking the owner and one related record. Only pivot form fields are accepted (422 per unknown key); the pivot foreign keys, timestamps and hook columns can never be set. Gated and scoped like the pivot show route.
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Param child path integer true "Related record id"
|
||||
// @Param body body AdminRecord true "Pivot form values keyed by field name"
|
||||
// @Success 200 {object} Envelope[AdminRecord]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 413 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/pivot/{child} [put]
|
||||
func AdminRelationPivotUpdate() {}
|
||||
|
||||
// FileMutationResult is the payload of a file removal: the number of files
|
||||
// removed (always 1 on success).
|
||||
type FileMutationResult struct {
|
||||
|
||||
Reference in New Issue
Block a user