feat: add presign api route

This commit is contained in:
24c02 2024-09-16 09:38:15 -04:00
parent e2dae17598
commit a7359dba58
3 changed files with 45 additions and 13 deletions

View file

@ -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!<br/>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) {

26
api/presign.js Normal file
View file

@ -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,
});
}

16
util.js
View file

@ -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()}`
}