feat: verify access code with server before saving (#128)

This commit is contained in:
Dayuan Jiang
2025-12-07 00:21:59 +09:00
committed by GitHub
parent 9f77199272
commit 46567cb0b8
2 changed files with 77 additions and 9 deletions

View File

@@ -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" })
}

View File

@@ -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({
<p className="text-[0.8rem] text-muted-foreground">
Required if the server has enabled access control.
</p>
{error && (
<p className="text-[0.8rem] text-destructive">
{error}
</p>
)}
</div>
<div className="flex items-center justify-between">
<div className="space-y-0.5">
@@ -111,7 +145,9 @@ export function SettingsDialog({
>
Cancel
</Button>
<Button onClick={handleSave}>Save</Button>
<Button onClick={handleSave} disabled={isVerifying}>
{isVerifying ? "Verifying..." : "Save"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>