146 lines
5.6 KiB
JavaScript
146 lines
5.6 KiB
JavaScript
const express = require('express');
|
|
const http = require('http');
|
|
const path = require('path');
|
|
const { getEnvConfig, readConfig, writeConfig } = require('./config');
|
|
const { listRows, batchCreateRows } = require('./baserow');
|
|
const { setupWebSocket, getSessions } = require('./live-session');
|
|
const { sanitizeQuestion, shuffleArray } = require('./quiz-logic');
|
|
|
|
const app = express();
|
|
const server = http.createServer(app);
|
|
|
|
app.use(express.json({ limit: '5mb' }));
|
|
app.use(express.static(path.join(__dirname, '..', 'public')));
|
|
|
|
function requireAdmin(req, res, next) {
|
|
if (req.headers['x-admin-token'] !== getEnvConfig().adminPassword) {
|
|
return res.status(401).json({ error: 'Nicht autorisiert' });
|
|
}
|
|
next();
|
|
}
|
|
|
|
/* ============================================================ */
|
|
/* Public API */
|
|
/* ============================================================ */
|
|
|
|
app.get('/api/sets', (req, res) => {
|
|
const config = readConfig();
|
|
console.log(`[api] GET /api/sets — ${(config.sets || []).length} sets`);
|
|
res.json((config.sets || []).map((s) => ({ id: s.id, name: s.name })));
|
|
});
|
|
|
|
app.get('/api/sets/:id/questions', async (req, res) => {
|
|
try {
|
|
const config = readConfig();
|
|
const set = config.sets.find((s) => s.id === req.params.id);
|
|
if (!set) return res.status(404).json({ error: 'Fragenset nicht gefunden' });
|
|
console.log(`[api] Loading questions for set "${set.name}" (table ${set.tableId})`);
|
|
const rows = await listRows(set.tableId);
|
|
console.log(`[api] Loaded ${rows.length} questions`);
|
|
if (rows.length > 0) {
|
|
console.log(`[api] Fields: ${Object.keys(rows[0]).join(', ')}`);
|
|
}
|
|
res.json(rows);
|
|
} catch (e) {
|
|
console.error(`[api] Error loading questions:`, e.message);
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
app.post('/api/results', async (req, res) => {
|
|
try {
|
|
const config = readConfig();
|
|
if (!config.answersTableId) return res.status(400).json({ error: 'Antworten-Tabelle nicht konfiguriert' });
|
|
const answers = req.body.answers || [];
|
|
console.log(`[api] Saving ${answers.length} results`);
|
|
await batchCreateRows(config.answersTableId, answers);
|
|
res.json({ success: true });
|
|
} catch (e) {
|
|
console.error(`[api] Error saving results:`, e.message);
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
app.get('/api/results/:name', async (req, res) => {
|
|
try {
|
|
const config = readConfig();
|
|
if (!config.answersTableId) return res.json([]);
|
|
const rows = await listRows(config.answersTableId, { Nutzername: req.params.name });
|
|
res.json(rows);
|
|
} catch (e) {
|
|
console.error(`[api] Error loading results:`, e.message);
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
/* ============================================================ */
|
|
/* Admin API */
|
|
/* ============================================================ */
|
|
|
|
app.post('/api/admin/login', (req, res) => {
|
|
if (req.body.password === getEnvConfig().adminPassword) {
|
|
res.json({ success: true, token: getEnvConfig().adminPassword });
|
|
} else {
|
|
res.status(401).json({ error: 'Falsches Passwort' });
|
|
}
|
|
});
|
|
|
|
app.get('/api/admin/config', requireAdmin, (req, res) => res.json(readConfig()));
|
|
|
|
app.post('/api/admin/config', requireAdmin, (req, res) => {
|
|
try {
|
|
writeConfig(req.body);
|
|
console.log('[api] Config updated');
|
|
res.json({ success: true });
|
|
} catch (e) {
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
app.get('/api/admin/sessions', requireAdmin, (req, res) => res.json(getSessions()));
|
|
|
|
app.get('/api/admin/stats', requireAdmin, async (req, res) => {
|
|
try {
|
|
const config = readConfig();
|
|
if (!config.answersTableId) return res.json({ answers: [] });
|
|
const rows = await listRows(config.answersTableId);
|
|
res.json({ answers: rows });
|
|
} catch (e) {
|
|
console.error('[api] Stats error:', e.message);
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
// Debug endpoint to test Baserow connection
|
|
app.get('/api/admin/debug-baserow', requireAdmin, async (req, res) => {
|
|
try {
|
|
const { baserowUrl, baserowToken } = getEnvConfig();
|
|
const config = readConfig();
|
|
const result = { baserowUrl, tokenLength: baserowToken.length, sets: config.sets, tests: [] };
|
|
for (const set of config.sets) {
|
|
try {
|
|
const rows = await listRows(set.tableId);
|
|
result.tests.push({ set: set.name, tableId: set.tableId, rowCount: rows.length, sampleFields: rows.length > 0 ? Object.keys(rows[0]) : [] });
|
|
} catch (e) {
|
|
result.tests.push({ set: set.name, tableId: set.tableId, error: e.message });
|
|
}
|
|
}
|
|
res.json(result);
|
|
} catch (e) {
|
|
res.status(500).json({ error: e.message });
|
|
}
|
|
});
|
|
|
|
/* ---- SPA routes ---- */
|
|
app.get('/admin', (req, res) => res.sendFile(path.join(__dirname, '..', 'public', 'admin.html')));
|
|
app.get('/present', (req, res) => res.sendFile(path.join(__dirname, '..', 'public', 'present.html')));
|
|
app.get('*', (req, res) => res.sendFile(path.join(__dirname, '..', 'public', 'index.html')));
|
|
|
|
/* ---- Start ---- */
|
|
setupWebSocket(server);
|
|
const { port } = getEnvConfig();
|
|
server.listen(port, '0.0.0.0', () => {
|
|
console.log(`[quizalarm] Server laeuft auf Port ${port}`);
|
|
console.log(`[quizalarm] Baserow URL: ${getEnvConfig().baserowUrl}`);
|
|
console.log(`[quizalarm] Config: ${JSON.stringify(readConfig())}`);
|
|
}); |