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:
curo1305
2026-05-30 11:51:54 +02:00
parent 9935c06aab
commit 34f012b4e8
4 changed files with 46 additions and 8 deletions
+11
View File
@@ -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
}
+9 -3
View File
@@ -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)
}