From 4a6c7b0637c1d1b2dd85592a001befe539db8a05 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Fri, 17 Jan 2025 10:25:07 +0000 Subject: [PATCH] Merge pull request #22882 from overleaf/jpa-file-tree-script [web] scripts/find_malformed_filetrees: flag missing file hash and folder arrays GitOrigin-RevId: 8561a59856486bd6903f84a99434d0bd81acb175 --- .../web/scripts/find_malformed_filetrees.mjs | 89 +++++++++---------- .../web/scripts/fix_malformed_filetree.mjs | 9 ++ 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/services/web/scripts/find_malformed_filetrees.mjs b/services/web/scripts/find_malformed_filetrees.mjs index 2b3901b510..a5cae0bda4 100644 --- a/services/web/scripts/find_malformed_filetrees.mjs +++ b/services/web/scripts/find_malformed_filetrees.mjs @@ -47,62 +47,59 @@ function findBadPaths(folder) { result.push('name') } - if (folder.folders) { - if (Array.isArray(folder.folders)) { - for (const [i, subfolder] of folder.folders.entries()) { - if (!subfolder || typeof subfolder !== 'object') { - result.push(`folders.${i}`) - continue - } - for (const badPath of findBadPaths(subfolder)) { - result.push(`folders.${i}.${badPath}`) - } + if (folder.folders && Array.isArray(folder.folders)) { + for (const [i, subfolder] of folder.folders.entries()) { + if (!subfolder || typeof subfolder !== 'object') { + result.push(`folders.${i}`) + continue + } + for (const badPath of findBadPaths(subfolder)) { + result.push(`folders.${i}.${badPath}`) } - } else { - result.push('folders') } + } else { + result.push('folders') } - if (folder.docs) { - if (Array.isArray(folder.docs)) { - for (const [i, doc] of folder.docs.entries()) { - if (!doc || typeof doc !== 'object') { - result.push(`docs.${i}`) - continue - } - if (!doc._id) { - result.push(`docs.${i}._id`) - // no need to check further: this doc can be deleted - continue - } - if (typeof doc.name !== 'string' || !doc.name) { - result.push(`docs.${i}.name`) - } + if (folder.docs && Array.isArray(folder.docs)) { + for (const [i, doc] of folder.docs.entries()) { + if (!doc || typeof doc !== 'object') { + result.push(`docs.${i}`) + continue + } + if (!doc._id) { + result.push(`docs.${i}._id`) + // no need to check further: this doc can be deleted + continue + } + if (typeof doc.name !== 'string' || !doc.name) { + result.push(`docs.${i}.name`) } - } else { - result.push('docs') } + } else { + result.push('docs') } - if (folder.fileRefs) { - if (Array.isArray(folder.fileRefs)) { - for (const [i, file] of folder.fileRefs.entries()) { - if (!file || typeof file !== 'object') { - result.push(`fileRefs.${i}`) - continue - } - if (!file._id) { - result.push(`fileRefs.${i}._id`) - // no need to check further: this file can be deleted - continue - } - if (typeof file.name !== 'string' || !file.name) { - result.push(`fileRefs.${i}.name`) - } + if (folder.fileRefs && Array.isArray(folder.fileRefs)) { + for (const [i, file] of folder.fileRefs.entries()) { + if (!file || typeof file !== 'object') { + result.push(`fileRefs.${i}`) + continue + } + if (!file._id) { + result.push(`fileRefs.${i}._id`) + // no need to check further: this file can be deleted + continue + } + if (typeof file.name !== 'string' || !file.name) { + result.push(`fileRefs.${i}.name`) + } + if (typeof file.hash !== 'string' || !file.hash) { + result.push(`fileRefs.${i}.hash`) } - } else { - result.push('fileRefs') } + } else { + result.push('fileRefs') } return result } diff --git a/services/web/scripts/fix_malformed_filetree.mjs b/services/web/scripts/fix_malformed_filetree.mjs index 4182fa8c76..2caf26aac7 100644 --- a/services/web/scripts/fix_malformed_filetree.mjs +++ b/services/web/scripts/fix_malformed_filetree.mjs @@ -29,6 +29,11 @@ async function main() { ) } else if (isName(mongoPath)) { modifiedCount = await fixName(projectId, mongoPath) + } else if (isHash(mongoPath)) { + console.error(`Missing file hash: ${mongoPath}`) + console.error('SaaS: likely needs filestore restore') + console.error('Server Pro: please reach out to support') + process.exit(1) } else { console.error(`Unexpected mongo path: ${mongoPath}`) process.exit(1) @@ -72,6 +77,10 @@ function isName(path) { return /\.name$/.test(path) } +function isHash(path) { + return /\.hash$/.test(path) +} + function parentPath(path) { return path.slice(0, path.lastIndexOf('.')) }