From 6423886930161e3d48a515690408ef3b56957f15 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Sat, 17 Jan 2026 15:15:34 +0100 Subject: [PATCH] added webdav server --- backend/package.json | 2 + backend/src/webdav/server.ts | 106 +++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 backend/src/webdav/server.ts diff --git a/backend/package.json b/backend/package.json index 6b2b772..b17d339 100644 --- a/backend/package.json +++ b/backend/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "dev": "tsx watch src/index.ts", + "dev:dav": "tsx watch src/webdav/server.ts", "build": "tsc", "start": "node dist/src/index.js", "schema:index": "ts-node scripts/generate-schema-index.ts" @@ -48,6 +49,7 @@ "pg": "^8.16.3", "pngjs": "^7.0.0", "sharp": "^0.34.5", + "webdav-server": "^2.6.2", "xmlbuilder": "^15.1.1", "zpl-image": "^0.2.0", "zpl-renderer-js": "^2.0.2" diff --git a/backend/src/webdav/server.ts b/backend/src/webdav/server.ts new file mode 100644 index 0000000..fe0061f --- /dev/null +++ b/backend/src/webdav/server.ts @@ -0,0 +1,106 @@ +import 'dotenv/config'; +import { v2 as webdav } from 'webdav-server'; +import { db } from '../../db'; +// WICHTIG: 'folders' muss hier importiert werden +import { tenants, files, folders } from '../../db/schema'; +import { eq } from 'drizzle-orm'; + +// 1. User & Rechte Setup +const userManager = new webdav.SimpleUserManager(); +const user = userManager.addUser('admin', 'admin', true); + +const privilegeManager = new webdav.SimplePathPrivilegeManager(); +privilegeManager.setRights(user, '/', [ 'all' ]); + +const server = new webdav.WebDAVServer({ + httpAuthentication: new webdav.HTTPDigestAuthentication(userManager, 'Default realm'), + privilegeManager: privilegeManager, + port: 3200, +}); + +async function startServer() { + console.log('------------------------------------------------'); + console.log('[WebDAV] Lade Struktur (Tenants -> Folders -> Files)...'); + + try { + // A. Alle Daten abrufen + const allTenants = await db.select().from(tenants); + const allFolders = await db.select().from(folders); + const allFiles = await db.select().from(files); + + console.log(`[WebDAV] Stats: ${allTenants.length} Tenants, ${allFolders.length} Ordner, ${allFiles.length} Dateien.`); + + // -------------------------------------------------------------------- + // REKURSIVE FUNKTION: Baut den Inhalt eines Ordners + // -------------------------------------------------------------------- + const buildFolderContent = (tenantId: string, parentFolderId: string | null) => { + const currentDir: any = {}; + + // 1. UNTERORDNER finden + // Wir suchen Ordner, die zum aktuellen Tenant gehören UND diesen Ordner als Parent haben + const subFolders = allFolders.filter(f => + f.tenant === tenantId && f.parent === parentFolderId + ); + + subFolders.forEach(folder => { + // Rekursion: Wir rufen die Funktion für diesen Unterordner erneut auf + // Das Objekt, das zurückkommt, ist der Inhalt des Unterordners + currentDir[folder.name] = buildFolderContent(tenantId, folder.id); + }); + + // 2. DATEIEN finden + // Wir suchen Dateien, die in diesem Ordner liegen + const dirFiles = allFiles.filter(f => + f.tenant === tenantId && f.folder === parentFolderId + ); + + dirFiles.forEach(file => { + // Name aus Pfad extrahieren (wie im Frontend) + let fileName = 'Unbenannt.txt'; + if (file.path) fileName = file.path.split('/').pop() || 'Unbenannt.txt'; + else if (file.name) fileName = file.name; + + // Inhalt (Placeholder) + currentDir[fileName] = `Datei: ${fileName}\nID: ${file.id}`; + }); + + return currentDir; + }; + + // B. Hauptbaum bauen (Einstiegspunkt) + const dbTree: any = {}; + + allTenants.forEach(tenant => { + const tenantName = tenant.name.replace(/\//g, '-'); + + // Wir starten die Rekursion am "Root" des Tenants (parentFolderId = null) + const tenantRootContent = buildFolderContent(tenant.id, null); + + // Wenn Tenant komplett leer ist (keine Ordner im Root, keine Files im Root) + if (Object.keys(tenantRootContent).length === 0) { + tenantRootContent['(Leer).txt'] = 'Dieser Tenant ist leer.'; + } + + dbTree[tenantName] = tenantRootContent; + }); + + // Fallback für leere DB + if (Object.keys(dbTree).length === 0) { + dbTree['Status.txt'] = 'Keine Tenants gefunden.'; + } + + // C. Baum registrieren + const root = server.rootFileSystem(); + root.addSubTree(server.createExternalContext(), dbTree); + + // D. Starten + server.start(() => { + console.log('[WebDAV] 🚀 READY auf http://localhost:3200'); + }); + + } catch (error) { + console.error('[WebDAV] 💥 Fehler:', error); + } +} + +startServer(); \ No newline at end of file