Skip to content

Asset Picker: scope the upload flow to the field that opened the picker #37365

Description

@nicobytes

Problem Statement

Split out of #37174 (finding 8). The Asset Picker (libs/ui/src/lib/components/dot-asset-picker) already restricts what you can browse to the field that opened it, but not what you can upload. An Image field, or a Story Block dotVideo node, lets you upload any file type from inside the picker — so an Image field can end up holding a PDF and a video node an mp3, exactly the case ASSET_PICKER_MIME_TYPES exists to prevent on the browse side.

Decision taken during refinement: the upload flow is restricted to the mode that opened the picker, using the same restriction config.mimeTypes already applies to browsing.

Root cause notes

  • buildAssetPickerConfig() already knows the entry point: ASSET_PICKER_MIME_TYPES maps image['image/*'], video['video/*'], audio['audio/*'], and config.mimeTypes is applied to every browse request.
  • Nothing carries that restriction into the upload path:
    • the hidden <input type="file" #fileInput hidden /> in dot-asset-picker.component.html has no accept attribute, so the OS dialog offers every file;
    • dot-upload-dropzone accepts any dropped file;
    • dot-upload-type-selector always offers both Asset and File with the same copy regardless of mode;
    • #resolveFilesUpload() / #uploadByBaseType() in dot-asset-picker.component.ts do no type validation before uploading.

Steps to Reproduce

  1. Edit a content type with an Image field and open its asset picker.
  2. Click Upload → the Asset/File popover appears.
  3. Pick either option — the OS file dialog offers every file type, and a PDF or a .zip uploads and lands in an image field's folder just fine.
  4. Repeat from the Story Block /video node: the same unrestricted upload is offered where only video should be.

📎 See Screenshots C and D on #37174 — the Asset/File upload popover (identical in every mode) and the Story Block /video entry point.

Acceptance Criteria

  • The picker's upload flow honours the mode it was opened in: an Image field offers only images, a Story Block dotVideo node only video, dotAudio only audio; the generic File field keeps offering everything
  • The restriction is derived from the config the picker already carries (ASSET_PICKER_MIME_TYPES / config.mimeTypes) — no second, hand-maintained list of types
  • The hidden file input carries a matching accept attribute, so the OS file dialog filters before the user picks
  • The drag-and-drop dropzone rejects a file outside the allowed types and says why, instead of uploading it
  • A file that slips through anyway (accept is a hint, not a guarantee) is rejected client-side before the upload request, with a clear message naming the allowed types
  • The Asset/File type popover reflects the mode — options that cannot apply are not offered, and the copy does not promise "images, documents and media" in a video-only context
  • After a successful scoped upload, the new asset appears in the list and can be selected without reopening the picker

Regression coverage

  • Asset Picker specs cover upload restriction per mode: accept attribute, dropzone rejection, and pre-upload validation
  • The generic File field's unrestricted upload is covered so the scoping does not over-reach

dotCMS Version

Latest from main (includes PR #36848, merged as 8c725747c0).

Severity

Medium - Some functionality impacted

Links

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions