Hauptteil

Zugangskonzept

Die Zugriffe auf die WebAPI erfolgen auf Basis eines Benutzerkontos (NetDB-Konto) und eines zugeordneten Access Tokens. Um das Risiko der Kompromittierung eines NetDB-Kontos zu minimieren und mögliche Einsatzprofile besser strukturieren zu können, gibt es 2 Arten von NetDB-Benutzerkonten:

  • Hauptkonten (KIT-Benutzerkonten, primär im IDM verwaltet)
  • Unterkonten (primär in NetDB verwaltet; nicht im IDM vorhanden)

Über ein Konto werden die Zugriffsrechte der ihm zugeordneten Access Token abgebildet. Unterkonten sind ausschließlich für den direkten WebAPI-Zugang vorgesehen und benutzen statische Token; Hauptkonten sind zur direkten Nutzung des Web-Portals (NETVS) vorgesehen und benutzen temporäre (Session-)Token. Unterkonten existieren nur in der NetDB und können vom Inhaber eines Hauptkontos jederzeit nach eigenem Ermessen angelegt, modifiziert oder gelöscht werden. Jedem Unterkonto (und den zugehörigen Access Token) ist dadurch genau ein Hauptkonto zu- und übergeordnet. Ebenso kann der Inhaber des Hauptkontos im Rahmen seiner eigenen Rechte auch die Rechte seiner Unterkonten (Rollen, Untergruppen, ND-Modultypklassen, ND-Accessgruppen) verwalten. Zusätzlich kann ein Unterkonto als ‘Nur-Lese-Konto’ eingestellt werden. Dadurch ist der Zugriff auf datenmodifizierende WebAPI-Funktionen gesperrt. Diese Sperre hat Vorrang vor allen anderen Rechten und wirkt davon unabhängig. Auch diese Einstellung kann der Inhaber des Hauptkontos jederzeit für alle seine Unterkonten ändern.

Unterkonten haben eine funktionale Sperre für

  • die Anmeldung im NETVS (da sie kein Passwort haben)
  • sicherheitsrelevante Funktionen (Modifizierungen an Konten einschl. Rechte- bzw. Rollenzuordnungen)

Diese Sperre wirkt unabhängig davon, ob das Unterkonto tatsächlich die benötigten Rechte hat. Die gesperrten Funktionen können daher nur mittels Hauptkonto ausgeführt werden. Unterkonten dürfen nur ihre eigenen Access-Token modifizieren.

Gruppen und Konten für Bereichsbetreuer

Gruppen dienen der effizienten Zuordnung der Netzbereiche (Adressräume, Namensräume) zu Benutzerkonten. Einer Gruppe sind BCDs, Domains und Benutzerkonten zugeordnet. Die zugeordneten Benutzerkonten werden auch als Gruppenmitglieder bezeichnet. Den Gruppenmitgliedern sind somit Domains und BCDs zugeordnet. Analog zu den beiden Kontenarten gibt es auch 2 Arten der Gruppen:

  • Hauptgruppen (können nur Hauptkonten enthalten; können als KIT-Benutzergruppen primär im IDM oder primär in NetDB verwaltet werden)
  • Untergruppen (enthalten jeweils genau ein Hauptkonto des Eigentümers und können darüberhinaus nur dessen eigene Unterkonten enthalten; nur primär in NetDB verwaltet; nicht im IDM vorhanden)

Domain- und BCD- Zuordnungen in Untergruppen können nur im Rahmen vorhandener Zuordnungen ihrer Hauptgruppe bestehen.

  • Der Namensraum aller Gruppenmitglieder wird durch die Domains ihrer Gruppen definiert.
  • Der Adressraum aller Gruppenmitglieder wird durch die Subnetze der BCDs ihrer Gruppen definiert.

Hauptgruppen in der NetDB können in 2 Modi benutzt werden:

  • IDM-synchron: alle Gruppenmitglieder werden primär über die IDM-Gruppenverwaltung zugeordnet. Beim Synchronisationsvorgang wird der Stand der Gruppenmitglieder der IDM-Gruppe auf die NetDB-Gruppe übertragen. Wird der Name und/oder die Beschreibung der IDM-Gruppe (idm-seitig) geändert, wird diese Namensänderung beim nächsten Synchronisationsvorgang auch auf die NetDB-Gruppe übertragen.
  • nicht-IDM-synchron: alle Gruppenmitglieder werden primär in der NetDB verwaltet.

Wird ein KIT-Benutzerkonto einer Hauptgruppe im IDM zugeordnet, und möchte der Kontoinhaber eine eigene Untergruppe mit eigenen Unterkonten erstellen, kann er dies erst, nachdem die Hauptgruppe synchronisiert wurde (und die Gruppenmitglieder aktualisiert sind). Umgekehrt werden Untergruppen und deren Unterkonten automatisch aus einer Hauptgruppe entfernt, wenn auch ihr Hauptkonto aus der Hauptgruppe entfernt wurde (unabhängig davon, ob die Hauptgruppe IDM-synchron ist oder nicht). Die automatische Synchronisation erfolgt dabei nicht in Echtzeit, sondern stündlich für alle Gruppen. Sie kann aber auch jederzeit explizit für eine bestimmte Gruppe angefordert werden, um eine sofortige Synchronisation zu erreichen. Der Synchronisationsvorgang ist IDM-seitig nur-lesend; alle Schreibzugriffe erfolgen ausschließlich NetDB-seitig.

Gruppenadministration durch OE-Betreuer

Für die Gruppenadministration ist die Zuordnung eines Benutzerkontos zu einer Organisationseinheit (OE) erforderlich. Diese Zuordnung wird nicht vom IDM übernommen, sondern primär in der NetDB abgebildet. Der Inhaber des zugeordneten Kontos wird dadurch OE-Betreuer und bekommt das Administrationsrecht für alle Hauptgruppen, die seiner OE (oder einer darunterliegenden OE, dh. seinem OE-Teilbaum) zugeordnet sind. Ebenso bekommt er das Administrationsrecht für alle Domains und BCDs, deren OEs seinem OE-Teilbaum zugeordnet sind. Zusammengefasst:

  • Alle Netzbereiche (BCDs), die seinem OE-Teilbaum zugeordnet sind, bilden den Adressraum des OE-Betreuers.
  • Alle Domains, die seinem OE-Teilbaum zugeordnet sind, bilden den Namensraum des OE-Betreuers.
  • Die Mitgliedschaft des OE-Betreuerkontos in den Hauptgruppen des OE-Teilbaums ist davon unabhängig.

Das Administrationsrecht für Hauptgruppen, deren OE im eigenen OE-Teilbaum liegt, umfasst außerdem:

  • Eintragen neuer Gruppen
  • Ändern der Gruppenattribute (Name, OE, Beschreibung, IDM-Synchronisation)
  • Eintragen oder Löschen der Mitglieder
  • Eintragen der Domains, soweit sie dem eigenen OE-Teilbaum zugeordnet sind und
    • bei rekursiver Wirkung die Domain-OE gleich oder oberhalb der Gruppen-OE liegt
    • bei nicht-rekursiver Wirkung die Domain-OE gleich der Gruppen-OE ist
  • Eintragen der BCDs, soweit sie dem eigenen OE-Teilbaum zugeordnet sind und
    • bei rekursiver Wirkung die BCD-OE gleich oder oberhalb der Gruppen-OE liegt
    • bei nicht-rekursiver Wirkung die BCD-OE gleich der Gruppen-OE ist
  • Löschen der BCDs, Domains

Untergruppen werden ausschließlich durch ihre Eigentümer administriert.

Authentifizierung

WebAPI-Zugriffe (Requests) werden über ein token-basiertes Verfahren (OAuth 2.0 Bearer Token) authentifiziert. Dazu kann jedem Unterkonto ein oder mehrere sog. Access Token zugeordnet werden. Über diese Zuordnung erfolgt die Identifikation. Der WebAPI-Zugriff erfolgt also mit den Rechten des Kontos, das dem verwendeten Access Token zugeordnet ist. Das Token bzw. dessen Authentifizierungstext wird vom System (NetDB) automatisch generiert und ist sicherheitstechnisch wie ein Klartext-Passwort zu betrachten. Bitte beachten Sie auch die Sicherheitshinweise dazu.

Die Registrierung eines Tokens muss je nach Umgebung über die NETVS-Webseite

vorgenommen werden.

Ein Access Token umfasst folgende Hauptdaten:

  • Benutzerkennung des Kontos
  • Ablaufdatum (kann auch leer sein, falls Token unbegrenzt gültig sein soll). Token, deren Ablaufdatum überschritten sind, sind f Sie bleiben aber bestehen, bis das Löschdatum erreicht ist.
  • Löschdatum: Datum der endgültigen Löschung des Tokens. Wird bei jedem Zugriff automatisch verlängert (je nach Typ, s. dort)
  • zuletzt angemeldet: Datum des letzten Zugriffs, der mit diesem Token erfolgte
  • zuletzt generiert: Datum, wann der aktuell gültige Authentifizierungstext erzeugt wurde
  • Beschreibungstext: benutzerseitige Information, frei wählbar
  • Authentifizierungstext: das eigentliche Identifizierungsmerkmal des Benutzerkontos (systemgeneriert)
  • Typ, Art des Tokens:
    • statisch, Inaktivitätsintervall 200 Tage, nur für Unterkonten
    • temporär mit kurzem Inaktivitätsintervall (1 Stunde), nur für Hauptkonten
    • temporär mit langem Inaktivitätsintervall (1 Monat), nur für Hauptkonten
  • gpk: Globaler Primärschlüssel

Statische Token werden für den WebAPI-Zugriff der Unterkonten verwendet. Der Inhaber des Hauptkontos kann für statische Token seiner Unterkonten jederzeit einen neuen Authentifizierungstext vom System generieren lassen, ebenso kann er das Ablaufdatum und den Beschreibungstext jederzeit neu bestimmen oder das Token löschen. Wichtig: Löschbare Token werden täglich automatisch gelöscht. Das Löschdatum ist erreicht, wenn

  • das Ablaufdatum um 200 Tage überschritten ist
  • kein Ablaufdatum definiert ist und die letzte Benutzung (Login) älter als 200 Tage ist
  • das Token unbenutzt, kein Ablaufdatum definiert und das Erzeugungsdatum älter als 200 Tage ist

Eine Löschung (bspsw. selten genutzter Token) kann verhindert werden, indem rechtzeitig eine Re-Validierung durch z.B. einen Request mit leerer Transaktion ausgeführt wird.

Temporäre Token werden typischerweise für Web-Browser-Sessions der Hauptkonten verwendet. Sie werden nach Überschreiten des Ablaufdatums, maximal aber nach 1 Monat automatisch gelöscht. Bei Token mit kurzem Inaktivitätsintervall wird das Ablaufdatum mit jedem Zugriff um das festgelegte Intervall (1 Stunde) verlängert. Der Inhaber des Hauptkontos kann eigene temporäre Token jederzeit löschen; Änderungen an temporären Token sind gesperrt.

Hinweise zur Registrierung von Unterkonten

Wir empfehlen Ihnen aus Sicherheitsgründen (Schadensminimierung im Mißbrauchsfall):

  • für den WebAPI-Zugang nicht Ihr persönliches, ggf. sogar höher privilegiertes Benutzerkonto zu verwenden, sondern je nach Einsatzprofil ein oder mehrere Unterkonten mit den mindestnötigen Privilegien anzulegen und einzusetzen.
  • die Trennung der Einsatzprofile nach Nur-Lese-Zugriffen und Schreib-Lese-Zugriffen, um im ersten Fall Nur-Lese-Konten einzusetzen.

Sicherheitshinweise zur Token-Benutzung

Der Authentifizierungstext ist das Identifizierungsmerkmal des eindeutig zugeordneten Benutzerkontos. Der Besitzer des Authentifizierungstextes kann hierdurch WebAPI-Requests mit den Rechten des zugeordneten Kontos ausführen. Um einen Mißbrauch bzw. Kompromittierung zu vermeiden, beachten Sie bitte folgendes:

  • den Authentifizierungstext nur in einer Umgebung speichern, in der der Zugriff unberechtigter Dritter nach aktuellen Sicherheitsstandards ausgeschlossen ist.
  • für zeitlich begrenzte Einsatzprofile das Ablaufdatum im Voraus entsprechend einstellen (ein z.B. ‘vergessenes’ Token ist dadurch automatisch deaktiviert). Nach Überschreiten des Ablaufdatums kann das Token zwar nicht mehr benutzt werden, bleibt aber für weitere 200 Tage in der NetDB gespeichert. In dieser Zeit kann es durch Ändern der Ablaufdatums wieder freigeschaltet werden, ohne dass der Authentifizierungstext verändert werden muss.

URI-Schema

Alle Zugriffe (Requests) werden über URIs adressiert, deren Aufbau nach folgendem Schema erklärt wird:

  • Werte in spitzen Klammern sind Platzhalter
  • Werte in eckigen Klammern sind optional
  • großgeschriebene Platzhalter sind konstant; kleingeschriebene sind variabel
  • Beschreibungstext wird von Anführungszeichen "" umgeben
<BASE-URI>/<vmajor>.<vminor>/<sys>/<objtype>/<function>[<params>]

<BASE-URI>: https://api.netdb.scc.kit.edu       "Produktionsumgebung"
            https://api.netdb-test.scc.kit.edu  "Testumgebung (täglich veraltete Kopie der Produktionsumgebung)"
            https://api.netdb-devel.scc.kit.edu "Entwicklungsumgebung (unbestimmt veraltete Kopie der Produktionsumgebung mit Modifikationen)"

<vmajor>  : "natürliche Zahl, Hauptnummer der Version (Versionsreihe, Major Release)"
<vminor>  : "natürliche Zahl, Unternummer der Version innerhalb der Versionsreihe (Minor Release)"

<sys>     : "WebAPI-Systemname, Teilbereich von Anwendungsdaten (z.B. dns, nd)"
<objtype> : "WebAPI-Objekttyp-Bezeichnung (z.B. record, module, fqdn)"
<function>: "WebAPI-Funktion: Zugriffsart (z.B. create, update, delete, list)"

<params>  : "Parameterzeichenkette (query string) der Form ?<param1>=<value1>[&<param2>=<value2>[&...]]"

Alle rechtsseitig bzw. unterhalb von <BASE-URI> stehenden Platzhalter im URI-Schema sind demnach variabel. Ihre Wertebelegungen sind bei Versionswechseln als potentiell veränderbar zu betrachten und können daher versionsweise unterschiedlich sein. Eine Ausgabe der Wertebelegungen der variablen Platzhalter kann über Indexabfragen oder über die Ausgabe (list-Funktion) der Objekttypen /wapi/system, /wapi/object_type, /wapi/function erreicht werden.

Die Inhalte der drei angegebenen Datenbanken (Produktions-, Test- und Entwicklungsumgebung) sind für sich unabhängig voneinander, aber:

  • die Testdatenbank wird täglich nachts von der Produktionsdatenbank kopiert. Dort gemachte Änderungen sind also maximal für einen Tag sichtbar, weil sie anschließend wieder vom Stand der Produktionsdatenbank überschrieben werden.
  • Die Entwicklungsdatenbank wird in unregelmäßigen Abständen von der Produktionsdatenbank kopiert; zusätzlich sind dort Modifikationen im Rahmen der Weiterentwicklung möglich. Selbstverständlich gibt es hierbei keinerlei Garantien oder Support.

Deren Datenbestände sind also “Momentaufnahmen” der Produktionsdatenbank und grundsätzlich als veraltet anzusehen. Demnach müssen auch ggf. neue Konto- bzw. Token-Registrierungen, die sofort auch in Test- und Entwicklungsumgebung benötigt werden, dort separat vorgenommen werden.

Requests

Ein Request entspricht einer Datenbank-Transaktion.

Authentifizierung

Die Requests unterliegen grundsätzlich dem Zwang zur Authentifizierung. Davon ausgenommen sind Zugriffe, die ausschließlich auf den Systemdatenbereich erfolgen.

Authentifizierte Requests

Im HTTP-Header Authorization muss ein gültiges OAuth 2.0 Bearer Token übergeben werden. Muster des HTTP-Headers:

Authorization: Bearer ***AUTH-TOKEN-TEXT***

Bearer bezeichnet das Authentifizierungsschema; ***AUTH-TOKEN-TEXT*** ist der Authentifizierungstext des Access-Tokens. Zwischen beiden Angaben steht mindestens 1 Leerzeichen. Jedes Access-Token ist genau einem Benutzerkonto zugeordnet, dessen Rechte bei der Ausführung des Requests gelten.

Nicht-authentifizierte Requests

Der HTTP-Header Authorization wird nicht angegeben oder ist leer.

Unterstützte Methoden

Als HTTP-Request-Methoden können POST (generell) und GET (nur für nicht-datenmodifizierende Funktionen) verwendet werden. Als Zeichenkodierung wird ausschließlich UTF-8 verwendet. Zur Ablehnung des Requests führen:

  • Authentifizierungsfehler
  • nicht als UTF-8 dekodierbare Werte
  • Übergabe von Parametern, die die jeweilige Funktion nicht erwartet
  • Parameterwerte, deren JSON-Datenyp nicht mit dem JSON-Datentyp des Parameters übereinstimmt
  • Parameterwerte, die sich nicht in den zugehörigen Datentyp konvertieren lassen

POST-Request

Diese Methode bietet die volle Funktionalität und ist für alle Funktionsaufrufe verwendbar. Der Request Body muss ein gültiges JSON-Dokument sein und auch als solches deklariert sein (HTTP-Header: Content-Type:application/json). Ein ungültiges JSON-Dokument führt zur Ablehnung des Requests.

Requests als Einzelbefehls-Aufruf

Bei dieser Variante wird pro Request genau ein Objekt eines Objekttyps eines Systems mit einer Funktion behandelt. Sollen mehrere Objekte desselben Objekttyps und Systems mit derselben Funktion behandelt werden, ist pro Objekt ein separater Request erforderlich; es sei denn, die Funktion gestattet die Behandlung mehrerer Objekte gleichzeitig (Bulk-Funktion). URI-Schema unterhalb der Version:

/<sys>/<objtype>/<function>

Datenstruktur des Request Body:

Da System, Objekttyp und Funktion bereits im URI adressiert sind, besteht das JSON-Dokument nur aus einem JSON-Dict mit den Schlüsseln old, new mit JSON-Dicts für die jeweiligen Parameter-Wertebelegungen. old beinhaltet die jeweiligen Parameterwerte vor der Änderung; new diejenigen nach der Änderung:

{
  "old": {
    "<param_name>": <param_value>, ...
  },
  "new": {
    "<param_name>": <param_value>, ...
  }
}

Requests als Mehrfachbefehls-Aufruf / Ausgaben im relationalen Verbund (JOIN-Anweisung)

Pro Request können hier mehrere Befehle (Statements) mit jeweils unterschiedlichen Systemen, Objekttypen und Funktionen behandelt werden. URI-Schema unterhalb der Version:

/wapi/transaction/execute

Im Gegensatz zum Einzelbefehls-Aufruf sind System, Objekttyp und Funktion hier nicht im URI festgelegt, sondern werden im Request Body pro Statement angegeben. Bei diesem generischen Transaktionsaufruf können zusätzliche Steuerparameter in der Parameterzeichenkette übergeben werden:

  • dry_mode (Boolean-Typ)

    • Der Wert true gibt an, dass dieser Request (=Transaktion) nur als ‘Trockenlauf’ behandelt wird, d.h. alle Änderungen, die innerhalb des Requests stattfinden, werden zwar durchlaufen, aber an dessen Ende wieder verworfen (es erfolgt ein Datenbank-Transaktions-Rollback). Dieser Modus ist geeignet, um die Transaktion auf Fehler zu testen und daher nur sinnvoll, wenn datenmodifizierende Funktionen enthalten sind.
    • Der Wert false (Standardwert) bewirkt eine ‘echte’ Abarbeitung des Requests, d.h. bei Fehlerfreiheit werden alle Änderungen gespeichert und sind für nachfolgende Requests sichtbar.
  • dict_mode (Boolean-Typ, s.a. Antwort-Datenstruktur)

    • Der Wert true gibt an, dass die äußere Ebene des Antwort-JSON-Dokuments (Transaktionsebene) ein JSON-Dict ist. Dessen Schlüssel sind gleichlautend zum zugehörigen Statement-Index idx des Request Body.
    • Der Wert false (Standardwert) gibt an, dass die äußere Ebene des Antwort-JSON-Dokuments (Transaktionsebene) ein JSON-Array ist. Dessen Positionen sind gleichlautend zur zugehörigen Statement-Position des Request Body.
  • su_login_name (Text-Typ)

    • Gibt den Login-Namen des einzusetzenden Benutzerkontos an, unter dessen Rechten die Transaktion ausgeführt werden soll.
    • Diese Transaktion wird immer zurückgerollt (unabhängig davon, welchen Wert dry_mode hat). Man kann damit feststellen, ob die Transaktion fehlerfrei gelaufen wäre bzw. welche Daten das eingesetzte Konto sehen würde. Der Parameter darf nur mit Administratorrechten eingesetzt werden, dh. das authentifizierte Benutzerkonto ist Inhaber der Rolle cntl.master.

Datenstruktur des Request Body:

Da mehrere Statements möglich sind, besteht das JSON-Dokument aus einem äußeren JSON-Array, das die Transaktionsebene darstellt. Dieses enthält wiederum JSON-Dicts, welche jeweils ein Statement darstellen.

Der Schlüssel idx beinhaltet den Statement-Index, der eine eindeutige Bezeichung des Statements innerhalb der Transaktion ermöglicht. Der Statement-Index kann abweichend von der Statement-Position willkürlich vorgegeben/benannt werden; dh. er ist unabhängig von der Position. Er wird als Zielreferenz für JOIN-Anweisungen und Bezugsparameter sowie als Statement-Index im Antwort-JSON-Dokument (nur mit dict_mode = true, s. Antwort-Datenstruktur) verwendet. Wird die Position eines Statements, das eine Zielreferenz darstellt, verschoben (z.B. durch veränderte Anwendungslogik), müssen die Ziele der JOIN-Anweisungen bzw. Bezugsparameter folglich nicht verändert werden, da der Statement-Index unverändert bleiben kann. Wird kein Statement-Index angegeben, bekommt er automatisch die eigene Statement-Position. Diese ist immer 0-basiert, d.h. die Position des ersten JSON-Dicts (Statements) ist 0.

Pro Statement müssen neben der Parameter-Wertebelegung auch die jeweiligen Werte für System, Objekttyp und Funktion unter dem Schlüssel name explizit angegeben werden. Unter dem Schlüssel join kann optional ein Verbund mehrerer Statement-Ausgaben als JSON-Dict angegeben werden (nur, wenn die Statement-Position größer als 0 ist und nur bei Funktionen, die nicht datenmodifizierend sind).

Die Parameter-Wertebelegung kann in 2 Varianten erfolgen (s. nachfolgendes Schema):

  • Variante 1: statische Angabe der Parameterwerte unter old, new:

    • alte Werte: JSON-Dict unter old; Schlüssel sind die Parameternamen. Der Wert ist der alte Parameterwert.
    • neue Werte: JSON-Dict unter new; Schlüssel sind die Parameternamen. Der Wert ist der neue Parameterwert.
  • Variante 2: dynamische Angabe der Parameterwerte unter old_ref, new_ref:

    Die Parameterwerte werden zur Laufzeit aus den Rückgabewerten des vorhergehenden Bezugs-Statements mit dem angegebenen Statement-Index und dem angegebenem Parameternamen gewonnen. Die Funktion dieses Bezugs-Statements muss die folgenden Eigenschaften (Attribute des zugehörigen Funktionsobjektes im Systemdatenbereich) haben:

    • sie muss referenzierbar sein (is_returning_referenceable = true) ODER
    • sie muss rückgabefähig sein (is_returning = true) und zur Laufzeit
      • genau einen Ergebnisdatensatz als Antwort erzeugen oder
      • keinen Ergebnisdatensatz als Antwort erzeugen und allow_no_data ist true. In diesem Fall ist der gewonnene Parameterwert immer null.

    Der Bezugs-Parametername "<ref_param_name>" bezeichnet das gleichnamige Attribut im Ergebnisdatensatz des Bezugs-Statements mit dem Statement-Index "<ref_stmt_idx>". idx und param sind Pflichtangaben; allow_no_data ist optional (Standardwert ist false). Letzterer kann eingesetzt werden, wenn der Bezugs-Parameter nullbar ist und wenn die Möglichkeit besteht, dass das Bezugs-Statement keine Datensätze zurückgibt.

[
  {
    "idx": "<statement_index>",
    "name": "<system_name>.<object_type_name>.<function_name>",
    "old": {
      "<param_name>": <param_value>
    },
    "old_ref": {
      "<param_name>": { "idx": "<ref_stmt_idx>", "param": "<ref_param_name>", "allow_no_data": true | false }
    },
    "new": {
      "<param_name>": <param_value>
    },
    "new_ref": {
      "<param_name>": { "idx": "<ref_stmt_idx>", "param": "<ref_param_name>", "allow_no_data": true | false }
    },
    "join": {
      "<join_stmt_idx>": "<ref_constraint_name>" | "default" | null
    }
  }
]

Pro Statement und Parametername ist entweder Variante 1 oder Variante 2 verwendbar, d.h. ein Parametername darf nicht gleichzeitig als Schlüssel in old und old_ref oder in new und new_ref vorkommen.

Parameternamen sollten nur einmal pro Belegung vorkommen. Andernfalls werden Werte von Parameternamen (die mehrfach in derselben Belegung vorkommen) überschrieben, so dass nur einer dieser Werte für den Parameter übernommen wird. Dies kann zu unerwünschten Ergebnissen oder zur Ablehnung des Requests führen.

Ausgabe von Objekten relational verbundener Objekttypen im Statement-Verbund mit join

Um relevante Ausgabedaten referenzierender oder referenzierter Objekte zu erhalten und die Datenmenge besser einzugrenzen, kann die Ausgabe eines Nachfolger-Statements mit der Ausgabe eines oder mehrerer (nicht zwingend direkt) Vorgänger-Statements verbunden werden. Das Verfahren arbeitet in vergleichbarer Weise zu SQL-Joins. Verbund bedeutet dabei, dass zwischen den Objekttypen dieser beiden Statements eine Relation in Form eines referenzierenden Constraints besteht. Dabei werden nur diejenigen Objekte des Nachfolger-Statements ausgegeben, deren referenzierbare (bzw. referenzierte) Attributwerte zu denen des Vorgänger-Statements passen. Die Ausgabe des Vorgänger-Statements wird durch die JOIN-Anweisung somit nicht beeinflusst. Der Verbund wird dabei über den Index des Vorgänger-Statements und -außer im Globalverbund- den Namen des referenzierenden Constraints (s. Abschnitt Objekttypen) definiert. Das Nachfolger-Statement hat dabei einen Index > 0, und dessen Funktion ist nicht datenmodifizierend. Der Index des Vorgänger-Statements ist kleiner als der des Nachfolger-Statements. Im JSON-Dict des Schlüssels join ist <join_stmt_idx> der Index des Vorgänger-Statements, und "<ref_constraint_name>" (Wert zum Schlüssel) entweder der Constraint-Name, das Schlüsselwort "default" oder der Wert null, je nach Variante. Es gibt 2 Verbundvarianten:

  1. Constraint-basiert: Zwischen den Objekttypen des Vorgänger- und Nachfolger-Statements existiert ein referenzierender Constraint, der in der jeweiligen Objekttypdefinition unter referencing (seitens des Child-Objekttyps) oder referenced_by (seitens des Parent-Objekttyps) ausgewiesen ist. Der Constraint gehört somit entweder zum Objekttyp des Vorgänger- oder des Nachfolger-Statements; die Reihenfolge beider Statements kann also nach Bedarf frei gewählt werden. Ist der Constraint mit dem Attribut "is_join_default": false ausgewiesen, muss dessen Name im JSON-Dict des Schlüssels join als Wert für "<ref_constraint_name>" (zum Dict-Schlüssel <join_stmt_idx>) angegeben werden. Andernfalls ("is_join_default": true) kann dessen Name durch das Schlüsselwort "default" ersetzt werden.

    Im Nachfolger-Statement werden dadurch nur Objektdatensätze ausgegeben, die entsprechend des angegebenen Constraints zu Objekten des Vorgänger-Statements gehören. Die Zugehörigkeit der Objektdatensätze dieser beiden Verbund-Statements wird je nach JOIN-Operator über die Wertegleichheit/Zuordbarkeit der jeweiligen (Objekttyp-)Attribute des referenzierenden Constraints und des referenzierten Constraints hergestellt. (s.a. Beispiel)

    Self-Joins:

    Falls die Objekttypen des Vorgänger- und Nachfolger-Statements identisch sind, wird der referenzierende Constraint immer dem Nachfolger-Statement zugeordnet, dh. Nachfolger referenziert Vorgänger. Es können somit im Nachfolger-Statement nur Child-Datensätze des Vorgänger-Statements ausgegeben werden. Eine Umkehrung (Nachfolger ist Parent zu Vorgänger bzw. Nachfolger wird durch Vorgänger referenziert) ist bei Self-Joins nicht möglich.

  2. Global: Der Wert zum JOIN-Dict-Schlüssel <join_stmt_idx> ist null, da es in den beiden folgenden Varianten keinen Constraint zwischen den Objekttypen des Vorgänger- und Nachfolger-Statements gibt. Die Varianten unterscheiden sich nach der Reihenfolge der Statements bzgl. der Eigenschaft der Objekttypen als Datensenke (Child) oder Datenquelle (Parent):

    1. Child joins Parent: Der Objekttyp des Vorgänger-Statements (Parent) gehört zur Kategorie “Datenquelle” (DQ; Log- oder OT-Attribut-Datenquelle), und der Objekttyp des Nachfolger-Statements (Child) gehört zur Kategorie “Datensenke” (DS; Log- oder OT-Attribut-Datensenke). Diese Variante ist geeignet, um die zugeordneten Objekte der DS zur DQ herauszufinden. Hierzu ist seitens der Datenquelle (Vorgänger-Stmt.) Lesezugriff für die betreffenden Objekte erforderlich. Der Lesezugriff auf die zugehörigen Attributdaten wird automatisch daraus abgeleitet.

      Beispiele:

      • zu einem oder mehreren Objekten (DQ) die Log-Einträge (z.B. nach Top-N) anzeigen
      • zu einem oder mehreren Objekten (DQ) die Objektattribute (z.B. nach Attributschlüssel oder -wert) anzeigen
    2. Parent joins Child: Der Objekttyp des Vorgänger-Statements (Child) gehört zur Kategorie “Datensenke” (DS; Log- oder OT-Attribut-Datensenke), und der Objekttyp des Nachfolger-Statements (Parent) gehört zur Kategorie “Datenquelle” (DQ; Log- oder OT-Attribut-Datenquelle). Diese Variante ist geeignet, um z.b. herauszufinden, welche Objektdaten der DS welchen Objekten der DQ zugeordnet sind. Hierzu ist DS-seitig (Vorgänger-Stmt.) globaler Lesezugriff erforderlich.

      Beispiele:

      • welche Log-Einträge (z.B. nach Zeitraum oder Kategorie oder User) sind welchen Objekten (DQ) zugeordnet
      • welche Attribute (z.B. nach Attributschlüssel oder -wert) sind welchen Objekten (DQ) zugeordnet

    Im Nachfolger-Statement werden alle Datensätze ausgegeben, die entsprechend der übereinstimmenden Datenart (z.B. Log, OT-Attribut) zu Objekten des Vorgänger-Statements gehören. Die Zugehörigkeit der Objektdatensätze dieser beiden Verbund-Statements wird über die Wertegleichheit des Attributs object_gfk (DS-seitig) und des Attributs gpk (DQ-seitig) hergestellt.

Alle Schlüssel-Wert-Paare, die im JOIN-Dict vorhanden sind, werden funktional logisch-UND verknüpft.

GET-Request

Diese Methode kann nur für nicht-datenmodifizierende Funktionen als Einzelbefehls-Aufruf verwendet werden. Im Funktionsindex sind diese durch das Attribut is_data_manipulating mit dem Wert false gekennzeichnet. Die Parameterzeichenkette (query string) entspricht hierbei der Belegung unter old im Parameterverzeichnis des Funktionsindex. Da die Parameterzeichenkette kein JSON-Format hat, werden die Parameterwerte nach JSON konvertiert; d.h. der Parameterwert wird als JSON-Literal betrachtet und daraus der entsprechende JSON-Datentyp abgeleitet. Dabei ergeben sich folgende Besonderheiten:

  • Parameterwerte der JSON-Datentypen string oder number werden gleichwertig betrachtet
  • Parameterwerte des JSON-Datentyps boolean sind als Zeichenkette true oder false zu übergeben
  • null kann nicht verwendet werden, da es als eigener JSON-Datentyp existiert und keine Unterscheidung zum Typ string möglich ist

Alle Parameterwerte haben durchweg auswählenden Charakter und werden typischerweise logisch-UND verknüpft. Elemente in Parameterwerten des JSON-Datentyps array werden typischerweise logisch-ODER verknüpft. Parameternamen dürfen nur einmal in der Parameterzeichenkette vorkommen; andernfalls werden deren Werte als Array gepackt übergeben und dadurch fälschlicherweise als Array-Literal interpretiert, was zu unerwünschten Ergebnissen oder zur Ablehnung des Requests führen kann. Parameterwerte, die reservierte URI-Zeichen enthalten, müssen kodiert werden (Stichworte ‘Prozentkodierung’, ‘URL-Encoding’, s.a. https://de.wikipedia.org/wiki/URL-Encoding).

Antwortverhalten der Funktionen

Es gibt 2 Kriterien, nach denen das Antwortverhalten eingeteilt wird:

  1. Rückgabefähigkeit: darunter wird die Eigenschaft einer Funktion verstanden, ihre Ergebnisdaten als nicht-leere oder leere Antwort zurückzugeben. Trifft dies nicht zu, wird garantiert eine leere Antwort zurückgegeben. (s. Funktionsattribut is_returning)

  2. Referenzierbarkeit: darunter wird die Eigenschaft einer Funktion verstanden, garantiert eine nicht-leere Antwort mit genau einem Ergebnisdatensatz zurückzugeben. Dadurch ist sie referenzierbar, dh. sie speichert den Ergebnisdatensatz für die Dauer der Transaktion, so dass er von nachfolgenden Funktionen innerhalb derselben Transaktion als Eingabewert verwendet (referenziert) werden kann. (s. Funktionsattribut is_returning_referenceable)

Nicht-datenmodifizierende Funktionen (s. Funktionsattribut is_data_manipulating) sind typischerweise immer rückgabefähig, aber nicht referenzierbar und geben im Normalfall an ihrem Statement-Index ein JSON-Array zurück, das die Ergebnisdatensätze entsprechend des angeforderten Objekttyps und der Abfragekriterien (auswählende Eingabeparameter) enthält. Bei Nichtzutreffen der Abfragekriterien bzw. falls keine übereinstimmenden Daten des Objekttyps vorhanden sind, wird eine leere Liste (leere Antwort) zurückgegeben. Die Referenzierbarkeit ist hier dynamisch und hängt von der Anzahl der Objekttyp-Datensätze in der Funktionsantwort des betreffenden Statement-Index ab. Falls genau 1 Objekt-Datensatz zurückgegeben wird, ist die Funktion an diesem Statement-Index dadurch automatisch referenzierbar (analoges Verhalten zu referenzierbaren Funktionen). Durch die Abfrage von Schlüsselparametern eines Objekttyps (zugeordnete Constraint-Typen: Primärschlüssel (p) oder Schlüssel (u)) kann hier die Referenzierbarkeit vorbestimmt werden (Schlüsselparameter erzwingen genau einen Objekt-Datensatz, falls er existiert.)

Antwort-Datenstruktur bei fehlerfreier Transaktion

Die Antwort ist immer ein JSON-Dokument mit dem Aufbau (von außen nach innen) in den folgenden 2 Varianten, je nachdem, wie dict_mode gesetzt ist:

  1. dict_mode = false (Standard):

    • JSON-Array: Transaktionsebene; enthält die Statement-Ebene mit den JSON-Arrays der Funktions-Antworten in der Reihenfolge der Statements aus dem Request Body. Die Statement-Position ist immer 0-basiert, d.h. das erste Statement hat die Position 0 (und, falls nicht vorgegeben, den Index “0”).
    • JSON-Array: Statement-Ebene; enthält die Objektebene mit den JSON-Dicts der Funktions-Antwort
    • JSON-Dict: Ergebnisdatensatz (Objekt), dessen Schlüssel bzw. Keys gleichlautend zu den Attributnamen (aus der Objekttyp-Struktur) sind
  2. dict_mode = true:

    • JSON-Dict: Transaktionsebene; enthält die Statement-Ebene mit den JSON-Arrays der Funktions-Antworten. Die Statements der Transaktionsebene sind entsprechend des Statement-Index des Request Body indiziert.
    • JSON-Array: Statement-Ebene; enthält die Objektebene mit den JSON-Dicts der Funktions-Antwort
    • JSON-Dict: Ergebnisdatensatz (Objekt), dessen Schlüssel bzw. Keys gleichlautend zu den Attributnamen (aus der Objekttyp-Struktur) sind

Antwort-Datenstruktur im Fehlerfall (Exception, Transaktionsabbruch)

Zusätzlich zum HTTP-Statuscode (4xx) wird ein JSON-Dict zurückgegeben, dessen (einziger) Key exception wiederum ein Dict mit der Struktur des Objekttyps wapi.exception enthält. Muster:

{
  "exception": {
    "error": {
      "code": number,
      "description": "text",
      "details": "text"
    },
    "error_type": {
      "code": number,
      "name": "text",
      "description": "text"
    },
    "constraint": {
      "name": "text",
      "description": "text"
    },
    "others": {},
    "stacked_diag_params" {
      "column": "text",
      "constraint": "text",
      "context": "text",
      "datatype": "text",
      "detail": "text",
      "dml_src_table": "text",
      "hint": "text",
      "message": "text",
      "schema": "text",
      "sqlstate": "text",
      "table": "text"
    },
    "traceback": [
      {
        "function": "text",
        "param": {
          "<param_name1>": <param_value1>,
          "<param_name2>": <param_value2>,
          ...
        }
      },
      ...,
      {
        "function": "wapi_3_1.exec_ta_handler",
        "param": {
          "wapi.transaction_stmt.index": number
        }
      }
    ]
  }
}
  • Die Keys der JSON-Dicts error und error_type entsprechen den gleichnamigen Objekttypen und deren Attribute im System cntl.
  • stacked_diag_params enthält interne Informationen zur Fehlerbehebung (Debugging).
  • constraint mit name und description sagt verbal aus, gegen welche Bedingung verstoßen wurde.
  • traceback enthält eine Liste (JSON-Array) entsprechend der Funktionsaufruffolge und der jeweiligen Parameternbelegung mit Parametername und -Wert. Der letzte Eintrag wapi.transaction_stmt.index sagt aus, welches Statement der Transaktion die Exception verursacht hat.
  • others ist nur im Fall nicht-zuordbarer Fehler (unbehandelte Exceptions) belegt.

Indexabfragen

Die Indexabfragen erlauben es, die gültigen Wertebelegungen der jeweils nächsten Unterebene des URI-Schemas festzustellen. Optional kann der endende Schrägstrich / (Slash) angehängt werden, optional gefolgt vom Schlüsselwort index; dies hat aber keine Auswirkungen und dient nur der Rückwärtskompatibilität bzw. Lesbarkeit. Indexabfragen sind parameterlos. Intern sind sie eine Weiterleitung auf den entsprechenden Objekttyp im Systemdatenbereich unter /wapi.

Für die 4 Unterebenen gilt folgendes allgemeines Schema:

Versionsindex : <BASE-URI>
Systemindex   : <BASE-URI>/<vmajor>.<vminor>
Objekttypindex: <BASE-URI>/<vmajor>.<vminor>/<sys>
Funktionsindex: <BASE-URI>/<vmajor>.<vminor>/<sys>/<objtype>

Dazu die äquivalenten Systemdatenabfragen entsprechend der internen Weiterleitung (außer Versionsindex):

Systemindex   : <BASE-URI>/<vmajor>.<vminor>/wapi/system/list
Objekttypindex: <BASE-URI>/<vmajor>.<vminor>/wapi/object_type/list?system_list=["<sys>"]
Funktionsindex: <BASE-URI>/<vmajor>.<vminor>/wapi/function/list?system_list=["<sys>"]&object_type_list=["<objtype>"]

Beispiele:

Abfragen der Systemdaten

Für den Systemdatenbereich ist das Spezial-System /wapi vorgesehen. Zugriffe auf diesen Bereich dürfen auch ohne Authentifizierung erfolgen. Unterhalb dieses Systems sind Basis-Objekttypen für

  • Systeme
  • Objekttypen
  • Funktionen und deren Zuordnungen zu Parametern bzw. Objekttyp-Attributen
  • Objekttyp für Transaktionsaufrufe
  • Objekttyp für Exceptions

definiert. Diese liefern Informationen über alle weiteren Systeme, Objekttypen und Funktionen.

Allgemeine Objekttyp-Datenstruktur

Jeder Objekttyp wird nach folgendem Schema dargestellt:

{ 
  "attributes": {
    "<attribute_name>": {
      "data_type": "<api_datatype_name>",
      "description_detail": "detaillierter Beschreibungstext des Attributes",
      "description_obj_type_scope": "objekttyp-weite Beschreibung des Attributes",
      "description_sys_scope": "system-weite Beschreibung des Attributes",
      "is_core": true | false,
      "is_deprecated": true | false,
      "is_nullable": true | false,
      "supported_values": {
        "<value>": "<value_description>"
      }
    }
  },
  "constraints": {
    "<constraint_name>": {
      "attributes": [ "<attribute_name>" ],
      "description": "Beschreibungstext des Constraints",
      "errors": [
        {
          "code": <error_code>,
          "type": <error_type_code>,
          "description": "<error_description>",
          "details": "<error_details>"
        }
      ],
      "grants_read_access": true | false,
      "internal_name": "systeminterner Name des Constraints",
      "is_deferred": true | false,
      "type": "<constraint_type>"
    }
  },
  "description_abbrev": "Abkürzung des Objekttyps",
  "description_detail": "ausführlicher Beschreibungstext des Objekttyps",
  "description_title": "Titeltext des Objekttyps",
  "fq_name": "<system_name>.<object_type_name>",
  "is_log_dst": true | false,
  "is_log_src": true | false,
  "is_otattr_dst": true | false,
  "is_otattr_src": true | false,
  "name": "<object_type_name>",
  "referenceable": {
    "<constraint_name>": {
      "attributes": [ "<attribute_name>" ],
      "is_deferred": true | false,
      "referenced_by": [ {"system": "<system_name>", "object_type": "<object_type_name>", "name": "<constraint_name>", "is_join_default": true | false} ],
      "type": "<constraint_type>"
    }
  },
  "referencing": {
    "<constraint_name>": {
      "attributes": [ "<attribute_name>" ],
      "grants_read_access": true | false,
      "is_deferred": true | false,
      "is_join_default": true | false,
      "on_delete": "raise" | "cascade" | "set null" | "set default",
      "references": {"system": "<system_name>", "object_type": "<object_type_name>", "name": "<constraint_name>"}
    }
  },
  "system": "<system_name>"
}

Bedeutung der Platzhalter (Variablen)

  • <system_name>: System-Name
  • <object_type_name>: Objekttyp-Name
  • <attribute_name>: Attribut-Name
  • <api_datatype_name>: Datentyp-Name des Attributs (Name auf API-Ebene)
  • <json_datatype_name>: Datentyp-Name des Attributs (Name auf JSON-Ebene), Wertebereich:
    • object
    • array
    • string
    • number
    • boolean
    • json (allgemein; kann ein beliebiger der vorgenannten JSON-Datentypen sein)
  • <constraint_name>: Constraint-Name
  • <constraint_type>: Constraint-Typ
  • <value>: erlaubter Attributwert
  • <value_description>: Erläuterung zu diesem Wert
  • <error_code>: numerischer Fehlercode
  • <error_type_code>: numerischer Fehlertypcode (negativ)
  • <error_description>: Fehlerbeschreibungstext
  • <error_details>: detaillierter Fehlertext

Bedeutung der Bezeichner (Konstanten)

  • “system”: Name des Systems, dem der Objekttyp zugeordnet ist
  • “name”: Objekttypname innerhalb eines Systems
  • “fq_name”: vollqualifizierter (systemqualifizierter) Objekttypname
  • “is_log_dst”: Objekttyp ist Log-Datensenke (DS; empfängt und hält Log-Daten)
  • “is_log_src”: Objekttyp ist Log-Datenquelle (DQ; erzeugt Log-Daten und sendet diese zur Log-Datensenke)
  • “is_otattr_dst”: Objekttyp ist OT-Attribut-Datensenke (DS; empfängt und hält relationale Objektyp-Attribute)
  • “is_otattr_src”: Objekttyp ist OT-Attribut-Datenquelle (DQ; erzeugt relationale Objektyp-Attribute und sendet diese zur OT-Attribut-Datensenke)
  • “description_abbrev”: Abkürzung des Objekttyps
  • “description_detail”: ausführlicher Beschreibungstext des Objekttyps
  • “description_title”: Titeltext des Objekttyps
  • “constraints”: Constraints (Datenintegritäts- und Prüfbedingungen) des Objekttyps und ggf. zugeordnete Fehlermeldungen.

    • “type”: Constraint-Typ. Wertebereich:
      • “U”: Schlüssel/Unique Key, referenzierbar. Es ist garantiert, dass die enthaltenen Attribute genau ein Objekt unter allen Objekten desselben Typs identifizieren. Darüber kann dieses Objekt angesprochen bzw. referenziert werden.
      • “UP”: wie “U”, enthält die veränderlichen Primärattribute des Objekts (existiert genau einmal pro Objekttyp). Unterscheidungsmerkmal gegenüber “P”: die UP-Attribute sind veränderlich.
      • “P”: Primärschlüssel/Primary Key (wie “U”, existiert genau einmal pro Objekttyp). Die Attribute eines Primärschlüssels sind garantiert unveränderlich, d.h. solange ein Objekt existiert, wird sich sein Primärschlüssel nicht ändern. (Unterscheidungsmerkmal gegenüber “UP”)
      • “X”: Ausschlußbedingung zur Verhinderung von Duplikaten unter bestimmten Bedingungen
      • “F”: Fremdschlüssel/Foreign Key, referenzierend, Merkmal der referentiellen Datenintegrität. Die enthaltenen Attribute sind eine Bezugnahme zu denen im referenzierten Schlüssel oder Primärschlüssel. Dabei ist garantiert, dass zu einem referenzierenden Objekt (child) ein referenziertes Objekt (parent) existiert. Der Bezug wird über die jeweilige Reihenfolge der Attribute hergestellt, d.h. das enthaltene (referenzierende) Attribut an einer Position ist dem referenzierten Attribut (des Schlüssels oder Primärschlüssels) an derselben Position zugeordnet. Beide Attribute sind dabei wertgleich und nicht null. Ist ein Attribut null, gilt die garantierte Bezugnahme nicht.
      • “FN”: Funktionsbasierte Referenz, referenzierend (aber kein Merkmal der referentiellen Datenintegrität) Die enthaltenen Attribute sind eine funktionale Bezugnahme zu denen im referenzierten Schlüssel oder Primärschlüssel.
      • “C”: einfache Prüfbedingung
      • “T”: Trigger (Komplexeres Prüfprogramm)
    • “grants_read_access”: bei Benutzung des Constraints im Statement-Verbund (JOIN) wird Lesezugriff auf die beteiligten Objekttypen gewährt, dh. durch den JOIN werden evtl. bestehende Einschränkungen der Leserechte aufgehoben (falls true).
    • “is_deferred”: Constraint wird am Ende der Transaktion validiert (true), bzw. pro Statement validiert (false). Dadurch ist es möglich, die geforderte Bedingung durch verschiedene Statements innerhalb der Transaktion zu ignorieren, solange sie am Transaktionsende wieder erfüllt ist.
    • “is_join_default”: wird als Standard-Constraint bei JOIN-Anweisungen eingesetzt, falls das Schlüsselwort “default” angegeben wurde
    • “internal_name”: systeminterner Name des Constraints; kann als Bezugnahme zur Constraint-Angabe unter stacked_diag_params im Exception-Objekt verwendet werden.
    • “description”: Beschreibung der Bedingung, die durch den Constraint garantiert bzw. erzwungen wird
    • “errors”: JSON-Array der JSON-Dicts der zugeordneten Fehler
      • “code”: Fehlernummer
      • “type”: Fehlertypnummer
      • “description”: Fehlerbeschreibung
      • “details”: Fehler-Details
  • “attributes”: JSON-Dict, dessen Schlüssel die Attribute des Objekttyps sind

    • “data_type”: Datentyp-Name auf API-Ebene. Eine vollständige Übersicht aller Datentyp-Attribute ist im Objekttyp cntl.data_type zu finden.
    • “description_detail”: detaillierter Beschreibungstext des Attributes
    • “description_obj_type_scope”: kurze Bezeichnung des Attributes, die sich auf eine objekttyp-weite Sichtweise bezieht
    • “description_sys_scope”: kurze Bezeichnung des Attributes, die sich auf eine system-weite Sichtweise bezieht
    • “is_core”: eigenes, primär zugehöriges Attribut (Kern-Attribut) des Objekttyps (true). Es können auch Attribute anderer Objekttypen oder weitere Daten angegeben werden (false).
    • “is_deprecated”: Attribut wird in neueren Versionen nicht mehr unterstützt (true) bzw. weiterhin unterstützt (false).
    • “is_nullable”: Das Attribut darf den Wert null haben (true) bzw. nicht haben (false).
    • “supported_values”: erlaubte Werte für dieses Attribut. Nur vorhanden, wenn zutreffend. Unabhängig vom tatsächlichen Datentyp muss die Darstellung des <value> als Text erfolgen, da JSON-Keys nur als Text dargestellt werden können.
  • “referencing”: JSON-Dict, dessen Schlüssel die referenzierenden Constraint-Namen (child-seitig) sind
    • “attributes”: JSON-Array der Attribute des bezeichneten Constraints
    • “is_deferred”: Constraint wird am Ende der Transaktion validiert (true), bzw. pro Statement validiert (false)
    • “is_join_default”: wird als Standard-Constraint bei JOIN-Anweisungen eingesetzt, falls das Schlüsselwort “default” angegeben wurde
    • “on_delete”: Aktion, die beim Löschen des referenzierten (parent-seitigen) Datensatzes ausgeführt wird. Mögliche Werte:
      • “raise”: Exception werfen
      • “cascade”: kaskadiert löschen (in Folge werden auch alle referenzierenden Datensätze gelöscht)
      • “set null”: Fremdschlüssel aller referenzierenden Datensätze wird null gesetzt
      • “set default”: Fremdschlüssel aller referenzierenden Datensätze wird auf den internen Standardwert gesetzt
    • “references”: JSON-Dict des referenzierten Constraints (parent-seitig) mit den Schlüsseln
      • “name”: Constraint-Name
      • “object_type”: Objekttyp-Name des Constraints
      • “system”: System-Name des Objekttyps des Constraints
  • “referenceable”: JSON-Dict, dessen Schlüssel die referenzierbaren Constraint-Namen sind (s. Constraint-Typ “U”, “UP” oder “P”)
    • “attributes”: JSON-Array der Attribute des bezeichneten Constraints. Über die Werte dieser Attribute kann ein Objekt dieses Objekttyps eindeutig identifiziert werden.
    • “is_deferred”: Constraint wird am Ende der Transaktion validiert (true), bzw. pro Statement validiert (false)
    • “referenced_by”: Liste der JSON-Dicts aller referenzierenden Constraints. Umgekehrte Darstellung zu “referencing”, aber aus Sicht des referenzierten Objekttyps (parent). Ein Dict hat die Schlüssel
      • “name”: Constraint-Name
      • “object_type”: Objekttyp-Name des Constraints
      • “system”: System-Name des Objekttyps des Constraints
      • “is_join_default”: wird als Standard-Constraint bei JOIN-Anweisungen eingesetzt, falls das Schlüsselwort “default” angegeben wurde
    • “type”: Constraint-Typ. Wertebereich: wie oben “type” unter “constraints”.

Beispiel

Allgemeine Funktions-Datenstruktur

Parameter bzw. Objekttyp-Attribute, die nicht-ausführbaren Funktionen zugeordnet sind, sind nur im Objekttypindex, aber nicht im Funktionsindex sichtbar. Jede ausführbare Funktion eines Objekttyps wird nach folgendem Schema dargestellt:


{
  "fq_name": "<system_name>.<object_type_name>.<function_name>",
  "is_data_manipulating": true | false,
  "is_executable": true | false,
  "is_returning": true | false,
  "is_returning_referenceable": true | false,
  "name": "<function_name>",
  "object_type": "<object_type_name>",
  "parameters": {
    "<parameter_name>": {
      "data_type": "<api_datatype_name>",
      "description_detail": "detaillierter Beschreibungstext des Parameters",
      "description_obj_type_scope": "objekttyp-weite Beschreibung des Parameters",
      "description_sys_scope": "system-weite Beschreibung des Parameters",
      "is_deprecated": true | false,
      "new": {
        "data_default": <default_value>,
        "is_nullable": true | false,
        "is_required": true | false
      },
      "old": {
        "data_default": <default_value>,
        "is_nullable": true | false,
        "is_required": true | false
      },
      "supported_values": {
        "<value>": "<value_description>"
      }
    }
  },
  "system": "<system_name>"
}

Bedeutung der Platzhalter (Variablen)

  • <system_name>: System-Name
  • <object_type_name>: Objekttyp-Name
  • <function_name>: Funktions-Name
  • <parameter_name>: Parameter-Name (bei Gleichnamigkeit zu Objekttyp-Attributnamen sind beide identisch)
  • <api_datatype_name>: Datentyp-Name des Attributs (Name auf API-Ebene)
  • <json_datatype_name>: Datentyp-Name des Attributs (Name auf JSON-Ebene), Wertebereich:
    • object
    • array
    • string
    • number
    • boolean
    • json (allgemein; kann ein beliebiger der vorgenannten JSON-Datentypen sein)
  • <value>: erlaubter Parameterwert
  • <value_description>: Erläuterung zu diesem Wert
  • <default_value>: Standardwert. Wird automatisch eingesetzt, wenn nicht null und wenn der Parameter in der jeweiligen Belegung nicht angegeben wurde.

Bedeutung der Bezeichner (Konstanten)

  • “system”: Name des Systems, dem der Objekttyp der Funktion zugeordnet ist
  • “object_type”: Name des Objekttyps der Funktion
  • “fq_name”: vollqualifizierter (system- und objekttyp-qualifizierter) Funktionsname
  • “is_data_manipulating”: modifizierende/datenschreibende Funktion (true) oder nur-datenlesende Funktion (false)
  • “is_executable”: Funktion ist ausführbar und kann damit in einer Transaktion angewendet werden
  • “is_returning”: Funktion ist rückgabefähig, dh. sie kann eine nicht-leere Antwort zurückgeben
  • “is_returning_referenceable”: Funktion gibt garantiert eine nicht-leere Antwort mit genau einem Ergebnisdatensatz zurück und ist dadurch für Parameternamen referenzierbar (hängt nicht mit Constraint-Referenzierung zusammen)
  • “name”: Funktionsname innerhalb eines Systems und Objekttyps
  • “parameters”: JSON-Dict, dessen Schlüssel die Funktionsparameter sind. Bei Gleichnamigkeit zu einem Attribut des Objekttyps entspricht der Parameter diesem Attribut.
    • “data_type”: Datentyp-Name auf API-Ebene. Eine vollständige Übersicht aller Datentyp-Attribute ist im Objekttyp cntl.data_type zu finden.
    • “description_detail”: detaillierter Beschreibungstext des Parameters
    • “description_obj_type_scope”: kurze Bezeichnung des Parameters, die sich auf eine objekttyp-weite Sichtweise bezieht
    • “description_sys_scope”: kurze Bezeichnung des Parameters, die sich auf eine system-weite Sichtweise bezieht
    • “is_deprecated”: Parameter wird in neueren Versionen nicht mehr unterstützt (true) bzw. weiterhin unterstützt (false).
    • “old”: Wertebelegung für den Zustand vor der Datenmodifikation (Altbelegung). Nur vorhanden, wenn zutreffend.
      • “data_default”: Standardwert, der in dieser Belegung eingesetzt wird, falls der Parameter nicht angegeben wurde. Erscheint nur, wenn der Standardwert nicht null ist.
      • “is_nullable”: Der Parameter darf in dieser Belegung den Wert null haben (true) bzw. nicht haben (false).
      • “is_required”: Der Parameter muss in dieser Belegung verwendet werden (true) bzw. kann weggelassen werden (false)
    • “new”: Wertebelegung für den Zustand nach der Datenmodifikation (Neubelegung). Nur vorhanden, wenn zutreffend.
      • “data_default”: Standardwert, der in dieser Belegung eingesetzt wird, falls der Parameter nicht angegeben wurde Erscheint nur, wenn der Standardwert nicht null ist.
      • “is_nullable”: Der Parameter darf in dieser Belegung den Wert null haben (true) bzw. nicht haben (false).
      • “is_required”: Der Parameter muss in dieser Belegung verwendet werden (true) bzw. kann weggelassen werden (false)
    • “supported_values”: erlaubte Werte für diesen Parameter. Nur vorhanden, wenn zutreffend. Unabhängig vom tatsächlichen Datentyp muss die Darstellung des <value> als Text erfolgen, da JSON-Keys nur als Text dargestellt werden können.

Je nach Funktion ist die Wertebelegung für old und/oder new definiert; mindestens aber eine davon. Die jeweils nicht definierte Wertebelegung wird weggelassen. Für Nur-Lesefunktionen ist immer die Altbelegung definiert.

Beispiel

Versionsangaben

Die explizite Versionsangabe aller Zugriffe ermöglicht es, neue Features schnell einzuführen, ohne Clients, die eine bestehende Version benutzen, auszusperren oder auf deren Versionsanpassung zu warten. Die Hauptnummer wird bei umfangreichen API-Änderungen erhöht, die Anpassungen bei den meisten Clients erfordern würden; die Unternummer bei solchen, die die meisten Clients nicht betrifft.

Beide Versionsangaben (<vmajor>, <vminor>) sind numerisch (natürliche Zahl). Um den Status einer Version zu kennzeichnen, gibt es neben der numerischen Versionsangabe (Standard-Angabe) auch eine semantische Angabe. Sie bezieht sich auf die Version der internen Schnittstelle zwischen WebAPI und der darunterliegenden Datenbank (NetDB). Die Versionsangabe bei Requests kann nur numerisch sein. Beispiele für den Status einer Version (semantische Versionsangaben):

  • alpha: Entwicklung
  • beta: Testbetrieb für begrenzten Anwenderkreis freigegeben
  • rc: Veröffentlichungskandidat (release candidate), abschließende Testversion
  • release: aktuelle Version
  • oldrelease: veraltete Version (Vorgänger der aktuellen Version)
  • deprecated: nicht mehr unterstützte Version (Vorgänger der veralteten Version)

Beispiel-Szenarium für einen Versionswechsel

  • vorher:
    • semantische Version beta ist numerischer Version 1.1 zugeordnet
    • semantische Version release ist numerischer Version 1.0 zugeordnet
    • semantische Version oldrelease ist numerischer Version 0.9 zugeordnet
    • semantische Version deprecated ist numerischer Version 0.8 zugeordnet
  • nachher (Freigabe der beta-Version als neue release-Version)
    • [NEU] semantische Version beta ist numerischer Version 1.2 zugeordnet
    • semantische Version release ist numerischer Version 1.1 zugeordnet
    • semantische Version oldrelease ist numerischer Version 1.0 zugeordnet
    • semantische Version deprecated ist numerischer Version 0.9 zugeordnet
    • [ALT] numerische Version 0.8 ist abgeschaltet und nicht mehr verfügbar