This commit is contained in:
Soph :3 2025-10-31 19:55:07 +02:00
parent 44020d24e4
commit 07fb985a3a

View file

@ -8,19 +8,53 @@ import { readFileSync } from "node:fs";
import { minify } from "uglify-js"; import { minify } from "uglify-js";
const app = express(); const app = express();
const allowedSites = new Set(
(process.env.ALLOWED_SITES || "")
.split(",")
.map(s => s.trim().toLowerCase())
.filter(Boolean)
);
const clientJS = const clientJS =
minify(readFileSync("src/clientAnalytics.js", "utf8")).code; minify(readFileSync("src/clientAnalytics.js", "utf8")).code;
app.use(bodyParser.json({ limit: "512kb" })); app.use(bodyParser.json({ limit: "512kb" }));
app.use( app.use(
cors() cors({
origin: (origin, callback) => {
if (!origin) return callback(null, true);
try {
const host = new URL(origin).hostname.toLowerCase();
if (allowedSites.size === 0 || allowedSites.has(host)) {
return callback(null, true);
}
return callback(new Error("Not allowed by CORS"));
} catch {
return callback(new Error("Invalid Origin"));
}
},
methods: ["GET", "POST", "OPTIONS"],
allowedHeaders: ["Content-Type"],
})
); );
if (process.env.TRUST_PROXY) { if (process.env.TRUST_PROXY) {
app.set("trust proxy", true); app.set("trust proxy", true);
} }
app.options("*path", (req, res) => { app.options("*path", (req, res) => {
res.set("Access-Control-Allow-Origin", "*"); const origin = req.get("Origin") || "";
let ok = true;
if (allowedSites.size > 0) {
try {
const host = new URL(origin).hostname.toLowerCase();
ok = allowedSites.has(host);
} catch {
ok = false;
}
}
if (!ok) return res.sendStatus(403);
res.set("Vary", "Origin");
res.set("Access-Control-Allow-Origin", origin || "*");
res.set("Access-Control-Allow-Methods", "GET,POST,OPTIONS"); res.set("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
res.set("Access-Control-Allow-Headers", "Content-Type"); res.set("Access-Control-Allow-Headers", "Content-Type");
res.sendStatus(204); res.sendStatus(204);
@ -108,6 +142,10 @@ app.post("/some-cool-endpoint", (req, res) => {
} catch (err) { } catch (err) {
} }
} }
site = (site || "").toLowerCase();
if (allowedSites.size > 0 && !allowedSites.has(site)) {
return res.sendStatus(403);
}
eventCounter.labels(site, e.type, country, device, browser, os).inc(); eventCounter.labels(site, e.type, country, device, browser, os).inc();
@ -136,9 +174,14 @@ app.get("/js", async (req, res) => {
const partial_url = req.protocol + "://" + req.get("host"); const partial_url = req.protocol + "://" + req.get("host");
const url = new URL(partial_url + req.url); const url = new URL(partial_url + req.url);
const id = url.searchParams.get("site") || url.hostname; const id = (url.searchParams.get("site") || url.hostname || "").toLowerCase();
if (allowedSites.size > 0 && !allowedSites.has(id)) {
res.status(403).send("site not allowed");
return;
}
res.set('Content-Type', 'text/javascript') res.set('Content-Type', 'text/javascript')
res.set('Vary', 'Origin')
res.end(clientJS.replace( res.end(clientJS.replace(
"some_misc_string", partial_url "some_misc_string", partial_url
).replace("some_site_string", id) ).replace("some_site_string", id)