Add CORS for personal website
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user