const webdav = require('webdav-server').v2; const fs = require('fs'); const path = require('path'); const adminUser = process.env.WEBDAV_USER || 'admin'; const adminPass = process.env.WEBDAV_PASS || 'password'; const WEB_URL = process.env.WEB_URL || 'localhost'; const PROTOCOLE = process.env.PROTOCOLE || 'http'; const ALLOWED_ORIGIN = `${PROTOCOLE}://${WEB_URL}`; const ROOT_DIR = '/data'; // Auth const userManager = new webdav.SimpleUserManager(); const user = userManager.addUser(adminUser, adminPass, false); const privilegeManager = new webdav.SimplePathPrivilegeManager(); privilegeManager.setRights(user, '/', ['all']); // βœ… LoggingFileSystem Γ©tend PhysicalFileSystem class LoggingFileSystem extends webdav.PhysicalFileSystem { move(ctx, source, destination, callback) { console.log(`🟑 MOVE requested from ${source.toString()} to ${destination.toString()}`); const srcPath = path.join(ROOT_DIR, source.toString()); const destPath = path.join(ROOT_DIR, destination.toString()); fs.promises.mkdir(path.dirname(destPath), { recursive: true }) .then(() => fs.promises.rename(srcPath, destPath)) .then(() => { console.log(`βœ… MOVE succeeded: ${srcPath} -> ${destPath}`); if (typeof callback === 'function') callback(null); }) .catch(err => { console.error(`❌ MOVE failed: ${err.message}`); if (typeof callback === 'function') callback(err); }); } } // Serveur WebDAV const server = new webdav.WebDAVServer({ port: 9999, hostname: '0.0.0.0', httpAuthentication: new webdav.HTTPBasicAuthentication(userManager, 'default realm'), privilegeManager, rootFileSystem: new LoggingFileSystem(ROOT_DIR), responseHeaders: { 'Access-Control-Allow-Origin': ALLOWED_ORIGIN, 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Headers': 'Authorization, Depth, Content-Type', 'Access-Control-Allow-Methods': 'GET, PUT, OPTIONS, MKCOL, PROPFIND, DELETE, COPY, MOVE, LOCK, UNLOCK' } }); // Ajout header Last-Modified server.beforeRequest((arg, next) => { const { request, response, requested } = arg; if (request.method === 'GET' || request.method === 'HEAD') { const filePath = path.join(ROOT_DIR, decodeURIComponent(requested.path.toString())); fs.stat(filePath, (err, stats) => { if (!err && stats.isFile()) { response.setHeader('Last-Modified', stats.mtime.toUTCString()); console.log(`[INFO] Added Last-Modified: ${stats.mtime.toUTCString()} for ${filePath}`); } next(); }); } else { next(); } }); // Start server.start(() => { console.log(`βœ… WebDAV server ready at http://0.0.0.0:9999`); console.log(`πŸ” Auth: user="${adminUser}", pass="***"`); console.log(`🌐 CORS: Allow-Origin = ${ALLOWED_ORIGIN}`); });