added webdav server
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx watch src/index.ts",
|
"dev": "tsx watch src/index.ts",
|
||||||
|
"dev:dav": "tsx watch src/webdav/server.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node dist/src/index.js",
|
"start": "node dist/src/index.js",
|
||||||
"schema:index": "ts-node scripts/generate-schema-index.ts"
|
"schema:index": "ts-node scripts/generate-schema-index.ts"
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"pngjs": "^7.0.0",
|
"pngjs": "^7.0.0",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
|
"webdav-server": "^2.6.2",
|
||||||
"xmlbuilder": "^15.1.1",
|
"xmlbuilder": "^15.1.1",
|
||||||
"zpl-image": "^0.2.0",
|
"zpl-image": "^0.2.0",
|
||||||
"zpl-renderer-js": "^2.0.2"
|
"zpl-renderer-js": "^2.0.2"
|
||||||
|
|||||||
106
backend/src/webdav/server.ts
Normal file
106
backend/src/webdav/server.ts
Normal file
@@ -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();
|
||||||
Reference in New Issue
Block a user