Initial commit: Projektübersicht - Docker GANT
This commit is contained in:
commit
004003cd17
670 files changed
+76973
No files matched your search
@@ -0,0 +1,113 @@
|
||||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const app = express();
|
||||
|
||||
const BOM = Buffer.from([0xEF, 0xBB, 0xBF]);
|
||||
const PORT = process.env.PORT || 3003;
|
||||
const VALID_DEPARTMENTS = new Set(['ELT','HLS','ARCH']);
|
||||
|
||||
app.use(require('cors')());
|
||||
app.use(express.json({ limit: '2mb' }));
|
||||
app.use(express.static(path.join(__dirname, 'public'), {
|
||||
setHeaders: (res, path) => {
|
||||
if(path.endsWith('.js') || path.endsWith('.css') || path.endsWith('.html')){
|
||||
res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
|
||||
res.set('Pragma', 'no-cache');
|
||||
res.set('Expires', '0');
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const SESSIONS_DIR = path.join(__dirname, 'sessions');
|
||||
if(!fs.existsSync(SESSIONS_DIR)) fs.mkdirSync(SESSIONS_DIR, { recursive: true });
|
||||
|
||||
// Erlaubt ausschliesslich sichere CSV-Dateinamen im Format <Name>.csv
|
||||
function safeName(name){
|
||||
const raw = String(name || '');
|
||||
// Pfad-Trennzeichen und Verzeichnisnavigation ablehnen
|
||||
if(/[\\/]|\.\./.test(raw)) return null;
|
||||
const base = path.basename(raw);
|
||||
if(!base || base.toLowerCase() === '.csv') return null;
|
||||
const safe = base.replace(/[^a-zA-Z0-9_\-\.]/g,'_');
|
||||
if(!/^([a-zA-Z0-9_\-]+)\.csv$/i.test(safe)) return null;
|
||||
return safe;
|
||||
}
|
||||
|
||||
function departmentDir(department){
|
||||
const dept = (typeof department === 'string' && VALID_DEPARTMENTS.has(department)) ? department : 'ELT';
|
||||
const dir = path.join(SESSIONS_DIR, dept);
|
||||
if(!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
return dir;
|
||||
}
|
||||
|
||||
app.post('/save-csv', (req, res) => {
|
||||
const { filename, csv, department } = req.body || {};
|
||||
if(!filename || typeof csv !== 'string') return res.status(400).json({ ok: false, error: 'Missing filename or csv' });
|
||||
const safe = safeName(filename);
|
||||
if(!safe) return res.status(400).json({ ok: false, error: 'Invalid filename' });
|
||||
const dir = departmentDir(department);
|
||||
const out = path.join(dir, safe);
|
||||
const data = Buffer.concat([BOM, Buffer.from(csv, 'utf8')]);
|
||||
fs.writeFile(out, data, (err) => {
|
||||
if(err){ console.error('Write error', err); return res.status(500).json({ ok:false, error: String(err) }); }
|
||||
console.log('Saved CSV:', out);
|
||||
return res.json({ ok: true, path: out });
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/delete-csv', (req, res) => {
|
||||
const { filename, department } = req.body || {};
|
||||
if(!filename) return res.status(400).json({ ok: false, error: 'Missing filename' });
|
||||
const safe = safeName(filename);
|
||||
if(!safe) return res.status(400).json({ ok: false, error: 'Invalid filename' });
|
||||
const dir = departmentDir(department);
|
||||
const out = path.join(dir, safe);
|
||||
fs.unlink(out, (err) => {
|
||||
if(err){
|
||||
if(err.code === 'ENOENT') {
|
||||
console.log('CSV-Datei nicht gefunden:', out);
|
||||
return res.json({ ok: true, missing: true });
|
||||
}
|
||||
console.error('Delete error', err);
|
||||
return res.status(500).json({ ok:false, error: String(err) });
|
||||
}
|
||||
console.log('Deleted CSV:', out);
|
||||
return res.json({ ok: true });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/load-all', (req, res) => {
|
||||
const dir = departmentDir(req.query.department);
|
||||
fs.readdir(dir, (err, files) => {
|
||||
if(err){ console.error('Read error', err); return res.status(500).json({ ok:false, error: String(err) }); }
|
||||
const csvFiles = files.filter(f => f.toLowerCase().endsWith('.csv'));
|
||||
const result = { ok: true, sessions: [], people: null };
|
||||
csvFiles.forEach(filename => {
|
||||
if(filename.toLowerCase() === '_people.csv'){
|
||||
result.people = fs.readFileSync(path.join(dir, filename), 'utf8');
|
||||
return;
|
||||
}
|
||||
const content = fs.readFileSync(path.join(dir, filename), 'utf8');
|
||||
result.sessions.push({ filename, content });
|
||||
});
|
||||
// Sortiere Sitzungen nach Dateiname, damit die Reihenfolge stabil ist
|
||||
result.sessions.sort((a,b) => a.filename.localeCompare(b.filename));
|
||||
res.json(result);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/health', (req,res)=> res.json({ok:true}));
|
||||
|
||||
app.get('/', (req,res)=>{
|
||||
res.sendFile(path.join(__dirname, 'public', 'Test.html'));
|
||||
});
|
||||
|
||||
const server = app.listen(PORT, ()=> console.log(`CSV-Session server running on http://localhost:${PORT}`));
|
||||
server.on('error', (err) => {
|
||||
console.error('Server konnte nicht starten:', err.message);
|
||||
if(err.code === 'EADDRINUSE'){
|
||||
console.error(`Port ${PORT} ist bereits belegt. Bitte einen anderen PORT verwenden, z.B. PORT=3004 npm start`);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in new issue
Block a user