/** * GET /api/submissions?key=... — read messages for inbox.html. * * Requires the MW_ADMIN_KEY secret. Returns the same shape as server.py: * { ok, count, items: [{ ref, type, data, createdAt, receivedAt }] } */ function json(status, payload) { return new Response(JSON.stringify(payload), { status, headers: { "content-type": "application/json; charset=utf-8", "cache-control": "no-store", "x-content-type-options": "nosniff", "referrer-policy": "same-origin" } }); } /** Length-independent-ish comparison so a wrong key leaks little. */ function safeEqual(a, b) { const A = new TextEncoder().encode(String(a)); const B = new TextEncoder().encode(String(b)); let diff = A.length ^ B.length; const len = Math.max(A.length, B.length); for (let i = 0; i < len; i++) { diff |= (A[i] || 0) ^ (B[i] || 0); } return diff === 0; } export async function onRequestGet({ request, env }) { const expected = env && env.MW_ADMIN_KEY; if (!expected) { return json(500, { ok: false, error: "The inbox key is not set. Add MW_ADMIN_KEY in Cloudflare." }); } const url = new URL(request.url); const key = url.searchParams.get("key") || ""; if (!safeEqual(key, expected)) { return json(401, { ok: false, error: "That key is not correct." }); } if (!env.DB) { return json(500, { ok: false, error: "Message storage is not configured." }); } const requested = parseInt(url.searchParams.get("limit") || "500", 10); const limit = Math.min(Math.max(Number.isFinite(requested) ? requested : 500, 1), 1000); try { const { results } = await env.DB.prepare( "SELECT ref, type, data, page, created_at, received_at FROM submissions ORDER BY id DESC LIMIT ?" ) .bind(limit) .all(); const items = (results || []).map((row) => { let data = {}; try { data = JSON.parse(row.data); } catch (err) { data = {}; } return { ref: row.ref, type: row.type, data, page: row.page || "", createdAt: row.created_at, receivedAt: row.received_at }; }); return json(200, { ok: true, count: items.length, items }); } catch (err) { return json(500, { ok: false, error: "Could not read the messages." }); } }