99 lines
3.0 KiB
JavaScript
99 lines
3.0 KiB
JavaScript
require('dotenv').config({ path: process.env.ENV_FILE || '../.env' });
|
|
const express = require('express');
|
|
const session = require('express-session');
|
|
const path = require('path');
|
|
const fetch = require('node-fetch');
|
|
|
|
const app = express();
|
|
const PORT = parseInt(process.env.SETTINGS_PORT) || 12752;
|
|
const INTERNAL_URL = `http://127.0.0.1:${process.env.INTERNAL_API_PORT || 12753}/internal`;
|
|
const SECRET = process.env.INTERNAL_API_SECRET;
|
|
const ADMIN_PASSWORD = process.env.SETTINGS_ADMIN_PASSWORD;
|
|
|
|
app.use(express.json());
|
|
app.use(express.urlencoded({ extended: true }));
|
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
app.use(session({
|
|
secret: SECRET || 'fallback-secret-change-me',
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
httpOnly: true,
|
|
secure: false, // set true if behind HTTPS proxy
|
|
maxAge: 8 * 60 * 60 * 1000 // 8 hours
|
|
}
|
|
}));
|
|
|
|
// Auth middleware
|
|
function requireAuth(req, res, next) {
|
|
if (req.session?.authed) return next();
|
|
res.redirect('/login');
|
|
}
|
|
|
|
// Internal API proxy helper
|
|
async function callBot(method, apiPath, body) {
|
|
const res = await fetch(`${INTERNAL_URL}${apiPath}`, {
|
|
method,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-internal-secret': SECRET
|
|
},
|
|
body: body ? JSON.stringify(body) : undefined
|
|
});
|
|
return res.json();
|
|
}
|
|
|
|
// Routes
|
|
app.get('/login', (req, res) => {
|
|
if (req.session?.authed) return res.redirect('/');
|
|
res.sendFile(path.join(__dirname, 'public', 'login.html'));
|
|
});
|
|
|
|
app.post('/login', (req, res) => {
|
|
if (!ADMIN_PASSWORD) return res.status(503).json({ error: 'SETTINGS_ADMIN_PASSWORD not set' });
|
|
if (req.body.password === ADMIN_PASSWORD) {
|
|
req.session.authed = true;
|
|
return res.json({ ok: true });
|
|
}
|
|
res.status(401).json({ error: 'Invalid password' });
|
|
});
|
|
|
|
app.post('/logout', (req, res) => {
|
|
req.session.destroy();
|
|
res.redirect('/login');
|
|
});
|
|
|
|
app.get('/', requireAuth, (req, res) => {
|
|
res.sendFile(path.join(__dirname, 'public', 'index.html'));
|
|
});
|
|
|
|
// Proxy to bot internal API
|
|
app.get('/api/config', requireAuth, async (req, res) => {
|
|
try { res.json(await callBot('GET', '/config')); }
|
|
catch (e) { res.status(502).json({ error: 'Bot unreachable' }); }
|
|
});
|
|
|
|
app.post('/api/config', requireAuth, async (req, res) => {
|
|
try { res.json(await callBot('POST', '/config', req.body)); }
|
|
catch (e) { res.status(502).json({ error: 'Bot unreachable' }); }
|
|
});
|
|
|
|
app.get('/api/discord/guild', requireAuth, async (req, res) => {
|
|
try { res.json(await callBot('GET', '/discord/guild')); }
|
|
catch (e) { res.status(502).json({ error: 'Bot unreachable' }); }
|
|
});
|
|
|
|
app.post('/api/restart', requireAuth, async (req, res) => {
|
|
try { res.json(await callBot('POST', '/restart', req.body)); }
|
|
catch (e) { res.status(502).json({ error: 'Bot unreachable' }); }
|
|
});
|
|
|
|
app.get('/api/restart/status', requireAuth, async (req, res) => {
|
|
try { res.json(await callBot('GET', '/restart/status')); }
|
|
catch (e) { res.status(502).json({ error: 'Bot unreachable' }); }
|
|
});
|
|
|
|
app.listen(PORT, '0.0.0.0', () => {
|
|
console.log(`[settings] running on port ${PORT}`);
|
|
});
|