Skip to content

feat(spec-107): backup admin dialog#38

Open
herbie-bot wants to merge 7 commits into
mainfrom
feat/107-backup-admin
Open

feat(spec-107): backup admin dialog#38
herbie-bot wants to merge 7 commits into
mainfrom
feat/107-backup-admin

Conversation

@herbie-bot

Copy link
Copy Markdown

Summary

Admin-only /admin/backup page that proxies the DbBackupClient from com.open-elements:spring-services 1.0.0-SNAPSHOT. An IT admin can verify the backup strategy end-to-end: show service health and metadata, trigger a backup, list backups with a copyable SHA-256, and download a backup file as backup-<createdAt>-<id>.sql.gz.

This is the intentionally minimal v1. Pagination, prod-restriction of the download, and a server-side restore trigger are deferred to follow-up specs.

Spec

  • Spec folder: specs/107-backup-admin/
  • Design: specs/107-backup-admin/design.md
  • Behaviors: specs/107-backup-admin/behaviors.md

Changes

  • Bump com.open-elements:spring-services from 0.17.0 to 1.0.0-SNAPSHOT
  • Add openelements.db-backup.{base-url,api-token,request-timeout} properties to application.yml
  • New backend controller BackupAdminController with four endpoints, gated by @RequiresItAdmin:
    • GET /api/admin/backup/status (combined health + info, partial-render on info failure)
    • POST /api/admin/backup/trigger (passes through alreadyRunning)
    • GET /api/admin/backup/backups (one-to-one DTO mapping; no pagination v1)
    • GET /api/admin/backup/backups/{id}/download (streamed gzip; filename includes timestamp)
  • @ExceptionHandler(DbBackupException) maps every upstream failure to a single generic 503
  • Frontend /admin/backup page with three cards (Status, Trigger, List) — each fetches independently so one card's failure doesn't block the others; download is initiated from row Download buttons via <a href>
  • New sidebar nav entry under the IT-ADMIN admin group (DatabaseBackup icon)
  • DE/EN translation keys under nav.backup and backup.*

Test coverage

  • BackupAdminControllerTest (13 tests) — status / trigger / list / download happy paths and error branches, including filename-with-timestamp + fallback
  • BackupAdminControllerNotConfiguredTest (1 test) — blank token short-circuits without calling the client
  • SecurityRoleIntegrationTest extended with 5 role-gate tests for the new endpoints
  • All 214 backend tests pass (9 pre-existing skipped)

Notes

  • 1.0.0-SNAPSHOT of spring-services is currently published only to GitHub Packages; CI may need credentials or a snapshot-repository config to resolve it. Local dev: mvn install against the upstream repo.

Closes spec 107

🤖 Generated with Claude Code

hendrikebbers and others added 7 commits June 11, 2026 12:06
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings DbBackupClient and the dbbackup DTOs into the classpath.
FullSpringServiceConfig already imports DbBackupConfig, so no
additional @import in CrmApplication is needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds /api/admin/backup/{status,trigger,backups,backups/{id}/download},
each gated by @RequiresItAdmin and proxying DbBackupClient. Includes:

- BackupStatusDto: configured/healthy/info shape, always HTTP 200
- BackupTriggerDto: jobId + alreadyRunning flag
- BackupItemDto: flattened BackupMetadata (trigger enum -> string)
- application.yml: openelements.db-backup.{base-url,api-token,request-timeout}
- @ExceptionHandler maps every DbBackupException to a generic 503
- Download filename: backup-<createdAt>-<id>.sql.gz, fallback backup-<id>.sql.gz

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Frontend mirror of the BackupAdminController:
- /admin/backup page with auth() + ROLE_IT_ADMIN gate
- backup-page-client.tsx with three independent cards (Status, Trigger, List)
- BackupItemDto / BackupStatusDto / BackupTriggerDto types
- getBackupStatus / triggerBackup / getBackups / backupDownloadUrl helpers
- Sidebar entry under the IT-ADMIN admin group with the DatabaseBackup icon
- DE/EN translation keys under nav.backup and backup.*

Backend tests:
- BackupAdminControllerTest covers /status (3 shapes), /trigger (success,
  alreadyRunning, exception), /backups (mapped, empty, exception), and
  /download (happy, metadata fallback, upstream failure, call counts)
- BackupAdminControllerNotConfiguredTest exercises the blank-token branch
- SecurityRoleIntegrationTest extended with /api/admin/backup/* role gates

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Backend: CI couldn't resolve com.open-elements:spring-services:1.0.0-SNAPSHOT
because the artifact lives on GitHub Packages, not Maven Central. Add the
GitHub Packages repository to backend/pom.xml and wire setup-java's
server-username/server-password to GITHUB_ACTOR + GITHUB_TOKEN so the
generated ~/.m2/settings.xml maps server id 'github' to the workflow token.
Add a workflow-level permissions block granting packages: read.

Frontend: pnpm/action-setup@v4 runs from the repo root (the job's
working-directory only affects `run` steps), so without package_json_file
it doesn't find a packageManager declaration. Point it at
frontend/package.json — a pre-existing CI failure on main that this PR
needs out of the way for its own checks to go green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The docker job's backend image build runs ./mvnw inside the container,
which doesn't see the runner's ~/.m2/settings.xml from setup-java. Add a
project-local backend/.mvn/settings.xml that reads GITHUB_ACTOR and
GITHUB_TOKEN from the env, accept them as build ARGs in the Dockerfile,
and forward them from the docker job and from docker-compose.yml.

The Dockerfile invokes mvn with -s .mvn/settings.xml so the github server
credentials are picked up. Defaults to empty strings, so cached local
builds that don't need the snapshot keep working.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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