fix(05): resolve 5 critical code review findings
CR-01: add Field(min_length=1) to UserDeleteConfirm.admin_password
CR-02: add folder ownership check in PATCH /documents/{id} — prevents IDOR
when folder_id belongs to another user
CR-03: add min_length=1, max_length=255, and path-separator validator to
DocumentPatch.filename — prevents empty and path-traversal filenames
CR-04: fetchDocumentContent now throws on non-ok responses instead of
silently returning the error Response
CR-05: object URL revoke in DocumentView uses pagehide + load events with
120s fallback instead of unreliable 60s blind timer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,14 @@ export function confirmUpload(documentId) {
|
||||
return request(`/api/documents/${documentId}/confirm`, { method: 'POST' })
|
||||
}
|
||||
|
||||
export function uploadToCloud(file, provider, folderPath) {
|
||||
const form = new FormData()
|
||||
form.append('file', file)
|
||||
form.append('target_backend', provider)
|
||||
if (folderPath) form.append('cloud_folder_path', folderPath)
|
||||
return request('/api/documents/upload', { method: 'POST', body: form })
|
||||
}
|
||||
|
||||
// ── Topics ───────────────────────────────────────────────────────────────────
|
||||
|
||||
export function listTopics() {
|
||||
@@ -413,6 +421,9 @@ export async function fetchDocumentContent(docId, options = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to fetch document content: ${res.status}`)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
@@ -173,9 +173,15 @@ async function openPdf() {
|
||||
}
|
||||
const blob = await res.blob()
|
||||
const objectUrl = URL.createObjectURL(blob)
|
||||
window.open(objectUrl, '_blank')
|
||||
// Revoke after a delay to allow the new tab to load the content
|
||||
setTimeout(() => URL.revokeObjectURL(objectUrl), 60000)
|
||||
const tab = window.open(objectUrl, '_blank')
|
||||
// Revoke once the new tab has loaded, or after 120s as a fallback.
|
||||
// Also revoke if the user navigates away from this page before the tab loads.
|
||||
const revoke = () => URL.revokeObjectURL(objectUrl)
|
||||
const timer = setTimeout(revoke, 120000)
|
||||
window.addEventListener('pagehide', revoke, { once: true })
|
||||
if (tab) {
|
||||
tab.addEventListener('load', () => { clearTimeout(timer); revoke() }, { once: true })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to open document:', err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user