Browse Source

Update low-code form docs and clarify sorting guard wording

Sync the form layout examples in docs/en/low-code/model-json.md to the
flat fields[]/row/colSpan shape introduced in this PR. Switch the form
descriptor schema description from "layout cell" to "layout placement"
to match the new vocabulary. Soften the AbpDynamicSortingGuard XML doc
and inline comment so they no longer claim the allowed constant-string
indexer carries no side effects — the guard cannot enforce that on
user-defined indexers, so the doc now states it assumes the matching
getter behaves like a property getter.
pull/25637/head
maliming 4 months ago
parent
commit
ce3945386d
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 17
      docs/en/low-code/model-json.md
  2. 15
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbpDynamicSortingGuard.cs
  3. 2
      schemas/low-code/definitions/form-descriptor.schema.json

17
docs/en/low-code/model-json.md

@ -362,9 +362,10 @@ Forms are named definitions referenced by pages through `formName`, `createFormN
"id": "details",
"title": "Details",
"isDefault": true,
"rows": [
{ "cells": [{ "fieldId": "name", "colSpan": 4 }] },
{ "cells": [{ "fieldId": "status", "colSpan": 2 }, { "fieldId": "ownerId", "colSpan": 2 }] }
"fields": [
{ "fieldId": "name", "row": 0, "colSpan": 4 },
{ "fieldId": "status", "row": 1, "colSpan": 2 },
{ "fieldId": "ownerId", "row": 1, "colSpan": 2 }
]
}
]
@ -526,10 +527,12 @@ The complete example below shows the logical aggregate shape. Split projects sto
"id": "details",
"title": "Details",
"isDefault": true,
"rows": [
{ "cells": [{ "fieldId": "name", "colSpan": 4 }] },
{ "cells": [{ "fieldId": "status", "colSpan": 2 }, { "fieldId": "budget", "colSpan": 2 }] },
{ "cells": [{ "fieldId": "startDate", "colSpan": 2 }, { "fieldId": "coverImage", "colSpan": 2 }] }
"fields": [
{ "fieldId": "name", "row": 0, "colSpan": 4 },
{ "fieldId": "status", "row": 1, "colSpan": 2 },
{ "fieldId": "budget", "row": 1, "colSpan": 2 },
{ "fieldId": "startDate", "row": 2, "colSpan": 2 },
{ "fieldId": "coverImage", "row": 2, "colSpan": 2 }
]
}
]

15
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/AbpDynamicSortingGuard.cs

@ -16,9 +16,11 @@ namespace Volo.Abp.Application.Services;
/// constrained to plain property or field access. Methods, comparisons, ternaries
/// and constants in the sort key are rejected with <see cref="AbpValidationException"/>.
/// Property-bag / shadow-property access through a constant string indexer
/// (e.g. <c>it["Prop"]</c>, <c>Data["Prop"]</c>) is treated as plain property access
/// and allowed, since it carries no side effects and is the canonical way to sort
/// dynamically-mapped entities.
/// (e.g. <c>it["Prop"]</c>, <c>Data["Prop"]</c>) is treated like plain property
/// access and allowed, because it is the canonical way to sort dynamically-mapped
/// entities. The guard assumes the matching indexer getter behaves like a property
/// getter; defining an indexer that performs IO or mutates state will expose those
/// effects through sorting.
/// </summary>
internal static class AbpDynamicSortingGuard
{
@ -88,9 +90,10 @@ internal static class AbpDynamicSortingGuard
protected override Expression VisitMethodCall(MethodCallExpression node)
{
// Allow property-bag / shadow-property access through a constant string
// indexer (it["Prop"], Data["Prop"], mainEntity["Prop"], ...). This is a
// pure read of a named member, not an arbitrary method invocation, so it
// does not open the injection surface the guard protects against.
// indexer (it["Prop"], Data["Prop"], mainEntity["Prop"], ...). The
// constant key cannot smuggle in an arbitrary method invocation, so this
// does not widen the injection surface the guard protects against; it
// treats the indexer access like ordinary property access.
if (IsConstantStringIndexer(node))
{
if (node.Object != null)

2
schemas/low-code/definitions/form-descriptor.schema.json

@ -34,7 +34,7 @@
},
"layout": {
"$ref": "form-layout-descriptor.schema.json",
"description": "Visual layout for the fields. Every layout cell fieldId must refer to a field in fields."
"description": "Visual layout for the fields. Every layout placement fieldId must refer to a field in fields."
},
"rules": {
"type": "array",

Loading…
Cancel
Save