182 lines
5.7 KiB
JavaScript
182 lines
5.7 KiB
JavaScript
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;
|
|
console.log(data)
|
|
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;
|
|
|
|
// if data.neverExpires == "on" then set expiresTimestamp to null
|
|
if (data.neverExpires == "on") {
|
|
expiresTimestamp = 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; |