Skip to content

feat: add per-user trash (soft delete) with scheduled cleanup#79

Merged
DenizAltunkapan merged 1 commit into
Vault-Web:mainfrom
GabrielBBaldez:feature/user-trash-soft-delete
Jun 13, 2026
Merged

feat: add per-user trash (soft delete) with scheduled cleanup#79
DenizAltunkapan merged 1 commit into
Vault-Web:mainfrom
GabrielBBaldez:feature/user-trash-soft-delete

Conversation

@GabrielBBaldez

Copy link
Copy Markdown
Contributor

What

Implements the per-user trash described in #60:

  • Delete moves to trashDELETE /api/files now moves the file into a per-user trash instead of removing it permanently.
  • Restore / permanent delete — new endpoints under /api/files/trash: list, restore (back to the original path), and permanent delete.
  • Auto-purge after 30 days — a scheduled job removes entries once their retention period elapses.

How

  • TrashEntry (+ TrashEntryRepository) persists the trash metadata (original path, deleted-at, size). The file itself is moved into a hidden .trash directory under the user's root, so it stays within the existing validatePath security boundary; .trash is excluded from folder listings and search.
  • TrashService handles move / list / restore / purge and the scheduled cleanup (@Scheduled, enabled via @EnableScheduling). Both are configurable: cloudpage.trash.retention-days (default 30) and cloudpage.trash.cleanup-cron (default daily at 03:00).
  • The trash_entries table is created automatically (ddl-auto=update).

Design notes / open question

  • Trashed files currently still count toward the storage quota until they are purged — happy to change this if you'd prefer they don't.
  • The case you raised in the issue — files removed directly on disk (OS file explorer) rather than through Vault Web — is not handled here. I left it as a follow-up since it needs a filesystem-watching / reconciliation approach and your steer on the direction.

Testing

  • New TrashServiceTest: move-to-trash, restore, permanent delete, scheduled purge of expired entries, and not-found handling.
  • Full backend suite green locally — 98 tests, 0 failures — plus spotless:check and verify.

Closes #60

Copilot AI review requested due to automatic review settings June 13, 2026 14:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, and TrashController endpoints for listing/restore/purge.
  • Updates file deletion to move files to trash instead of permanently deleting them.
  • Excludes .trash from folder listing/search and enables scheduling for retention-based cleanup; adds unit tests for TrashService.

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.

Comment thread backend/src/main/java/cloudpage/service/FolderService.java
Comment thread backend/src/main/java/cloudpage/service/TrashService.java Outdated
Comment thread backend/src/main/java/cloudpage/service/TrashService.java
Comment thread backend/src/main/java/cloudpage/service/TrashService.java Outdated
Comment thread backend/src/main/java/cloudpage/controller/TrashController.java
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.
@GabrielBBaldez GabrielBBaldez force-pushed the feature/user-trash-soft-delete branch from cfdc69d to fa39358 Compare June 13, 2026 15:17
@GabrielBBaldez

Copy link
Copy Markdown
Contributor Author

Addressed the review feedback in the latest push:

  • restore no longer overwrites a file that already exists at the original path — it throws instead of silently replacing it (avoids data loss if the file was recreated after deletion).
  • If the DB write fails after the file is moved to the trash, the file is moved back — no orphaned trash files.
  • .trash is now hidden only at the root, not for any folder named .trash deeper in the tree.
  • The scheduled purge logs failures instead of swallowing them.
  • Added TrashControllerTest covering the list / restore / permanent-delete endpoints.

@DenizAltunkapan DenizAltunkapan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @GabrielBBaldez would you like to integrate this in the frontend ui?

@DenizAltunkapan DenizAltunkapan removed the request for review from Copilot June 13, 2026 22:39
@DenizAltunkapan DenizAltunkapan merged commit e082062 into Vault-Web:main Jun 13, 2026
1 check passed
@GabrielBBaldez

Copy link
Copy Markdown
Contributor Author

Pushed 6e215c5: restore now returns 409 Conflict (instead of a generic 500) when a file already exists at the original path — added a FileAlreadyExistsException handler in GlobalExceptionHandler plus a regression test. This gives the trash UI in Vault-Web/vault-web#238 a clean status to branch on.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: User Trash (Soft Delete)

3 participants