const test = require("node:test"); const assert = require("node:assert/strict"); const fs = require("fs"); const os = require("os"); const path = require("path"); const request = require("supertest"); const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), "dws-test-")); process.env.DATABASE_PATH = path.join(testRoot, "site.sqlite"); process.env.UPLOAD_DIR = path.join(testRoot, "uploads"); process.env.BACKUP_DIR = path.join(testRoot, "backups"); process.env.SESSION_SECRET = "test-session-secret-with-more-than-thirty-two-characters"; process.env.SETUP_TOKEN = "test-setup-token-with-enough-length"; const { app } = require("../src/server"); function csrfFrom(html) { return /name="_csrf" value="([^"]+)"/.exec(html)?.[1] || ""; } test("public pages load", async () => { for (const path of ["/", "/items", "/services", "/about-contact", "/healthz"]) { const response = await request(app).get(path); assert.equal(response.status < 500, true, `${path} returned ${response.status}`); } }); test("admin redirects to setup or login", async () => { const response = await request(app).get("/admin"); assert.equal([302, 303].includes(response.status), true); }); test("owner setup requires the private setup token", async () => { const agent = request.agent(app); const locked = await agent.get("/admin/setup"); assert.equal(locked.status, 403); const setupPage = await agent.get("/admin/setup?token=test-setup-token-with-enough-length"); assert.equal(setupPage.status, 200); const token = csrfFrom(setupPage.text); const takeover = await agent .post("/admin/setup") .type("form") .send({ _csrf: token, name: "Attacker", email: "attacker@example.com", password: "attacker-password" }); assert.equal(takeover.status, 403); const created = await agent .post("/admin/setup") .type("form") .send({ _csrf: token, setup_token: "test-setup-token-with-enough-length", name: "Owner", email: "owner@example.com", password: "owner-password-123" }); assert.equal(created.status, 302); assert.equal(created.headers.location, "/admin/dashboard"); const dashboard = await agent.get("/admin/dashboard"); assert.equal(dashboard.status, 200); const setupAfterClaim = await agent.get("/admin/setup?token=test-setup-token-with-enough-length"); assert.equal(setupAfterClaim.status, 302); assert.equal(setupAfterClaim.headers.location, "/admin/login"); }); test("multipart admin uploads pass CSRF after form parsing", async () => { const agent = request.agent(app); const loginPage = await agent.get("/admin/login"); const loginToken = csrfFrom(loginPage.text); const login = await agent .post("/admin/login") .type("form") .send({ _csrf: loginToken, email: "owner@example.com", password: "owner-password-123" }); assert.equal(login.status, 302); const mediaPage = await agent.get("/admin/media"); const uploadToken = csrfFrom(mediaPage.text); const sampleImage = path.join(__dirname, "..", "public", "uploads", "sample-hero.png"); const upload = await agent .post("/admin/media") .field("_csrf", uploadToken) .field("title", "Test upload") .field("alt", "Test upload") .attach("images", sampleImage); assert.equal(upload.status, 302); assert.equal(upload.headers.location, "/admin/media"); }); test("contact form requires complete fields", async () => { const agent = request.agent(app); const page = await agent.get("/about-contact"); const token = csrfFrom(page.text); const response = await agent .post("/contact") .send(`_csrf=${encodeURIComponent(token || "")}&name=&email=bad&subject=&message=`); assert.equal(response.status, 400); });