feat: harden production data and backups
This commit is contained in:
@@ -2,14 +2,17 @@ import type { APIRoute } from "astro";
|
||||
|
||||
const base = process.env.API_INTERNAL_URL || import.meta.env.API_INTERNAL_URL || "http://localhost:8000";
|
||||
|
||||
export const POST: APIRoute = async ({ request, redirect }) => {
|
||||
export const POST: APIRoute = async ({ request, redirect, cookies }) => {
|
||||
const form = await request.formData();
|
||||
const reportId = String(form.get("report_id") || "");
|
||||
const screenshot = form.get("screenshot");
|
||||
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(reportId) || !(screenshot instanceof File) || screenshot.size === 0) return redirect(`/report?state=screenshot_error&report_id=${encodeURIComponent(reportId)}`, 303);
|
||||
const cookieName = `rf4-upload-${reportId}`;
|
||||
const uploadToken = cookies.get(cookieName)?.value;
|
||||
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(reportId) || !uploadToken || !(screenshot instanceof File) || screenshot.size === 0) return redirect(`/report?state=screenshot_error&report_id=${encodeURIComponent(reportId)}`, 303);
|
||||
try {
|
||||
const upload = new FormData(); upload.set("screenshot", screenshot);
|
||||
const response = await fetch(`${base}/api/v1/catch-reports/${reportId}/screenshot`, { method: "POST", body: upload });
|
||||
const response = await fetch(`${base}/api/v1/catch-reports/${reportId}/screenshot`, { method: "POST", headers:{"X-Upload-Token":uploadToken}, body: upload });
|
||||
if (response.ok) cookies.delete(cookieName, {path:"/"});
|
||||
return redirect(response.ok ? "/report?state=screenshot_sent" : `/report?state=screenshot_error&report_id=${encodeURIComponent(reportId)}`, 303);
|
||||
} catch { return redirect(`/report?state=screenshot_error&report_id=${encodeURIComponent(reportId)}`, 303); }
|
||||
};
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
import type { APIRoute } from "astro";
|
||||
const base = process.env.API_INTERNAL_URL || import.meta.env.API_INTERNAL_URL || "http://localhost:8000";
|
||||
export const POST: APIRoute = async ({ request, redirect }) => {
|
||||
export const POST: APIRoute = async ({ request, redirect, cookies }) => {
|
||||
const form = await request.formData();
|
||||
const text = (name: string) => String(form.get(name) || "").trim() || null;
|
||||
const number = (name: string) => text(name) ? Number(text(name)) : null;
|
||||
const payload = { fish_slug: String(form.get("fish_slug") || ""), waterbody_slug: String(form.get("waterbody_slug") || ""), x: Number(form.get("x")), y: Number(form.get("y")), weight_g: Number(form.get("weight_g")), bait_name: text("bait_name"), fishing_method: text("fishing_method"), retrieve_method: text("retrieve_method"), retrieve_speed: number("retrieve_speed"), player_name: text("player_name"), comment: text("comment"), website: String(form.get("website") || "") };
|
||||
let createdId: string | null = null;
|
||||
let uploadToken: string | null = null;
|
||||
try {
|
||||
const response = await fetch(`${base}/api/v1/catch-reports`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(payload) });
|
||||
if (!response.ok) return redirect("/report?state=create_error", 303);
|
||||
const created = await response.json();
|
||||
const created = await response.json() as { id?: unknown; screenshot_upload_token?: unknown };
|
||||
if (typeof created.id !== "string" || typeof created.screenshot_upload_token !== "string") return redirect("/report?state=create_error", 303);
|
||||
createdId = created.id;
|
||||
uploadToken = created.screenshot_upload_token;
|
||||
const screenshot = form.get("screenshot");
|
||||
if (screenshot instanceof File && screenshot.size > 0) {
|
||||
const upload = new FormData(); upload.set("screenshot", screenshot);
|
||||
const uploaded = await fetch(`${base}/api/v1/catch-reports/${created.id}/screenshot`, { method: "POST", body: upload });
|
||||
if (!uploaded.ok) return redirect(`/report?state=screenshot_error&report_id=${encodeURIComponent(created.id)}`, 303);
|
||||
const uploaded = await fetch(`${base}/api/v1/catch-reports/${created.id}/screenshot`, { method: "POST", headers: {"X-Upload-Token": created.screenshot_upload_token}, body: upload });
|
||||
if (!uploaded.ok) {
|
||||
cookies.set(`rf4-upload-${created.id}`, created.screenshot_upload_token, {httpOnly:true, sameSite:"strict", secure:import.meta.env.PROD, path:"/", maxAge:3600});
|
||||
return redirect(`/report?state=screenshot_error&report_id=${encodeURIComponent(created.id)}`, 303);
|
||||
}
|
||||
}
|
||||
return redirect("/report?state=sent", 303);
|
||||
}
|
||||
catch { return redirect(createdId ? `/report?state=screenshot_error&report_id=${encodeURIComponent(createdId)}` : "/report?state=create_error", 303); }
|
||||
catch {
|
||||
if (createdId && uploadToken) cookies.set(`rf4-upload-${createdId}`, uploadToken, {httpOnly:true, sameSite:"strict", secure:import.meta.env.PROD, path:"/", maxAge:3600});
|
||||
return redirect(createdId ? `/report?state=screenshot_error&report_id=${encodeURIComponent(createdId)}` : "/report?state=create_error", 303);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user