feat(website): Mirror backend filename validation in website - #7218
feat(website): Mirror backend filename validation in website#7218tombch wants to merge 14 commits into
Conversation
|
This PR may be related to: #7056 (Allowed characters |
|
Claude finished @tombch's task in 7m 13s —— View job Code reviewReviewed against Findings are in inline comments; nothing blocking. The two most substantive:
Smaller items, all inline: message-truncation punctuation and a per-file Testing. Documentation. Neither No security or performance concerns. This is defence-in-depth in front of validation the backend still enforces, so bypassing the client-side check gains nothing. Validation is O(n) over filenames with no unbounded regex backtracking. Verification note: I could not run
|
| const folderNames = files.flatMap((f) => f.webkitRelativePath.split('/').slice(1, -1)); | ||
| const fileNames = files.map((f) => f.name); | ||
|
|
||
| if (fileNames.some((n) => /\s/.test(n))) return 'File names cannot contain whitespace.'; | ||
| if (folderNames.some((p) => /\s/.test(p))) return 'Folder names cannot contain whitespace.'; | ||
|
|
||
| const fileNameValidationResult = validateFileNames(fileNames, fileSharingConfig); | ||
| if (fileNameValidationResult.isErr()) { | ||
| return 'Encountered errors in uploaded files: ' + getFileNameErrorMessage(fileNameValidationResult.error); | ||
| } |
There was a problem hiding this comment.
Two things worth confirming are intentional:
-
Bulk mode is now stricter than the backend. In bulk mode the name that reaches the backend is the metadata
name, not the uploaded basename —fileMapping.ts:321lets a row declarereads.fastq::文件.fastq, and the backend only validatesreads.fastq. That submission is valid server-side, but this check rejects the upload because the file on disk is文件.fastq. Inform/individual mode the path is used as its own name (fileMapping.ts:233), so validating basenames there is correct and necessary. If the over-strictness in bulk mode isn't wanted, the strict portion could be limited toinputMode === 'form'. -
Folder names are still only whitespace-checked (line 543) while file names now get the full ruleset, so under strict config a folder
data#1or文件passes but a file with those characters doesn't. That may be fine given folder names never reach the backend, but the error strings also now differ in style (Folder names cannot contain whitespace.vsEncountered errors in uploaded files: Invalid filename '…': …), which reads inconsistently when both appear in the same UI.
There was a problem hiding this comment.
The situation described here although valid, is basically never going to happen and it'd be more confusing if the folder component sometimes validated and sometimes didn't
There was a problem hiding this comment.
Agree we should not check the folder names, I think it would also be consistent to only check the defined fileNames that are sent to the backend and not the "true" fileNames - but I also think this is an uncommon situation and is more complicated as this comes from parsing the metadata file and not the actual file names - so we could also do that in a later PR
There was a problem hiding this comment.
or actually, could we just remove the validation here any only do the validation on the file mapping? that seems more correct, less code and potentially less passing down of the FileSharingConfig config?
There was a problem hiding this comment.
Yeah could do it just on the file mapping! the only thing you'd lose is the rejecting of files with invalid names before they can even be uploaded. But I guess that's not really a huge benefit and only makes total sense for the form upload anyway?
…ect/loculus into website-filename-validation
18f74fc to
cd5e8cb
Compare
| * - Trailing periods: Windows silently strips these, and single or double period names break path normalisation | ||
| * - Whitespace characters | ||
| * | ||
| * The website mirrors this validation in fileNameValidation.ts - any changes here must also be made there. |
| }); | ||
| export type SequenceFlaggingConfig = z.infer<typeof sequenceFlaggingConfig>; | ||
|
|
||
| export const fileSharingConfig = z.object({ disableStrictFilenameValidation: z.boolean().default(false) }); |
There was a problem hiding this comment.
the config can also have the field outputFileUrlType - will zod have any issues if this field is in the input?
There was a problem hiding this comment.
No zod will just ignore it as it's not declared in the fileSharingConfig. We could have it just pass the disableStrictFilenameValidation flag only in the website, but I thought to do fileSharing as I think it looks nicer and more extensible if we wanted other props in the future?
resolves #
Summary
FolderUploadComponent), as well as filenames declared in the metadata TSV (viaparseSubmissionFileMappingcalled inFormOrUploadWrapper).Screenshot
Files with invalid names are rejected before upload:
Invalid file names declared in the metadata also raise a toast that blocks submission:
PR Checklist
🚀 Preview: Add
previewlabel to enable