Dateien nach "backend/src/tools/dateien" hochladen

This commit is contained in:
2026-05-26 15:38:13 +02:00
parent c8b327e457
commit 37ccdfbdda

View File

@@ -0,0 +1,136 @@
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const db = require('../../db');
const { authenticate, requireAdmin } = require('../../middleware/auth');
const router = express.Router();
const UPLOAD_DIR = process.env.UPLOAD_DIR || '/data/uploads';
if (!fs.existsSync(UPLOAD_DIR)) fs.mkdirSync(UPLOAD_DIR, { recursive: true });
const getSetting = key => db.prepare('SELECT value FROM admin_settings WHERE key=?').get(key)?.value;
const storage = multer.diskStorage({
destination: UPLOAD_DIR,
filename: (req, file, cb) => cb(null, `${Date.now()}-${Math.random().toString(36).slice(2)}${path.extname(file.originalname)}`),
});
const upload = multer({
storage,
limits: { fileSize: () => parseInt(getSetting('file_max_size_mb') || '50') * 1024 * 1024 },
fileFilter: (req, file, cb) => {
const allowed = (getSetting('file_allowed_ext') || '').split(',').map(e => e.trim().toLowerCase());
const ext = path.extname(file.originalname).toLowerCase();
if (!allowed.length || allowed.includes(ext)) cb(null, true);
else cb(new Error(`Dateityp nicht erlaubt: ${ext}`));
},
});
// GET / eigene Dateien + freigegebene
router.get('/', authenticate, (req, res) => {
const uid = req.user.id;
const own = db.prepare('SELECT f.*, u.username as owner FROM files f JOIN users u ON u.id=f.user_id WHERE f.user_id=? ORDER BY f.created_at DESC').all(uid);
const shared = db.prepare(`
SELECT f.*, u.username as owner, s.shared_by, sb.username as shared_by_name
FROM files f
JOIN users u ON u.id=f.user_id
JOIN file_shares s ON s.file_id=f.id
JOIN users sb ON sb.id=s.shared_by
WHERE s.shared_with=?
ORDER BY f.created_at DESC
`).all(uid);
res.json({ own, shared });
});
// POST / Datei hochladen
router.post('/', authenticate, (req, res) => {
const uid = req.user.id;
const maxCount = parseInt(getSetting('file_max_count') || '20');
const count = db.prepare('SELECT COUNT(*) c FROM files WHERE user_id=?').get(uid).c;
if (count >= maxCount) return res.status(400).json({ error: `Maximum ${maxCount} Dateien erlaubt` });
upload.single('file')(req, res, err => {
if (err) return res.status(400).json({ error: err.message });
if (!req.file) return res.status(400).json({ error: 'Keine Datei' });
const r = db.prepare('INSERT INTO files (user_id,filename,originalname,mimetype,size) VALUES (?,?,?,?,?)')
.run(uid, req.file.filename, req.file.originalname, req.file.mimetype || 'application/octet-stream', req.file.size);
res.json(db.prepare('SELECT f.*, u.username as owner FROM files f JOIN users u ON u.id=f.user_id WHERE f.id=?').get(r.lastInsertRowid));
});
});
// GET /:id/download
router.get('/:id/download', authenticate, (req, res) => {
const uid = req.user.id;
const file = db.prepare('SELECT * FROM files WHERE id=?').get(req.params.id);
if (!file) return res.status(404).json({ error: 'Nicht gefunden' });
// Zugriff: eigene Datei oder freigegeben
const hasAccess = file.user_id === uid ||
db.prepare('SELECT id FROM file_shares WHERE file_id=? AND shared_with=?').get(file.id, uid);
if (!hasAccess) return res.status(403).json({ error: 'Kein Zugriff' });
const filePath = path.join(UPLOAD_DIR, file.filename);
if (!fs.existsSync(filePath)) return res.status(404).json({ error: 'Datei fehlt auf Server' });
res.download(filePath, file.originalname);
});
// GET /:id/shares wer hat Zugriff auf diese Datei
router.get('/:id/shares', authenticate, (req, res) => {
const file = db.prepare('SELECT * FROM files WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!file) return res.status(404).json({ error: 'Nicht gefunden' });
const shares = db.prepare(`
SELECT u.id, u.username FROM file_shares s
JOIN users u ON u.id=s.shared_with
WHERE s.file_id=?
`).all(file.id);
res.json(shares);
});
// DELETE /:id nur eigene Dateien
router.delete('/:id', authenticate, (req, res) => {
const file = db.prepare('SELECT * FROM files WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!file) return res.status(404).json({ error: 'Nicht gefunden' });
try { fs.unlinkSync(path.join(UPLOAD_DIR, file.filename)); } catch {}
db.prepare('DELETE FROM files WHERE id=?').run(file.id);
res.json({ success: true });
});
// POST /:id/share Datei freigeben
router.post('/:id/share', authenticate, (req, res) => {
const file = db.prepare('SELECT * FROM files WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!file) return res.status(404).json({ error: 'Nicht gefunden oder kein Zugriff' });
const { username } = req.body;
const target = db.prepare('SELECT * FROM users WHERE username=?').get(username);
if (!target) return res.status(404).json({ error: `Benutzer "${username}" nicht gefunden` });
if (target.id === req.user.id) return res.status(400).json({ error: 'Kannst du nicht mit dir selbst teilen' });
try {
db.prepare('INSERT OR IGNORE INTO file_shares (file_id,shared_by,shared_with) VALUES (?,?,?)').run(file.id, req.user.id, target.id);
res.json({ success: true });
} catch(e) { res.status(400).json({ error: e.message }); }
});
// DELETE /:id/share/:userId Freigabe entfernen
router.delete('/:id/share/:userId', authenticate, (req, res) => {
const file = db.prepare('SELECT * FROM files WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!file) return res.status(404).json({ error: 'Nicht gefunden' });
db.prepare('DELETE FROM file_shares WHERE file_id=? AND shared_with=?').run(file.id, req.params.userId);
res.json({ success: true });
});
// GET /settings Admin-Einstellungen lesen
router.get('/settings', authenticate, requireAdmin, (req, res) => {
const s = db.prepare('SELECT * FROM admin_settings').all();
const obj = {}; for (const r of s) obj[r.key] = r.value;
res.json(obj);
});
// PUT /settings Admin-Einstellungen speichern
router.put('/settings', authenticate, requireAdmin, (req, res) => {
const allowed = ['file_max_size_mb','file_max_count','file_allowed_ext'];
for (const key of allowed) {
if (req.body[key] !== undefined)
db.prepare('INSERT OR REPLACE INTO admin_settings (key,value) VALUES (?,?)').run(key, String(req.body[key]));
}
res.json({ success: true });
});
module.exports = router;