generated from Dicken/dickendock
Commit 8: Plugin-System (Scanner erweitern, Geräte importieren, Icons)
This commit is contained in:
78
apps/backend/plugins/README.md
Normal file
78
apps/backend/plugins/README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# LaunchPad-Plugins
|
||||
|
||||
Jeder Unterordner hier ist ein Plugin. Erkannt wird alles, was eine
|
||||
`index.js` mit einem passenden Default-Export enthält – kein Rebuild des
|
||||
Docker-Images nötig, dieser Ordner wird zur Laufzeit als Volume eingebunden
|
||||
(siehe `docker-compose.yml`). Nach dem Hinzufügen/Ändern eines Plugins
|
||||
reicht ein Neustart des Backend-Containers:
|
||||
|
||||
```bash
|
||||
docker compose restart backend
|
||||
```
|
||||
|
||||
## Minimalstruktur
|
||||
|
||||
```
|
||||
apps/backend/plugins/mein-plugin/
|
||||
└── index.js
|
||||
```
|
||||
|
||||
```js
|
||||
export default {
|
||||
name: "mein-plugin",
|
||||
version: "1.0.0",
|
||||
description: "Kurze Beschreibung, erscheint unter Admin -> Plugins",
|
||||
|
||||
// optional: Scanner erweitern
|
||||
setup(ctx) {
|
||||
ctx.registerSoftwareSignature({
|
||||
name: "Meine Software",
|
||||
category: "Sonstiges",
|
||||
icon: "🔧", // Emoji oder Icon-URL
|
||||
matches: (input) => !!input.body && /meine-software/i.test(input.body),
|
||||
});
|
||||
},
|
||||
|
||||
// optional: eigene Geräte-Importquelle
|
||||
async importDevices() {
|
||||
return [
|
||||
{ hostname: "beispiel", ip: "192.168.1.99", source: "plugin" },
|
||||
];
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Beide Funktionen (`setup`, `importDevices`) sind optional – ein Plugin kann
|
||||
nur die eine, nur die andere, oder beide implementieren. Reines JavaScript
|
||||
(ESM), kein Build-Schritt nötig.
|
||||
|
||||
## Was Plugins aktuell können
|
||||
|
||||
- **Scanner registrieren**: `ctx.registerSoftwareSignature(...)` in `setup()`
|
||||
fügt der automatischen Softwareerkennung (siehe `apps/backend/src/scanner/softwareDetection.ts`)
|
||||
eine zusätzliche Signatur hinzu, inklusive eigenem Icon. Wird bei jedem
|
||||
Geräte-Scan berücksichtigt.
|
||||
- **Geräte importieren**: `importDevices()` liefert eine Liste von Geräten,
|
||||
die per Knopfdruck unter Admin -> Plugins importiert werden
|
||||
(`POST /api/plugins/:name/import`). Abgeglichen wird wie bei Scans über
|
||||
MAC/IP – ein erneuter Import überschreibt keine Gerätefelder, die der
|
||||
Nutzer zwischenzeitlich geändert hat, außer den scan-eigenen (siehe
|
||||
`upsertDeviceFromScan`).
|
||||
- **Icons bereitstellen**: über `icon` an einer registrierten Signatur. Wird
|
||||
als Startwert für neu angelegte Dienste übernommen (wie `category` –
|
||||
niemals nachträglich überschrieben, siehe README Hauptprojekt).
|
||||
|
||||
## Was (noch) nicht geht
|
||||
|
||||
- Eigene Admin-Menüpunkte/Unterseiten (aktuell erscheinen alle Plugins
|
||||
gesammelt auf einer Seite unter Admin -> Plugins, keine eigene Route pro
|
||||
Plugin).
|
||||
- Kein Sandboxing: Plugin-Code läuft mit vollem Zugriff im Backend-Prozess.
|
||||
Nur Plugins aus vertrauenswürdiger Quelle einbinden.
|
||||
|
||||
## Beispiel-Plugins
|
||||
|
||||
- `example-signatures/` – registriert zwei zusätzliche Software-Signaturen
|
||||
(Homebridge, Uptime Kuma).
|
||||
- `static-import/` – importiert Geräte aus einer lokalen `devices.json`
|
||||
(standardmäßig leer, siehe `devices.example.json` für das Format).
|
||||
29
apps/backend/plugins/example-signatures/index.js
Normal file
29
apps/backend/plugins/example-signatures/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Beispiel-Plugin: registriert zwei zusätzliche Softwareerkennungen, die
|
||||
* nicht in der eingebauten Liste enthalten sind, inklusive eigenem Icon.
|
||||
*
|
||||
* Zeigt das setup()-Pattern: ein Plugin bekommt beim Laden einen Kontext mit
|
||||
* registerSoftwareSignature() und kann darüber den Scanner erweitern.
|
||||
*/
|
||||
export default {
|
||||
name: "example-signatures",
|
||||
version: "1.0.0",
|
||||
description:
|
||||
"Erkennt Homebridge und Uptime Kuma zusätzlich zu den eingebauten Signaturen.",
|
||||
|
||||
setup(ctx) {
|
||||
ctx.registerSoftwareSignature({
|
||||
name: "Homebridge",
|
||||
category: "Smart Home",
|
||||
icon: "🏠",
|
||||
matches: (input) => !!input.body && /homebridge/i.test(input.body),
|
||||
});
|
||||
|
||||
ctx.registerSoftwareSignature({
|
||||
name: "Uptime Kuma",
|
||||
category: "Monitoring",
|
||||
icon: "📈",
|
||||
matches: (input) => !!input.body && /uptime\s*kuma/i.test(input.body),
|
||||
});
|
||||
},
|
||||
};
|
||||
9
apps/backend/plugins/static-import/devices.example.json
Normal file
9
apps/backend/plugins/static-import/devices.example.json
Normal file
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"hostname": "nas",
|
||||
"ip": "192.168.1.20",
|
||||
"mac": "AA:BB:CC:DD:EE:FF",
|
||||
"manufacturer": "Synology",
|
||||
"model": "DS920+"
|
||||
}
|
||||
]
|
||||
1
apps/backend/plugins/static-import/devices.json
Normal file
1
apps/backend/plugins/static-import/devices.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
40
apps/backend/plugins/static-import/index.js
Normal file
40
apps/backend/plugins/static-import/index.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* Beispiel-Plugin: importiert Geräte aus einer lokalen devices.json neben
|
||||
* diesem Plugin. Zeigt das importDevices()-Pattern für eigene Datenquellen
|
||||
* (z. B. ein Inventar-Export oder eine externe API) – im Unterschied zu den
|
||||
* Netzwerk-Scannern rein datengetrieben, kein eigener Netzwerkzugriff nötig.
|
||||
*
|
||||
* Standardmäßig ist devices.json leer, damit beim ersten Start keine
|
||||
* Fantasiegeräte auftauchen. Zum Ausprobieren einfach Einträge ergänzen und
|
||||
* unter Admin -> Plugins auf "Jetzt importieren" klicken.
|
||||
*/
|
||||
export default {
|
||||
name: "static-import",
|
||||
version: "1.0.0",
|
||||
description: "Importiert Geräte aus plugins/static-import/devices.json.",
|
||||
|
||||
async importDevices() {
|
||||
try {
|
||||
const raw = readFileSync(join(currentDir, "devices.json"), "utf-8");
|
||||
const entries = JSON.parse(raw);
|
||||
|
||||
return entries.map((entry) => ({
|
||||
hostname: entry.hostname,
|
||||
ip: entry.ip,
|
||||
mac: entry.mac ?? undefined,
|
||||
manufacturer: entry.manufacturer ?? undefined,
|
||||
model: entry.model ?? undefined,
|
||||
online: false,
|
||||
source: "plugin",
|
||||
}));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user