Enforce admin CSRF, harden catalog translate, use CMS hotel name for PayPal.
Local Build and Deploy / deploy (push) Successful in 1m38s

Mutating withAdmin routes now require a double-submit CSRF token; translate is capped at 500 items with audit logging; PayPal descriptions prefer siteSettings hotel_name.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-18 19:38:42 +02:00
1 parent 6b884ad25a
commit 2de3696993
18 files changed
+218 -62

No files matched your search

@@ -52,6 +52,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { NitroEditorDialog } from "./nitro-editor-dialog";
import { adminFetch } from "@/lib/admin-fetch";
interface FurniItem {
id: number;
@@ -222,7 +223,7 @@ export function ImportFurniClient() {
const fetchStats = useCallback(async () => {
try {
const res = await fetch("/api/admin/import/furni?action=stats");
const res = await adminFetch("/api/admin/import/furni?action=stats");
const data = await res.json();
if (res.ok) {
setStats({
@@ -327,7 +328,7 @@ export function ImportFurniClient() {
if (status === "missing-nitro") {
params.set("action", "missing-nitro");
}
const res = await fetch(`/api/admin/import/furni?${params}`);
const res = await adminFetch(`/api/admin/import/furni?${params}`);
const data = await res.json();
if (!res.ok) {
setError(data.error || "Failed to load");
@@ -417,7 +418,7 @@ export function ImportFurniClient() {
async function doImport(item: FurniItem) {
setImportingId(item.classname);
try {
const res = await fetch("/api/admin/import/furni", {
const res = await adminFetch("/api/admin/import/furni", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -483,7 +484,7 @@ export function ImportFurniClient() {
setBatchProgress(new Map(initialProgress));
try {
const res = await fetch("/api/admin/import/furni/batch", {
const res = await adminFetch("/api/admin/import/furni/batch", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -590,7 +591,7 @@ export function ImportFurniClient() {
async function regenNitro(item: FurniItem) {
setRegeneratingNitro((prev) => new Set(prev).add(item.classname));
try {
const res = await fetch("/api/admin/import/furni", {
const res = await adminFetch("/api/admin/import/furni", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -640,7 +641,7 @@ export function ImportFurniClient() {
setRegenProgress(new Map(initialProgress));
try {
const res = await fetch("/api/admin/import/furni/batch-regen", {
const res = await adminFetch("/api/admin/import/furni/batch-regen", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -753,7 +754,7 @@ export function ImportFurniClient() {
async function startReorganize() {
setReorganizing(true);
try {
const previewRes = await fetch("/api/admin/import/furni?dryrun=1", {
const previewRes = await adminFetch("/api/admin/import/furni?dryrun=1", {
method: "PUT",
});
const previewData = await previewRes.json();
@@ -779,7 +780,7 @@ export function ImportFurniClient() {
setReorgPreview(null);
setReorganizing(true);
try {
const res = await fetch("/api/admin/import/furni", { method: "PUT" });
const res = await adminFetch("/api/admin/import/furni", { method: "PUT" });
const d = await res.json();
if (res.ok) {
const parts: string[] = [];
@@ -31,6 +31,7 @@ import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import { adminFetch } from "@/lib/admin-fetch";
interface NitroEditorDialogProps {
classname: string;
@@ -121,7 +122,7 @@ export function NitroEditorDialog({
setLoading(true);
setJsonError(null);
try {
const res = await fetch(
const res = await adminFetch(
`/api/admin/import/furni/nitro-editor?classname=${encodeURIComponent(classname)}`,
);
if (!res.ok) {
@@ -189,7 +190,7 @@ export function NitroEditorDialog({
setSaving(true);
try {
const res = await fetch("/api/admin/import/furni/nitro-editor", {
const res = await adminFetch("/api/admin/import/furni/nitro-editor", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({