import express from "express"; import cookieParser from "cookie-parser"; import http from "node:http"; import createBareServer from "@tomphttp/bare-server-node"; import { uvPath } from "@titaniumnetwork-dev/ultraviolet"; import path from "node:path"; import config from "./deployment.config.json" assert { type: "json" }; import sgMail from "@sendgrid/mail"; import nodemailer from "nodemailer"; import * as uuid from "uuid"; import fs from "node:fs"; import bcrypt from "bcrypt"; const PORT = process.env.PORT || 3000; const __dirname = process.cwd(); const ACTIVE_CODES = new Set(); let TOKENS = fs .readFileSync("./memory.txt", "utf-8") .trim() .split("\n") .map((token) => { const parts = token.split(":"); return { id: parts[0], token: parts[1], expiration: parts[2] }; }); const server = http.createServer(); const app = express(server); const bareServer = createBareServer("/bare/"); // Middleware app.use(cookieParser()); app.use(express.json()); app.use( express.urlencoded({ extended: true }) ); // Verification app.patch("/generate-otp", async (req, res) => { if ( config.sendgrid_verification == true || config.discord_verification == true || config.smtp_verificaton == true ) { const OTP = generateCode(); ACTIVE_CODES.add(OTP); setTimeout(() => { ACTIVE_CODES.delete(OTP); }, 1000 * 60 * 5); let email = { to: "", from: "", subject: `NebulaWEB personal access code ${OTP}`, text: ` ####### ACCESS CODE (OTP) ${OTP} ####### ####### DO NOT SHARE THIS CODE! ####### (this message is automated)` }; if (config.sendgrid_verification == true) { sgMail.setApiKey(config.sendgrid_options.api_key); email.to = config.sendgrid_options.to_email; email.from = config.sendgrid_options.sendFromEmail; try { await sgMail.send(msg); } catch { return res.status(504).end(); } } if (config.smtp_verification == true) { const smtpMailerAgent = nodemailer.createTransport(config.smtp_options); email.to = config.smtp_options.to_email; email.from = config.smtp_options.sendFromEmail; try { smtpMailerAgent.sendMail(email); } catch { return res.status(504).end(); } } if (config.discord_verification == true) { try { await fetch(config.webhook_url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: `Your NebulaWEB access code is \`${OTP}\`` }) }); } catch { return res.status(500).end(); } } res.status(200).end(); } else { res.status(404).end(); } }); function generateCode() { const code = Math.floor(Math.random() * 1000000); return code.toString().padStart(6, "0"); } app.post("/validate-otp", (req, res) => { if ( config.sendgrid_verification == true || config.discord_verification == true || config.smtp_verificaton == true ) { const OTP = req.body.otp; if (ACTIVE_CODES.has(OTP)) { ACTIVE_CODES.delete(OTP); const token = uuid.v4(); TOKENS.push({ id: OTP, token: hash(token), expiration: Date.now() + 1000 * 60 * 60 * 24 * 30 }); fs.writeFileSync( "./memory.txt", TOKENS.map((token) => { return `${token.id}:${token.token}:${token.expiration}`; }).join("\n"), "utf-8" ); res.status(200).json({ success: true, validation: `${OTP}:${token}` }); } else { res.status(401).json({ success: false }); } } else { res.status(404).end(); } }); // Static files app.use("/uv/", express.static(uvPath)); app.use(express.static(path.join(__dirname, "public"))); // Login route app.get("/login", (req, res) => { if ( config.sendgrid_verification == true || config.discord_verification == true || config.smtp_verificaton == true ) { res.sendFile(path.join(__dirname, "src", "unv.html")); } else { res.redirect("/"); } }); // General Routes app.use((req, res, next) => { const verification = req.cookies["validation"]; if (!verification || !validateToken(verification)) { res.redirect("/login"); } else { next(); } }); app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "src", "index.html")); }); app.get("/options", (req, res) => { res.sendFile(path.join(__dirname, "src", "options.html")); }); app.get("/privacy", (req, res) => { res.sendFile(path.join(__dirname, "src", "privacy.html")); }); // Bare Server server.on("request", (req, res) => { if (bareServer.shouldRoute(req)) { bareServer.routeRequest(req, res); } else { app(req, res); } }); server.on("upgrade", (req, socket, head) => { if (bareServer.shouldRoute(req)) { bareServer.routeUpgrade(req, socket, head); } else { socket.end(); } }); server.on("listening", () => { console.log(`Server running at http://localhost:${PORT}/.`); }); server.listen({ port: PORT }); function hash(token) { const salt = bcrypt.genSaltSync(10); return bcrypt.hashSync(token, salt); } function validateToken(verification) { console.log(verification); const [id, token] = verification.split(":"); const tokenData = TOKENS.find((token) => token.id == id); if (!tokenData) { return false; } if (tokenData.expiration < Date.now()) { return false; } return bcrypt.compareSync(token, tokenData.token); }