Add folder management, move/rename, and nested path support to User Files#283
Merged
Conversation
…iles
Extend the User Files feature with full directory support: users can now create
folders, navigate into them via breadcrumb navigation, rename and move files or
directories, and delete directories recursively. All new and existing endpoints
are hardened against path traversal attacks.
Backend (api/api.py, api/api_utils.py):
- Add `is_safe_user_path()` utility that resolves symlinks and verifies the
target stays under the user's root directory; applied to every UserFiles,
UserFileContent, and UserFileFolder endpoint
- GET /user/files now accepts `path` (sub-directory listing) and `recursive`
(walk all nested files) query parameters; response includes `name`, `type`
("file" or "directory"), and `relative_path` fields; sorting places
directories before files
- POST /user/files supports nested filenames (e.g. "folder/sub/file.txt") by
auto-creating intermediate directories; dot-filename validation now checks
only the basename so nested paths are accepted
- PUT /user/files (new) moves or renames a file or directory, with conflict
detection and auto-creation of the destination parent directory
- DELETE /user/files now handles directories via `shutil.rmtree` in addition
to single files; response uses `api_response.return_ok()` consistently
- POST /user/files/folder (new `UserFileFolder` resource) creates a directory,
supporting nested paths and rejecting dot-prefixed leaf names
Frontend (app/src/app/UserFiles/*, Constants/constants.tsx):
- Add `createUserFolder`, `moveUserFile`, and `deleteUserFile` helper functions
in constants.tsx; `loadUserFiles` gains `_path` and `_recursive` parameters;
`loadFileContent` URL-encodes the filename for nested paths
- Forms that list user files (APIForm, DocumentForm, TestCaseForm,
TestRunConfigForm, TestCaseImport) now request a recursive listing and
display `relative_path` as the label so nested files are distinguishable
- New form components: `UserFilesCreateFolderForm`, `UserFilesRenameForm`,
`UserFilesMoveForm`, `UserFilesDeleteConfirm`
- `UserFilesModal` becomes a multi-action modal dispatching to the correct form
based on the action (add / edit / create-folder / rename / move / delete);
delete action uses a danger-styled confirm button
- `UserFilesMenuKebab` replaces inline delete logic with a unified `openModal`
helper exposing Edit, Rename, Move, and Delete actions; Edit is hidden for
directories
- `UserFiles` page adds breadcrumb navigation for folder drill-down and a
"New Folder" button; listing refreshes without full page reloads
- `UserFilesListing` shows folder/file icons, clickable folder names for
navigation, and an empty-state message
Tests (api/test/):
- `user_files_test_helpers.py`: add `move_file`, `create_folder` helpers;
`remove_if_exists` now handles directories
- `conftest.py`: `ut_user_files_dir` cleanup removes directories as well
- `test_user_files.py`: new tests for type field, directory-first sorting,
`path` param, path traversal blocking, recursive listing, nested file
creation, directory deletion, move/rename (file, directory, into subfolder,
conflict, empty fields, path traversal)
- `test_user_file_content.py`: new tests for nested file GET/PUT and path
traversal blocking on both endpoints
- `test_user_file_folder.py` (new): tests for folder creation (auth, missing
fields, empty name, dot name, success, nested, conflict, path traversal)
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Collaborator
Author
|
Refers to #224 |
added 4 commits
April 23, 2026 11:50
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
- Fix `add_test_case_to_user_files` command: update button selector from `#btn-user-file-add-confirm` to `#btn-user-file-modal-confirm` to match the renamed confirm button id in the refactored `UserFilesModal` component Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extend the User Files feature with full directory support: users can now create folders, navigate into them via breadcrumb navigation, rename and move files or directories, and delete directories recursively. All new and existing endpoints are hardened against path traversal attacks.
Backend (api/api.py, api/api_utils.py):
is_safe_user_path()utility that resolves symlinks and verifies the target stays under the user's root directory; applied to every UserFiles, UserFileContent, and UserFileFolder endpointpath(sub-directory listing) andrecursive(walk all nested files) query parameters; response includesname,type("file" or "directory"), andrelative_pathfields; sorting places directories before filesshutil.rmtreein addition to single files; response usesapi_response.return_ok()consistentlyUserFileFolderresource) creates a directory, supporting nested paths and rejecting dot-prefixed leaf namesFrontend (app/src/app/UserFiles/*, Constants/constants.tsx):
createUserFolder,moveUserFile, anddeleteUserFilehelper functions in constants.tsx;loadUserFilesgains_pathand_recursiveparameters;loadFileContentURL-encodes the filename for nested pathsrelative_pathas the label so nested files are distinguishableUserFilesCreateFolderForm,UserFilesRenameForm,UserFilesMoveForm,UserFilesDeleteConfirmUserFilesModalbecomes a multi-action modal dispatching to the correct form based on the action (add / edit / create-folder / rename / move / delete); delete action uses a danger-styled confirm buttonUserFilesMenuKebabreplaces inline delete logic with a unifiedopenModalhelper exposing Edit, Rename, Move, and Delete actions; Edit is hidden for directoriesUserFilespage adds breadcrumb navigation for folder drill-down and a "New Folder" button; listing refreshes without full page reloadsUserFilesListingshows folder/file icons, clickable folder names for navigation, and an empty-state messageTests (api/test/):
user_files_test_helpers.py: addmove_file,create_folderhelpers;remove_if_existsnow handles directoriesconftest.py:ut_user_files_dircleanup removes directories as welltest_user_files.py: new tests for type field, directory-first sorting,pathparam, path traversal blocking, recursive listing, nested file creation, directory deletion, move/rename (file, directory, into subfolder, conflict, empty fields, path traversal)test_user_file_content.py: new tests for nested file GET/PUT and path traversal blocking on both endpointstest_user_file_folder.py(new): tests for folder creation (auth, missing fields, empty name, dot name, success, nested, conflict, path traversal)