Skip to content

Add manual backup creation and delete buttons to Update Manager#1255

Open
Sebbeben wants to merge 10 commits intoPart-DB:masterfrom
Sebbeben:feature/update-manager-improvements
Open

Add manual backup creation and delete buttons to Update Manager#1255
Sebbeben wants to merge 10 commits intoPart-DB:masterfrom
Sebbeben:feature/update-manager-improvements

Conversation

@Sebbeben
Copy link
Contributor

@Sebbeben Sebbeben commented Feb 17, 2026

Summary

Adds backup management buttons to the Update Manager and improves Docker support, with security hardening for sensitive operations.

Backup Management

  • "Create Backup" button in the backups tab for on-demand backups
  • Download button for each backup — essential for Docker users since var/backups/ is not a persistent volume
  • Trash icon delete buttons for update logs and backup files
  • Docker support: Backup creation and restore are now available for all installation types, not just git-based installs
  • Docker warning: Info banner when Docker is detected, advising to download backups or mount var/backups/
  • SQLite restore fix: Restore now uses the actual configured DATABASE_URL path instead of hardcoded var/app.db

Security Hardening

  • DISABLE_BACKUP_DOWNLOAD env var (default: 1 = disabled) — backups contain sensitive data (password hashes, secrets), so download is opt-in
  • Password confirmation required before downloading a backup
  • CSRF token validation on all mutating endpoints (create, delete, download, restore, start update)
  • IS_AUTHENTICATED_FULLY check on all critical endpoints to prevent remember-me token abuse
  • Per-backup modals for CSP/Turbo compatibility (no inline JavaScript)

New .env variable

# Disable backup download from the Update Manager UI (0=enabled, 1=disabled).
# Backups contain sensitive data including password hashes and secrets.
# When enabled, users must confirm their password before downloading.
DISABLE_BACKUP_DOWNLOAD=1

Changes

File What changed
UpdateManagerController.php Added UserPasswordHasherInterface, DISABLE_BACKUP_DOWNLOAD env var, IS_AUTHENTICATED_FULLY on critical endpoints, POST download with CSRF + password
BackupManager.php Fixed SQLite restore to use Doctrine's configured path
index.html.twig Per-backup download modals with password confirmation, Docker warning, data-turbo="false" for downloads
.env Added DISABLE_BACKUP_DOWNLOAD=1 default
messages.en.xlf Added translation strings for download, password confirmation, security warning

Testing done

  • Verified DISABLE_BACKUP_DOWNLOAD=1 (default) hides download buttons entirely
  • Verified DISABLE_BACKUP_DOWNLOAD=0 shows download button with password modal
  • Wrong password → flash error, download denied
  • Correct password → backup ZIP downloaded, modal closes
  • Create/delete backup and log with CSRF protection
  • No CSP console errors (no inline JavaScript)
  • All CI checks pass (PHPUnit 12/12, PHPStan, codecov)

@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

❌ Patch coverage is 67.08861% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.26%. Comparing base (32a666f) to head (877e300).
⚠️ Report is 16 commits behind head on master.

Files with missing lines Patch % Lines
src/Controller/UpdateManagerController.php 69.35% 19 Missing ⚠️
src/Services/System/BackupManager.php 0.00% 4 Missing ⚠️
src/Services/System/UpdateExecutor.php 76.92% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1255      +/-   ##
============================================
+ Coverage     55.42%   56.26%   +0.83%     
- Complexity     8266     8291      +25     
============================================
  Files           610      610              
  Lines         26513    26594      +81     
============================================
+ Hits          14694    14962     +268     
+ Misses        11819    11632     -187     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Sebbeben Sebbeben mentioned this pull request Feb 20, 2026
Sebbeben added 5 commits March 3, 2026 21:09
- Add "Create Backup" button in the backups tab for on-demand backups
- Add delete buttons (trash icons) for update logs and backups
- New controller routes with CSRF protection and permission checks
- Use data-turbo-confirm for CSP-safe confirmation dialogs
- Add deleteLog() method to UpdateExecutor with filename validation
…ple from auto-update

- Decouple backup creation/restore UI from can_auto_update so Docker
  and other non-git installations can use backup features
- Add backup download endpoint for saving backups externally
- Fix SQLite restore to use configured DATABASE_URL path instead of
  hardcoded var/app.db (affects Docker and custom SQLite paths)
- Show Docker-specific warning about var/backups/ not being persisted
- Pass is_docker flag to template via InstallationTypeDetector
- Controller tests: auth, CSRF validation, 404 for missing backups, restore disabled check
- UpdateExecutor: deleteLog validation, non-existent file, successful deletion
- BackupManager: deleteBackup validation for missing/non-zip files
@Sebbeben Sebbeben force-pushed the feature/update-manager-improvements branch from 9a82359 to b15074e Compare March 4, 2026 07:45
Sebbeben added 3 commits March 4, 2026 11:31
Add happy-path tests for backup creation, deletion, download,
and log deletion with valid CSRF tokens. Also test the locked
state blocking backup creation.
@jbtronics
Copy link
Member

The ability to download database dumps is quite critical, as it circumvents bascially any protection mechanism of Part-DB and allows access to even normally hidden infos like password hashes, secrets, etc.

Thats why there should be an environment variable to enable/disable the backup download ability.

Also this makes the downloadBackup endpoint quite critical. It should at very least have an CSFR token check.
Maybe make the backup download the response of an POST form submit, where the user has to input his current password (because that is probably the most hard to forge).

Also all more critical endpoints, should also do an $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');, to ensure that the user is not on some old remember me token.

@Sebbeben Sebbeben force-pushed the feature/update-manager-improvements branch from 829b321 to c16b6c7 Compare March 5, 2026 15:53
Sebbeben added 2 commits March 5, 2026 19:06
Address security review feedback from jbtronics:

- Add IS_AUTHENTICATED_FULLY to all sensitive endpoints (create/delete
  backup, delete log, download backup, start update, restore)
- Change backup download from GET to POST with CSRF token
- Require password confirmation before downloading backups (backups
  contain sensitive data like password hashes and secrets)
- Add DISABLE_BACKUP_DOWNLOAD env var (default: disabled) to control
  whether backup downloads are allowed
- Add password confirmation modal with security warning in template
- Add comprehensive tests: auth checks, env var blocking, POST-only
  enforcement, status/progress endpoint auth
- Replace shared modal + inline JS with per-backup modals that have
  filename pre-set in hidden fields (no JavaScript needed)
- Add data-turbo="false" to download forms for native browser handling
- Add data-bs-dismiss="modal" to submit button to auto-close modal
- Add hidden username field for Chrome accessibility best practice
- Fix test: GET on POST-only route returns 404 not 405
@Sebbeben
Copy link
Contributor Author

Sebbeben commented Mar 6, 2026

Thanks for the security review @jbtronics! All suggestions have been implemented:

  • DISABLE_BACKUP_DOWNLOAD env var (default 1 = disabled)
  • ✅ Backup download via POST with CSRF token validation
  • ✅ Password confirmation required before downloading
  • IS_AUTHENTICATED_FULLY on all critical endpoints (createBackup, deleteBackup, deleteLog, downloadBackup, startUpdate, restore)

Screenshot of the password confirmation dialog:

Screenshot 2026-03-06 074855

Tested on a live instance — download works with password verification, wrong passwords are rejected, and the download button is hidden when DISABLE_BACKUP_DOWNLOAD=1 (default).

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.

2 participants