feat: add per-user trash (soft delete) with scheduled cleanup#79
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a per-user “trash” (soft-delete) feature: deleted files are moved to a hidden .trash directory, tracked in DB, restorable/purgeable via API, and automatically cleaned up on a schedule.
Changes:
- Introduces
TrashService,TrashEntry(entity),TrashEntryRepository, andTrashControllerendpoints for listing/restore/purge. - Updates file deletion to move files to trash instead of permanently deleting them.
- Excludes
.trashfrom folder listing/search and enables scheduling for retention-based cleanup; adds unit tests forTrashService.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| backend/src/main/java/cloudpage/service/TrashService.java | Implements soft-delete, restore, purge, and scheduled retention cleanup |
| backend/src/main/java/cloudpage/controller/TrashController.java | Adds REST endpoints for trash operations |
| backend/src/main/java/cloudpage/controller/FileController.java | Switches delete behavior to trash soft-delete |
| backend/src/main/java/cloudpage/service/FolderService.java | Filters .trash from listing/search results |
| backend/src/main/java/cloudpage/model/TrashEntry.java | Adds DB entity for trashed files metadata |
| backend/src/main/java/cloudpage/repository/TrashEntryRepository.java | Adds repository methods used by trash service |
| backend/src/main/java/cloudpage/dto/TrashEntryDto.java | Adds DTO for trash listing output |
| backend/src/main/java/cloudpage/Application.java | Enables scheduling for periodic purge |
| backend/src/test/java/cloudpage/service/TrashServiceTest.java | Adds tests for trash service behavior |
| backend/src/test/java/cloudpage/controller/FileControllerTest.java | Updates deletion test to assert soft-delete behavior |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Deleting a file now moves it into a per-user trash instead of removing it permanently. Trashed files can be listed, restored to their original location, or permanently deleted, and are purged automatically after a configurable retention period (30 days by default). - TrashEntry / TrashEntryRepository persist the metadata; the file is moved into a hidden .trash directory under the user's root, which keeps it inside the existing path security boundary and is excluded from folder listings. - TrashController exposes list / restore / permanent-delete; DELETE /api/files now soft-deletes. - A scheduled job (@EnableScheduling) removes entries past the retention period, configurable via cloudpage.trash.retention-days and cloudpage.trash.cleanup-cron.
cfdc69d to
fa39358
Compare
|
Addressed the review feedback in the latest push:
|
DenizAltunkapan
left a comment
There was a problem hiding this comment.
Thanks @GabrielBBaldez would you like to integrate this in the frontend ui?
|
Pushed |
What
Implements the per-user trash described in #60:
DELETE /api/filesnow moves the file into a per-user trash instead of removing it permanently./api/files/trash: list, restore (back to the original path), and permanent delete.How
TrashEntry(+TrashEntryRepository) persists the trash metadata (original path, deleted-at, size). The file itself is moved into a hidden.trashdirectory under the user's root, so it stays within the existingvalidatePathsecurity boundary;.trashis excluded from folder listings and search.TrashServicehandles move / list / restore / purge and the scheduled cleanup (@Scheduled, enabled via@EnableScheduling). Both are configurable:cloudpage.trash.retention-days(default 30) andcloudpage.trash.cleanup-cron(default daily at 03:00).trash_entriestable is created automatically (ddl-auto=update).Design notes / open question
Testing
TrashServiceTest: move-to-trash, restore, permanent delete, scheduled purge of expired entries, and not-found handling.spotless:checkandverify.Closes #60