Commit Graph

611 Commits

Author SHA1 Message Date
Marcel
5d356cd694 feat: add OpenAPI spec (dev only) with typed frontend client
- Add springdoc-openapi 3.0.2 (supports Spring Boot 4) to backend
- Disable api-docs/swagger-ui in application.yaml (prod default)
- Enable both in application-dev.yaml; Swagger UI at /swagger-ui.html
- Add openapi-fetch (runtime) and openapi-typescript (dev) to frontend
- Add generate:api npm script — run with backend up to regenerate types
- Add src/lib/api.server.ts typed client factory (uses SvelteKit fetch)
- Gitignore src/lib/generated/api.ts (generated artifact)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 13:30:57 +01:00
Marcel
4cc86de143 feat: replace raw error messages with structured error codes
Backend now returns { code: ErrorCode, message: string } for all errors,
making it language-agnostic. Frontend maps codes to localised strings via
Paraglide (en/de/es), so translations live in messages/*.json.

- Add ErrorCode enum and DomainException with static factory methods
- Update GlobalExceptionHandler to return ErrorResponse(code, message)
- Replace ResponseStatusException throughout controllers/services/aspects
- Add frontend errors.ts with parseBackendError() and getErrorMessage()
- getErrorMessage() delegates to Paraglide m.error_*() functions
- Add error_* keys to messages/en.json, de.json, es.json
- Update all page.server.ts files to use the new error utilities
- Fix hardcoded localhost URLs in admin and login pages
- Fix missing baseUrl in deleteTag action

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 13:15:28 +01:00
Marcel
ace57e9fc7 feat: add import status tracking to MassImportService
The async import previously ran fire-and-forget with no way to know
if it succeeded, failed, or was still running.

- Add ImportStatus record (state, message, processed count, startedAt)
  and a volatile currentStatus field updated throughout the async run
- POST /api/admin/trigger-import now returns 202 Accepted with initial status
- GET /api/admin/import-status lets callers poll for the current state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:37:09 +01:00
Marcel
82974170e9 fix: make Permission enum complete and grant all permissions to admin group
Three related issues:
- READ_ALL was stored in the DB but missing from the Permission enum
- ADMIN_USER, ADMIN_TAG and ADMIN_PERMISSION were in the enum and used
  in controllers but never granted to any user, making those endpoints
  permanently inaccessible
- No runtime signal when a DB permission string drifts from the enum

Changes:
- Add READ_ALL to Permission enum
- Grant all six permissions to the Administrators group in DataInitializer
- Warn in CustomUserDetailsService when a DB permission string has no
  matching Permission enum value

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:35:42 +01:00
Marcel
35b998a0e8 refactor: remove unused Spring Session JDBC dependency and tables
Spring Session was pulled in as a dependency but never used — auth is
stateless HTTP Basic, so sessions are never written. Removed:
- spring-boot-starter-session-jdbc (and test variant) from pom.xml
- spring_session and spring_session_attributes tables/indexes/constraints
  from V1__initial_schema.sql

Added V2 migration to drop the tables on existing databases that already
ran V1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:32:38 +01:00
Marcel
e89dd5dc3c docs: document why CSRF is intentionally disabled in SecurityConfig
The previous comment implied CSRF was disabled as a temporary dev
convenience. Replaced it with an explanation of why it is safe with
the current Authorization-header-based auth scheme, and added a
clear note on when it must be re-enabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:27:50 +01:00
Marcel
d50cfc7718 fix: remove duplicate 'Admins' group from dev data initializer
initData was creating an 'Admins' group with identical permissions to
the 'Administrators' group already created by initAdminUser, resulting
in two redundant groups on every fresh start. Removed the duplicate,
dropped the now-unused groupRepo parameter, and corrected the log
message which claimed 50 persons were created when only 4 were.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:26:22 +01:00
Marcel
adee746b23 refactor: migrate to YAML config and add Maven dev/prod profiles
- Replace application.properties with application.yaml (base/prod config)
  and application-dev.yaml (dev overrides: show-sql=true)
- Add Maven 'dev' profile (activeByDefault) and 'prod' profile to pom.xml;
  spring-boot:run picks up the active Spring profile automatically
- Guard DataInitializer.initData with @Profile("dev") so test data is
  never seeded in production

Local dev: ./mvnw spring-boot:run (dev profile active by default)
Production: SPRING_PROFILES_ACTIVE env var controls the Spring profile;
            Maven profiles are irrelevant for the packaged JAR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:21:16 +01:00
Marcel
107cec8a2f fix: remove plaintext password from startup log in DataInitializer
The log statement revealed the default admin password in application
logs. Now only the username is logged, using the resolved variable
instead of a hardcoded string.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:16:27 +01:00
Marcel
09ec2103c8 fix: correct malformed @Value annotations in DataInitializer
Missing closing braces caused Spring to inject the literal placeholder
string instead of resolving the property, silently ignoring any
app.admin.username / app.admin.password env-var overrides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 12:16:00 +01:00
Marcel
e63adb964d restructure: flatten workspace nesting, move devcontainer to root
- backend/workspaces/backend/ → backend/
- backend/workspaces/frontend/ → frontend/
- backend/.devcontainer/ + .vscode/ → repo root (where VS Code expects them)
- loose scripts/SQL files → scripts/
- replace nested git repo with single repo at project root
- update docker-compose.yml build context and devcontainer.json path
- add root .gitignore

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 11:47:58 +01:00