diff --git a/app/api/verify-access-code/route.ts b/app/api/verify-access-code/route.ts new file mode 100644 index 0000000..d69f59d --- /dev/null +++ b/app/api/verify-access-code/route.ts @@ -0,0 +1,32 @@ +export async function POST(req: Request) { + const accessCodes = + process.env.ACCESS_CODE_LIST?.split(",") + .map((code) => code.trim()) + .filter(Boolean) || [] + + // If no access codes configured, verification always passes + if (accessCodes.length === 0) { + return Response.json({ + valid: true, + message: "No access code required", + }) + } + + const accessCodeHeader = req.headers.get("x-access-code") + + if (!accessCodeHeader) { + return Response.json( + { valid: false, message: "Access code is required" }, + { status: 401 }, + ) + } + + if (!accessCodes.includes(accessCodeHeader)) { + return Response.json( + { valid: false, message: "Invalid access code" }, + { status: 401 }, + ) + } + + return Response.json({ valid: true, message: "Access code is valid" }) +} diff --git a/components/settings-dialog.tsx b/components/settings-dialog.tsx index 298aef7..b5570b2 100644 --- a/components/settings-dialog.tsx +++ b/components/settings-dialog.tsx @@ -30,6 +30,8 @@ export function SettingsDialog({ }: SettingsDialogProps) { const [accessCode, setAccessCode] = useState("") const [closeProtection, setCloseProtection] = useState(true) + const [isVerifying, setIsVerifying] = useState(false) + const [error, setError] = useState("") useEffect(() => { if (open) { @@ -42,17 +44,44 @@ export function SettingsDialog({ ) // Default to true if not set setCloseProtection(storedCloseProtection !== "false") + setError("") } }, [open]) - const handleSave = () => { - localStorage.setItem(STORAGE_ACCESS_CODE_KEY, accessCode.trim()) - localStorage.setItem( - STORAGE_CLOSE_PROTECTION_KEY, - closeProtection.toString(), - ) - onCloseProtectionChange?.(closeProtection) - onOpenChange(false) + const handleSave = async () => { + setError("") + setIsVerifying(true) + + try { + // Verify access code with server + const response = await fetch("/api/verify-access-code", { + method: "POST", + headers: { + "x-access-code": accessCode.trim(), + }, + }) + + const data = await response.json() + + if (!data.valid) { + setError(data.message || "Invalid access code") + setIsVerifying(false) + return + } + + // Save settings only if verification passes + localStorage.setItem(STORAGE_ACCESS_CODE_KEY, accessCode.trim()) + localStorage.setItem( + STORAGE_CLOSE_PROTECTION_KEY, + closeProtection.toString(), + ) + onCloseProtectionChange?.(closeProtection) + onOpenChange(false) + } catch { + setError("Failed to verify access code") + } finally { + setIsVerifying(false) + } } const handleKeyDown = (e: React.KeyboardEvent) => { @@ -87,6 +116,11 @@ export function SettingsDialog({

Required if the server has enabled access control.

+ {error && ( +

+ {error} +

+ )}
@@ -111,7 +145,9 @@ export function SettingsDialog({ > Cancel - +