fix(web): PendingApprovalsCard 批准/拒絕補 CSRF Token — 修復 403
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
根因: fetch 沒帶 X-CSRF-Token header + credentials:include
API 回 403 "CSRF token cookie missing"
修復: 加 useCSRF hook,sign/reject 請求帶 ...getHeaders() + credentials:include
與 incident-card.tsx / openclaw-state-machine.tsx 同一模式
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import { useState, useEffect } from 'react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useLocale } from 'next-intl'
|
||||
import { useCSRF } from '@/hooks/useCSRF'
|
||||
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_URL ?? ''
|
||||
|
||||
@@ -33,6 +34,7 @@ export function PendingApprovalsCard() {
|
||||
const t = useTranslations('dashboard')
|
||||
const router = useRouter()
|
||||
const locale = useLocale()
|
||||
const { getHeaders } = useCSRF()
|
||||
const [approvals, setApprovals] = useState<Approval[]>([])
|
||||
const [actionError, setActionError] = useState<string | null>(null)
|
||||
const [actioningId, setActioningId] = useState<string | null>(null)
|
||||
@@ -83,7 +85,7 @@ export function PendingApprovalsCard() {
|
||||
onClick={() => {
|
||||
setActionError(null)
|
||||
setActioningId(ap.id)
|
||||
fetch(`${API_BASE}/api/v1/approvals/${ap.id}/sign`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ signer: 'web-ui' }) })
|
||||
fetch(`${API_BASE}/api/v1/approvals/${ap.id}/sign`, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', ...getHeaders() }, body: JSON.stringify({ signer: 'web-ui' }) })
|
||||
.then(r => { if (!r.ok) throw new Error(`${r.status}`); return r })
|
||||
.then(() => setApprovals(prev => prev.filter(x => x.id !== ap.id)))
|
||||
.catch(e => setActionError(`approve failed: ${e.message}`))
|
||||
@@ -96,7 +98,7 @@ export function PendingApprovalsCard() {
|
||||
onClick={() => {
|
||||
setActionError(null)
|
||||
setActioningId(ap.id)
|
||||
fetch(`${API_BASE}/api/v1/approvals/${ap.id}/reject`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reason: 'rejected-from-web' }) })
|
||||
fetch(`${API_BASE}/api/v1/approvals/${ap.id}/reject`, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', ...getHeaders() }, body: JSON.stringify({ reason: 'rejected-from-web' }) })
|
||||
.then(r => { if (!r.ok) throw new Error(`${r.status}`); return r })
|
||||
.then(() => setApprovals(prev => prev.filter(x => x.id !== ap.id)))
|
||||
.catch(e => setActionError(`reject failed: ${e.message}`))
|
||||
|
||||
Reference in New Issue
Block a user