From a7359dba5805b8fcf7e2a1931ec615ac0832cbf4 Mon Sep 17 00:00:00 2001 From: 24c02 <163450896+24c02@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:38:15 -0400 Subject: [PATCH] feat: add presign api route --- api/email.js | 16 ++++------------ api/presign.js | 26 ++++++++++++++++++++++++++ util.js | 16 +++++++++++++++- 3 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 api/presign.js diff --git a/api/email.js b/api/email.js index fea51a3..6b150fd 100644 --- a/api/email.js +++ b/api/email.js @@ -1,7 +1,6 @@ -import {redirect, redirect_error, sign} from "../util.js"; +import {gen_shipments_url, redirect, redirect_error, EMAIL_REGEX} from "../util.js"; import {LoopsClient} from "loops"; // sorry -const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ export const config = { runtime: 'edge', }; @@ -14,7 +13,7 @@ export default async function handler(req) { const internal = form.get('internal') console.log(email) console.log(internal) - if (internal && internal !== process.env.INTERNAL_KEY) return redirect("https://www.youtube.com/watch?v=gvdf5n-zI14") + if (internal && internal !== process.env.INTERNAL_KEY) return redirect(process.env.NOPE_URL) if (email === "dinobox@hackclub.com") return redirect_error("that is not your email :3") // huh?? @@ -38,21 +37,14 @@ export default async function handler(req) { console.error(e, e.stack) return redirect_error(`error checking for shipments from that email!
request ID: ${req.headers.get('x-vercel-id')}`) } - if (internal) return redirect(`${process.env.BASE_URL}/shipments?${new URLSearchParams({ - email, - signature: await sign(email), - show_ids: "yep" - }).toString()}`) + if (internal) return redirect(gen_shipments_url(email, true)) try { const loops = new LoopsClient(process.env.LOOPS_API_KEY); await loops.sendTransactionalEmail({ transactionalId: process.env.TRANSACTIONAL_ID, email: email, dataVariables: { - link: `${process.env.BASE_URL}/shipments?${new URLSearchParams({ - email, - signature: await sign(email) - }).toString()}` + link: gen_shipments_url(email) } }); } catch (e) { diff --git a/api/presign.js b/api/presign.js new file mode 100644 index 0000000..7738a3d --- /dev/null +++ b/api/presign.js @@ -0,0 +1,26 @@ +import {redirect, gen_shipments_url, EMAIL_REGEX} from "../util.js"; + +export const config = { + runtime: 'edge', +}; + +export default async function handler(req) { + if (req.method !== 'POST') return redirect(process.env.BASE_URL) + + if (!process.env.PRESIGNING_KEYS.split(',').includes(req.headers.get('authorization'))) + return new Response(null, { + status: 301, + headers: + { + Location: process.env.NOPE_URL, + "x-nice-try": "lol" + } + }); + + const email = await req.text() + if(!email || !EMAIL_REGEX.test(email)) return new Response(':-/', {status: 400}) + + return new Response(await gen_shipments_url(email), { + status: 200, + }); +} diff --git a/util.js b/util.js index 4ce8a30..14b48cf 100644 --- a/util.js +++ b/util.js @@ -1,4 +1,7 @@ // it is what it is + +export const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + export async function sign(text) { const encoder = new TextEncoder(); const key = await crypto.subtle.importKey( @@ -11,7 +14,8 @@ export async function sign(text) { const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(text)); return Array.from(new Uint8Array(signature)).map(b => b.toString(16).padStart(2, '0')).join(''); } -export function redirect(url, additional_headers={}) { + +export function redirect(url, additional_headers = {}) { return new Response(null, { status: 301, headers: { @@ -20,6 +24,16 @@ export function redirect(url, additional_headers={}) { } }); } + export function redirect_error(error_text) { return redirect(`/?error=${encodeURIComponent(error_text)}`) +} + +export async function gen_shipments_url(email, show_ids) { + let params = { + email, + signature: await sign(email), + } + if (show_ids) params.show_ids = "yep" + return `${process.env.BASE_URL}/shipments?${new URLSearchParams(params).toString()}` } \ No newline at end of file