const express = require('express'); const router = express.Router(); const mariadb = require('mariadb'); const reasonFlags = JSON.parse(process.env.REASON_FLAGS) const expressSession = require('express-session'); const bcrypt = require("bcrypt") const crypto = require("crypto") const flags = require('../flags'); const { execSync } = require('child_process'); const { env } = require('process'); const session = require('express-session'); const totp = require('totp-generator').TOTP; // Create a MariaDB connection pool const pool = mariadb.createPool({ host: process.env.DB_HOST, // Replace with your database host port: process.env.DB_PORT || 3306, user: process.env.DB_USER, // Replace with your database username password: process.env.DB_PASS, // Replace with your database password database: process.env.DB_DATABASE, // Replace with your database name connectionLimit: 5 // Adjust connection limit as needed }); router.use(express.json()); router.use(express.urlencoded({ extended: true })); router.use(expressSession({ store: expressSession.MemoryStore(), secret: process.env.SESSION_SECRET || 'default_secret', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', maxAge: 24 * 60 * 60 * 1000 // 24 hours } })); const authenticate = (req, res, next) => { if (!req.session.admin) { res.redirect('/admin/login'); return; } next(); } // MAIN PAGES router.get('/', authenticate, (req, res) => { res.render('admin/dashboard', { env: process.env, session: req.session }); }); router.get('/edit/:id', authenticate, async (req, res) => { const conn = await pool.getConnection(); const id = req.params.id; const row = await conn.query('SELECT * FROM bans WHERE id = ?', [id]); conn.end(); if (!row[0]) { res.redirect('/admin'); return; } res.render('admin/edit', { env: process.env, session: req.session, ban: row[0], reasonFlags, setFlags: flags.getSetFlags(row[0].reasonsFlag, reasonFlags) }); }); // Ban Creation router.get('/create', authenticate, (req, res) => { res.render('admin/create', { env: process.env, session: req.session, reasonFlags }); }); router.post('/create', authenticate, async (req, res) => { const conn = await pool.getConnection(); const data = req.body; if (!data.robloxId && !data.discordId) { res.json({ success: false, message: 'Please enter a Roblox ID or Discord ID.' }); return; } const reasonShort = data.reasonShort || 'No reason provided'; const reasonLong = data.reasonLong || 'No reason provided'; const reasonsFlag = data.reasonsFlag || 0; const moderator = req.session.user.username || 'Unknown'; const expiresTimestamp = data.expiresTimestamp || null; const robloxId = data.robloxId || null; const discordId = data.discordId || null; await conn.query('INSERT INTO bans (reasonShort, reasonLong, reasonsFlag, moderator, expiresTimestamp, robloxId, discordId) VALUES (?, ?, ?, ?, ?, ?, ?)', [reasonShort, reasonLong, reasonsFlag, moderator, expiresTimestamp, robloxId, discordId]); conn.end(); res.json({ success: true, message: 'User banned successfully', redirect: '/admin' }); }); // Ban Editing router.post('/edit/:id', authenticate, async (req, res) => { const conn = await pool.getConnection(); const id = req.params.id; const data = req.body; if (!data.robloxId && !data.discordId) { res.json({ success: false, message: 'Please enter a Roblox ID or Discord ID.' }); return; } const reasonShort = data.reasonShort || 'No reason provided'; const reasonLong = data.reasonLong || 'No reason provided'; const reasonsFlag = data.reasonsFlag || 0; const moderator = req.session.user.username || 'Unknown'; const expiresTimestamp = data.expiresTimestamp || null; const robloxId = data.robloxId || null; const discordId = data.discordId || null; await conn.query('UPDATE bans SET reasonShort = ?, reasonLong = ?, reasonsFlag = ?, moderator = ?, expiresTimestamp = ?, robloxId = ?, discordId = ? WHERE id = ?', [reasonShort, reasonLong, reasonsFlag, moderator, expiresTimestamp, robloxId, discordId, id]); conn.end(); res.json({ success: true, message: 'User updated successfully', redirect: '/admin' }); }); // API STUFF // router.get("/api/bans", authenticate, async (req, res) => { const conn = await pool.getConnection(); const rows = await conn.query('SELECT * FROM bans'); conn.end(); res.json(rows); }); // AUTH STUFF // router.get('/login', (req, res) => { if (req.session.admin) { res.redirect('/admin'); return; } res.render('admin/login', { env: process.env }); }); router.post('/login', async (req, res) => { const conn = await pool.getConnection(); const username = req.body.username; const password = req.body.password; const row = await conn.query('SELECT * FROM users WHERE username = ?', [username]); conn.end(); if (row[0]) { const user = row[0]; const match = await bcrypt.compare(password, user.passwordHash); if (match) { if (user.totp_token) { if (!req.body.totp) { return res.json({ success: false, totpRequired: true, message: 'Please enter your 2FA code!' }); } const generatedToken = totp.generate(user.totp_token).otp; if (req.body.totp !== generatedToken) { return res.json({ success: false, totpRequired: true, message: 'Invalid TOTP token' }); } } req.session.admin = true; req.session.user = user; delete req.session.user.passwordHash; // Security measure return res.json({ success: true, message: 'Login successful', redirect: '/admin' }); } } res.json({ success: false, message: 'Invalid username or password' }); }); router.all('/logout', (req, res) => { req.session.destroy(); res.redirect('/admin/login'); }); module.exports = router;