Markus Michalski FAQ

API Key Wildcard: Technische Details

Technik von API Key Wildcard: Ablauf einer Anfrage und des Plugin-Lebenszyklus als Diagramm, Klassen und Rückgabewerte, SQL-Prüfung, Auto-Update, Signal api und Dateistruktur.

English Version

Zurück zur Übersicht

API Key Wildcard: Technische Details

Ablauf einer Anfrage

graph TD
    A["POST /api/wildcard/tickets.json"] --> B["api/.htaccess: Regel wildcard/ nach wildcard.php"]
    B --> C["api/wildcard.php mit PATH_INFO /tickets.json"]
    C --> D{"Route POST /tickets.json, .xml oder .email?"}
    D -->|"Nein"| E["Keine Route der Wildcard-Prüfung"]
    D -->|"Ja"| F["WildcardTicketApiController.create"]
    F --> G["WildcardApiController.requireApiKey"]
    G -->|"Key fehlt, unbekannt, inaktiv oder IP passt nicht"| H["401"]
    G -->|"Key gültig"| I{"Key-IP ist 0.0.0.0 und Logging aktiv?"}
    I -->|"Ja"| J["Debug-Eintrag im System-Log"]
    I -->|"Nein"| K["Ticket wird erstellt"]
    J --> K

wildcard.php bootstrapt osTicket über ../main.inc.php, lädt include/plugins/api-key-wildcard/api.wildcard.inc.php und api.tickets.php. Es definiert WildcardTicketApiController als Unterklasse von TicketApiController, deren requireApiKey() an WildcardApiController delegiert. Anschließend wird der Dispatcher aufgebaut, das Signal api gesendet und der Pfad aufgelöst.

Prüfung des API-Keys

WildcardApiController.requireApiKey() arbeitet in dieser Reihenfolge:

  1. Kein Key im Request: 401 Valid API key required.
  2. Suche mit wildcard_getIdByKey(): ohne Treffer 401 API key not found or IP not authorized.
  3. Key laden: nicht vorhanden oder nicht aktiv ergibt 401 API key not active.
  4. Key-IP ist weder 0.0.0.0 noch die Absender-IP: 401 Source IP not authorized.
  5. Key-IP ist 0.0.0.0 und log_wildcard_access aktiv: Debug-Eintrag, danach wird der Key zurückgegeben.

Die SQL-Bedingung der Suche lautet:

SELECT id FROM API_KEY_TABLE WHERE apikey = ? AND (ipaddr = ? OR ipaddr = "0.0.0.0")

Die Standard-API prüft dagegen nur auf die exakte IP. Schritt 4 ist nach der SQL-Suche eine zusätzliche Absicherung.

Lebenszyklus des Plugins

graph TD
    A["bootstrap()"] --> B{"installed_version leer oder niedriger?"}
    B -->|"Ja"| C["performUpdate()"]
    B -->|"Nein"| D["Nichts zu tun"]
    C --> E["PluginInstaller.update()"]
    E --> F["HtaccessManager.applyAll(), falls api/.htaccess existiert"]
    F --> G["installed_version speichern, Eintrag im PHP-Error-Log"]
    H["enable()"] --> I["Singleton-Instanz anlegen, falls keine existiert"]
    I --> J["PluginInstaller.install()"]
    J --> K["HtaccessManager.applyAll()"]
    K --> L["installed_version speichern"]
    M["disable()"] --> N["PluginInstaller.uninstall()"]
    N --> O["removeWildcardRule() und removeMultiViews()"]

Klassen und Rückgabewerte

Klasse Aufgabe Wichtige Methoden
ApiKeyWildcardPlugin Plugin-Klasse, Singleton bootstrap(), enable(), disable(), performUpdate() (public)
ApiKeyWildcardConfig Konfigurationsfelder getOptions()
PluginInstaller Endpoint-Datei kopieren, löschen install() und update() geben ein Array mit Fehlern zurück, uninstall() gibt bool zurück
HtaccessManager Änderungen an api/.htaccess applyAll() gibt ein Array mit Fehlern zurück, addMultiViews(), addWildcardRule(), removeWildcardRule(), removeMultiViews() geben bool zurück
PluginConstants Konstanten (Slug, Dateiname, 0.0.0.0, Kommentare, Dateimodus 0755)
WildcardApiController API-Key-Prüfung mit Wildcard requireApiKey()
WildcardTicketApiController Ticket-Controller mit dieser Prüfung (in wildcard.php) requireApiKey()

enable() gibt true oder ein Array mit Fehlern zurück. disable() gibt immer true zurück, die Ergebnisse der einzelnen Schritte werden nicht ausgewertet. performUpdate() gibt ein Array mit allen Fehlern zurück, sonst true.

Auto-Update

Bei jedem bootstrap() liest das Plugin installed_version aus der Konfiguration und vergleicht sie per version_compare mit der Version aus plugin.php. Ist der Wert leer oder niedriger, läuft performUpdate(): Die Endpoint-Datei wird neu kopiert, api/.htaccess (falls vorhanden) ergänzt und die neue Version gespeichert. Bei Erfolg schreibt performUpdate() eine Zeile ins PHP-Error-Log (Installation oder Update). Eine gleiche oder höhere installierte Version löst kein Update aus.

enable() schreibt kein Installations- oder Update-Log. Es schreibt nur dann ins PHP-Error-Log, wenn es die Singleton-Instanz automatisch anlegt: [API Key Wildcard] Auto-created singleton instance bei Erfolg, [API Key Wildcard] Failed to auto-create instance: ... bei einem Fehler.

Signal api

Signal Gesendet von Zweck
api wildcard.php Gibt anderen Plugins die Möglichkeit, Routen am Dispatcher des Wildcard-Endpoints zu registrieren. Diese Routen nutzen ihre eigene Key-Prüfung.

Die Plugin-Klasse selbst verbindet sich mit keinem Signal.

Dateistruktur

Auszug aus dem Repository. Das ist nicht der Inhalt des Release-ZIP.

osticket-api-key-wildcard/
├── plugin.php                  # Registrierung (ID, Name, Plugin-Klasse)
├── class.ApiKeyWildcard.php    # Plugin-Klasse und Konfiguration
├── class.PluginConstants.php   # Konstanten
├── class.PluginInstaller.php   # Endpoint-Datei kopieren und löschen
├── class.HtaccessManager.php   # Änderungen an api/.htaccess
├── api.wildcard.inc.php        # WildcardApiController und Hilfsfunktionen
├── wildcard.php                # Endpoint, wird nach api/ kopiert
├── .htaccess                   # Referenz, nur im Repository, vom Plugin nicht verwendet
├── README.md
├── CHANGELOG.md
├── LICENSE
├── .releaseinclude             # Dateien des Release-ZIP
├── .gitignore
└── .github/                    # CI-Workflow

Das Release-ZIP enthält laut .releaseinclude nur *.php, README.md, README-de.md, LICENSE und CHANGELOG.md. Die .htaccess ist daher nicht im ZIP. Die Datei README-de.md steht in .releaseinclude, existiert im Repository aber nicht.