CodamAIDocs
Themafertig

Die vier Fälle beim verschachtelten Schreiben

Ob ein Kindobjekt angelegt, geändert, nur verknüpft oder abgelehnt wird, entscheiden zwei Fragen: Hat es eine id? Ist das passende Flag gesetzt?

Ausprägungen
ohne id + CREATE → anlegenohne id ohne CREATE → 400mit id + UPDATE → mitändernmit id ohne UPDATE → nur verknüpfenunbekannte id → 404Listen bei PATCHRollen der KinderStrict Mode aus

Worum es geht

In einem Request kannst du nicht nur ein Objekt schreiben, sondern auch seine Kinder: die Objekte in seinen Beziehungsfeldern. Eine Firma mit neuen Mitarbeitern anlegen, eine Rechnung mit ihren Positionen ändern, einen Mitarbeiter einer bestehenden Abteilung zuordnen. Das heißt verschachteltes Schreiben.

Für jedes Kind im Request stellt CDMS zwei Fragen:

  1. Hat das Kind eine id?
  2. Erlaubt die Beziehung das Passende, also das Flag CREATE bzw. UPDATE?

Der Entscheidungsbaum

flowchart TB
    K["Kind im Request"] --> I{"hat eine id?"}
    I -->|nein| C{"Flag CREATE?"}
    C -->|ja| A1["1 · anlegen"]
    C -->|nein| A4["4 · abgelehnt: 400"]
    I -->|ja| E{"gibt es das Objekt?"}
    E -->|nein| A5["404"]
    E -->|ja| U{"Flag UPDATE?"}
    U -->|ja| A2["2 · mitändern"]
    U -->|nein| A3["3 · nur verknüpfen"]

Alle vier Fälle in einem Request

Eine Abteilung, deren Beziehung employees die Flags CREATE und UPDATE hat, und deren Beziehung location keine Flags hat:

PUT mit allen Fällen
Anfrage
PUT /api/rest/department/update/d1…
{
  "data": {
    "id": "d1…",
    "name": "IT",
    "employees": [
      { "firstname": "Ada", "lastname": "Lovelace" },
      { "id": "e2…", "firstname": "Alan", "lastname": "Turing" }
    ],
    "location": { "id": "l7…", "city": "Wiesbaden" }
  },
  "response": ["+"]
}
Was CDMS macht
Ada      → Fall 1: wird angelegt (kein id, CREATE)
Alan     → Fall 2: wird geändert (id, UPDATE)
location → Fall 3: wird nur verknüpft (id, kein UPDATE),
           "city" wird ignoriert

Hätte location ein Kind ohne id, wäre das Fall 4: location hat kein CREATE, die ganze Anfrage scheitert mit 400 recursive-create-not-allowed|location.

Die vier Fälle im Einzelnen

Ein Kind im Request

Wann: Kind ohne id, Beziehung mit CREATE.

  1. 1
    CDMS
    prüft die Anlegerolle des Kindmodells (oder eine Feldrolle am Beziehungsfeld)
  2. 2
    CDMS
    legt das Kind an: eigene id, _createdOn, Defaultwerte, CREATE-Regeln
  3. 3
    CDMS
    verbindet es mit dem Elternobjekt, beide Seiten

Ergebnis: Das Kind existiert und gehört zum Elternobjekt. Das gilt bei Create, PUT und PATCH gleich.

Wann: Kind mit id, Beziehung mit UPDATE.

  1. 1
    CDMS→Database
    sucht das Kind
  2. 2
    CDMS
    prüft die Änderungsrolle des Kindmodells (oder eine Feldrolle)
  3. 3
    CDMS
    ändert das Kind nach den Regeln des Verbs: bei Create und PUT ersetzt es das Kind, bei PATCH ändert es nur die gesendeten Felder
  4. 4
    CDMS
    verbindet es mit dem Elternobjekt

Ergebnis: Achtung bei PUT: { "id": "e2…" } allein leert alle Felder des Kindes, bei Pflichtfeldern kommt 422 employees[0].firstname cannot-be-null.

Wann: Kind mit id, Beziehung ohne UPDATE.

  1. 1
    CDMS→Database
    sucht das Kind
  2. 2
    CDMS→Client
    gibt es nicht → 404
  3. 3
    CDMS
    prüft, ob du das Kind lesen dürftest: Leserolle (oder Lese-Feldrolle) und Zeilenfilter
  4. 4
    CDMS→Client
    darfst du es nicht sehen → 404, als gäbe es die id nicht
  5. 5
    CDMS
    verbindet es mit dem Elternobjekt; weitere Felder des Kindes werden ignoriert

Ergebnis: Das Kind bleibt, wie es ist. Nur die Verbindung ist neu. Verlangt wird die Leseberechtigung des Kindes – nicht seine Änderungsrolle, denn das Kind ändert sich ja nicht.

Wann: Kind ohne id, Beziehung ohne CREATE.

  1. 1
    CDMS
    Flag CREATE fehlt
  2. 2
    CDMS→Client
    400 recursive-create-not-allowed|<feld>, nichts wird gespeichert

Ergebnis: So verhindert CDMS, dass über einen Verweis versehentlich neue Objekte entstehen.

Listen bei PATCH

In einer Liste gelten bei PATCH dieselben vier Fälle wie bei Create und PUT und wie bei einer Einzelreferenz. Anders ist nur, wie ein Kind mit UPDATE geändert wird: PATCH ändert nur die gesendeten Felder, PUT ersetzt das Kind.

Ein Listeneintrag bei PUT und bei PATCH
Create und PUTPATCH
Eintrag mit id, ohne UPDATEwird nur verknüpft, gesendete Felder werden ignoriertwird nur verknüpft, gesendete Felder werden ignoriert
Eintrag ohne id, ohne CREATE400 recursive-create-not-allowed|<feld>400 recursive-create-not-allowed|<feld>
Eintrag mit id, mit UPDATEKind wird ersetztnur die gesendeten Felder ändern sich

Entscheidungstabelle

Ergebnis je Kind (Strict Mode an)
idObjekt existiertFlagVerb, FeldartErgebnis
nein–CREATEalleanlegen
nein–kein CREATEalle400 recursive-create-not-allowed|<feld>
janein–Create, PUT (Einzelreferenz)404 missing-object|<id>|<feld>
janein–PATCH404 missing-object-for-field|<id>|<feld>
jajaUPDATEallemitändern (PUT ersetzt, PATCH ändert)
jajakein UPDATEallenur verknüpfen

Bei einem abstrakten Zielmodell braucht ein neues Kind zusätzlich @type, sonst weiß CDMS nicht, welchen Untertyp es anlegen soll. Fehlt er, kommt 400 missing-type-for-abstract-field mit dem Pfad des Feldes: bei PATCH …|mainPhone, bei Create und PUT …|data.mainPhone. Ein unbekannter Typ liefert 400 unknown-type-for-abstract-field|<pfad>|<typ>.

Rollen der Kinder

Jedes Kind, das CDMS anlegt, ändert oder löscht, wird mit den Rollen seines Modells geprüft. Eine Feldrolle am Beziehungsfeld kann die Rolle des Kindmodells ersetzen, aber nur für diesen Weg. Fehlt beides, scheitert die ganze Anfrage mit 403 missing-permission|<rolle>. Siehe Beziehungstypen und Recursive-Flags und Rechte auf Beziehungen (Feldrollen).

Strict Mode aus

Der Strict Mode ist der Standard: Was nicht erlaubt ist, wird mit einem Fehler abgelehnt. Eine Installation kann ihn abschalten. Dann lehnt CDMS weniger ab und lässt stattdessen weg:

FallStrict Mode anStrict Mode aus
neues Kind in einer Liste, kein CREATE400Eintrag wird übergangen
neues Kind als Einzelreferenz, kein CREATE400das Feld wird leer
Rolle des Kindes fehlt403 missing-permission|<rolle>403 missing-create-role / missing-update-role / missing-delete-role

Siehe Strict Mode: Fehler oder still ignorieren.

Fallen

Wie es weitergeht

Quellen im Code und in der Wissensdatenbank
  • CDMS/cdms-system-layer – AbstractLayer.setModel, recursiveCreate (Listen), recursiveUpdate (Listen), recursivePatch (Einzelreferenz, Listen), recursivePrepare (Rollen), enterField (Feldrollen)
  • CDMS/cdms-authorization – AbstractAuthorizationLayer (classAccess, fieldRole)
  • commons – RequestContext (STRICT_MODE)
  • CDMS/cdms-integrationtest – AbstractRecursiveCreate, AbstractRecursiveUpdate, AbstractRecursivePatch, AbstractUpdateTest, AbstractFieldRoleTest, AbstractRoleDenialTest, AbstractPatchListRecursionTest; Probe gegen Group, Department, Contact, SponsorInvoice
  • documentation/05-api-guide/07-verschachtelt-schreiben.md
Suchen