153 lines
6.0 KiB
JavaScript
153 lines
6.0 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const db = require('../db');
|
|
const { requireAdmin } = require('../middleware/auth');
|
|
|
|
// Alle Admin-Routen erfordern Admin-Zugriff
|
|
router.use(requireAdmin);
|
|
|
|
// ── Stats ─────────────────────────────────────────────
|
|
|
|
router.get('/stats', async (req, res) => {
|
|
try {
|
|
const [[{ ghosts }]] = await db.execute('SELECT COUNT(*) as ghosts FROM ghosts');
|
|
const [[{ total }]] = await db.execute('SELECT COUNT(*) as total FROM submissions');
|
|
const [[{ pending }]] = await db.execute("SELECT COUNT(*) as pending FROM submissions WHERE status='pending'");
|
|
const [[{ approved }]]= await db.execute("SELECT COUNT(*) as approved FROM submissions WHERE status='approved'");
|
|
const [[{ rejected }]]= await db.execute("SELECT COUNT(*) as rejected FROM submissions WHERE status='rejected'");
|
|
res.json({ ghosts, total, pending, approved, rejected });
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// ── Ghosts CRUD ───────────────────────────────────────
|
|
|
|
// Geist erstellen
|
|
router.post('/ghosts', async (req, res) => {
|
|
const { id, name, evidence, sanity, hunt, sanity_special, tip, description, tells } = req.body;
|
|
if (!id || !name || !Array.isArray(evidence) || evidence.length !== 3) {
|
|
return res.status(400).json({ error: 'Ungültige Daten (id, name, genau 3 evidence erforderlich)' });
|
|
}
|
|
try {
|
|
await db.query(
|
|
`INSERT INTO ghosts (id, name, evidence, sanity, hunt, sanity_special, tip, description, tells, updated_by)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[id, name, JSON.stringify(evidence), sanity||50, hunt||'mid',
|
|
sanity_special||'', tip||'', description||'', JSON.stringify(tells||[]),
|
|
req.user.username]
|
|
);
|
|
res.json({ ok: true });
|
|
} catch (e) {
|
|
if (e.code === 'ER_DUP_ENTRY') return res.status(409).json({ error: 'ID bereits vorhanden' });
|
|
console.error(e);
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// Geist bearbeiten
|
|
router.put('/ghosts/:id', async (req, res) => {
|
|
const { name, evidence, sanity, hunt, sanity_special, tip, description, tells } = req.body;
|
|
if (!name || !Array.isArray(evidence) || evidence.length !== 3) {
|
|
return res.status(400).json({ error: 'Ungültige Daten' });
|
|
}
|
|
try {
|
|
const result = await db.query(
|
|
`UPDATE ghosts SET name=?, evidence=?, sanity=?, hunt=?, sanity_special=?,
|
|
tip=?, description=?, tells=?, updated_by=? WHERE id=?`,
|
|
[name, JSON.stringify(evidence), sanity||50, hunt||'mid',
|
|
sanity_special||'', tip||'', description||'', JSON.stringify(tells||[]),
|
|
req.user.username, req.params.id]
|
|
);
|
|
if (result.affectedRows === 0) return res.status(404).json({ error: 'Geist nicht gefunden' });
|
|
res.json({ ok: true });
|
|
} catch (e) {
|
|
console.error(e);
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// Geist löschen
|
|
router.delete('/ghosts/:id', async (req, res) => {
|
|
try {
|
|
const result = await db.query('DELETE FROM ghosts WHERE id=?', [req.params.id]);
|
|
if (result.affectedRows === 0) return res.status(404).json({ error: 'Geist nicht gefunden' });
|
|
res.json({ ok: true });
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// ── Submissions ───────────────────────────────────────
|
|
|
|
// Alle Submissions laden (mit Filter)
|
|
router.get('/submissions', async (req, res) => {
|
|
const { status } = req.query;
|
|
try {
|
|
const rows = status
|
|
? await db.query('SELECT * FROM submissions WHERE status=? ORDER BY created_at DESC', [status])
|
|
: await db.query('SELECT * FROM submissions ORDER BY created_at DESC');
|
|
res.json(rows);
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// Submission reviewen (approve/reject)
|
|
router.patch('/submissions/:id', async (req, res) => {
|
|
const { status, admin_note } = req.body;
|
|
if (!['approved','rejected'].includes(status)) return res.status(400).json({ error: 'Status muss approved oder rejected sein' });
|
|
try {
|
|
await db.query(
|
|
`UPDATE submissions SET status=?, admin_note=?, reviewed_at=NOW(), reviewed_by=? WHERE id=?`,
|
|
[status, admin_note||'', req.user.username, req.params.id]
|
|
);
|
|
res.json({ ok: true });
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// ── Admin Whitelist ───────────────────────────────────
|
|
|
|
// Whitelist laden
|
|
router.get('/whitelist', async (req, res) => {
|
|
try {
|
|
const rows = await db.query('SELECT * FROM admin_whitelist ORDER BY added_at ASC');
|
|
res.json(rows);
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// Admin hinzufügen
|
|
router.post('/whitelist', async (req, res) => {
|
|
const { discord_id, discord_username } = req.body;
|
|
if (!discord_id || discord_id.length < 10) return res.status(400).json({ error: 'Ungültige Discord ID' });
|
|
try {
|
|
await db.query(
|
|
'INSERT INTO admin_whitelist (discord_id, discord_username, added_by) VALUES (?,?,?)',
|
|
[discord_id.trim(), discord_username||discord_id, req.user.username]
|
|
);
|
|
res.json({ ok: true });
|
|
} catch (e) {
|
|
if (e.code === 'ER_DUP_ENTRY') return res.status(409).json({ error: 'Bereits in der Whitelist' });
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
// Admin entfernen (kann sich nicht selbst entfernen)
|
|
router.delete('/whitelist/:discord_id', async (req, res) => {
|
|
if (req.params.discord_id === req.user.id) {
|
|
return res.status(400).json({ error: 'Du kannst dich nicht selbst aus der Whitelist entfernen' });
|
|
}
|
|
try {
|
|
await db.query('DELETE FROM admin_whitelist WHERE discord_id=?', [req.params.discord_id]);
|
|
res.json({ ok: true });
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'DB-Fehler' });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|