Add CORS for personal website

This commit is contained in:
2026-06-10 13:12:12 +01:00
parent 34faf0c95d
commit 7a646f16b7
5 changed files with 24 additions and 6 deletions
+1
View File
@@ -42,6 +42,7 @@ jobs:
ADMIN_PASSWORD_HASH=${{ secrets.ADMIN_PASSWORD_HASH }}
DATABASE_PATH=/app/data/rate-my-shots.db
DATA_DIR=/opt/rate-my-shots/data
EXPORT_ALLOWED_ORIGINS=${{ vars.EXPORT_ALLOWED_ORIGINS }}
EOF
- name: Build and deploy
+13 -1
View File
@@ -1,10 +1,22 @@
import type { NextRequest } from "next/server";
import { EXPORT_ALLOWED_ORIGINS } from "@/lib/env";
import { errorResponse, unknownToResponse } from "@/lib/errors";
import { getExportPhotos } from "@/lib/export-queries";
import { getIp } from "@/lib/get-ip";
import { parsePage } from "@/lib/parse-params";
import { checkRateLimit } from "@/lib/rate-limit";
function corsHeaders(request: NextRequest): Record<string, string> {
const origin = request.headers.get("origin");
if (origin && EXPORT_ALLOWED_ORIGINS.includes(origin)) {
return {
"Access-Control-Allow-Origin": origin,
Vary: "Origin",
};
}
return { Vary: "Origin" };
}
export async function GET(request: NextRequest) {
try {
const ip = await getIp();
@@ -18,7 +30,7 @@ export async function GET(request: NextRequest) {
const page = parsePage(sp.get("page"));
const data = await getExportPhotos(seed, page);
return Response.json(data);
return Response.json(data, { headers: corsHeaders(request) });
} catch (e) {
return unknownToResponse(e);
}
+3 -3
View File
@@ -14,14 +14,14 @@ export function AssetStats({ asset }: { asset: PairingAsset }) {
return (
<div className="flex flex-col items-center gap-2 w-full">
{/* Elo + Record */}
<div className="flex items-center gap-3">
<div className="flex items-baseline gap-3">
<span className="text-2xl font-bold tabular-nums tracking-tight">
{formatElo(asset.eloProvisional)}
</span>
<span className="text-xs text-muted uppercase tracking-widest">
<span className="text-xs text-muted tracking-widest">
Elo
</span>
<div className="flex items-center gap-1.5 ml-1">
<div className="flex items-baseline gap-1.5 ml-1">
<span className="text-success text-sm font-semibold tabular-nums">
{asset.winsProvisional}W
</span>
+2 -2
View File
@@ -68,7 +68,7 @@ export function StatsBlock(props: StatsBlockProps) {
<span className="text-5xl font-bold tabular-nums tracking-tight">
{formatElo(props.eloProvisional)}
</span>
<span className="text-sm text-muted uppercase tracking-widest">
<span className="text-sm text-muted tracking-widest">
Elo
</span>
</div>
@@ -105,7 +105,7 @@ export function StatsBlock(props: StatsBlockProps) {
<span className="text-5xl font-bold tabular-nums tracking-tight">
{formatElo(props.eloProvisional)}
</span>
<span className="text-sm text-muted uppercase tracking-widest">
<span className="text-sm text-muted tracking-widest">
Elo
</span>
</div>
+5
View File
@@ -10,3 +10,8 @@ export const IMMICH_URL = required("IMMICH_URL");
export const IMMICH_API_KEY = required("IMMICH_API_KEY");
export const IMMICH_ALBUM_ID = required("IMMICH_ALBUM_ID");
export const ADMIN_PASSWORD_HASH = required("ADMIN_PASSWORD_HASH");
export const EXPORT_ALLOWED_ORIGINS = (process.env.EXPORT_ALLOWED_ORIGINS ?? "")
.split(",")
.map((s) => s.trim())
.filter(Boolean);