Files
Mitgliederverwaltung/.plans/done/issue-48-encrypted-export.md
shahondin1624 b29a268b1d Restructure .plans/ into done/ and open/ subdirectories
- Move completed plan files to .plans/done/
- Move 18 open plan files to .plans/open/
- Update .gitignore to exclude .verified_plans temp file
- Verified all 18 open plans still describe unimplemented issues
2026-04-28 20:30:55 +02:00

3.3 KiB

Plan: Issue #48 — Encrypted export (password-protected ZIP)

Summary

Add encrypted export functionality that wraps sensitive CSV/PDF export files in AES-256 password-protected ZIP archives. The user provides a password at export time, and only users with banking visibility can export banking reports. All sensitive exports are audit-logged.

Existing Code Context

  • EncryptionService.php — field-level encryption (Issue #60), NOT file-level
  • CsvExportService.php — generates CSV exports with UTF-8 BOM
  • ExportController.php — REST endpoints for CSV downloads
  • AuditService.php — audit logging with field-level diffs
  • PermissionService.php — access control with canSeeBanking() method
  • Routes in appinfo/routes.php

Implementation Steps

Step 1: Create EncryptedExportService

File: lib/Service/EncryptedExportService.php

Service that wraps any export content (CSV or PDF binary) in a password-protected ZIP.

class EncryptedExportService {
    // Dependencies: AuditService, PermissionService, IUserSession, LoggerInterface
    
    // createEncryptedZip(string $content, string $filename, string $password): string
    //   - Creates temp ZipArchive
    //   - Sets encryption to AES-256 (ZipArchive::EM_AES_256)
    //   - Adds content as file inside ZIP
    //   - Returns ZIP binary
    //   - Cleanup: unlink temp files
    
    // createEncryptedExport(string $content, string $innerFilename, string $password, string $userId, string $exportType): array
    //   - Permission check for sensitive exports
    //   - Calls createEncryptedZip
    //   - Audit logs the export
    //   - Returns {content: binary, filename: "Export_encrypted_<date>.zip"}
}

Step 2: Add Encrypted Export Endpoints to ExportController

File: lib/Controller/ExportController.php

Add new endpoints that accept a password POST parameter and return encrypted ZIPs:

  • POST /api/v1/export/members/encrypted — encrypted member list
  • POST /api/v1/export/fees/encrypted — encrypted fee records
  • POST /api/v1/export/birthdays/encrypted — encrypted birthday list
  • POST /api/v1/export/banking/encrypted — encrypted banking data (requires canSeeBanking)

POST method used because password must not appear in URL/query string.

Step 3: Add Banking Export to CsvExportService

File: lib/Service/CsvExportService.php

Add exportBankingList() method that exports IBAN/Kontoinhaber data (decrypted) for members. This is a sensitive export that requires banking permission.

Step 4: Register New Routes

File: appinfo/routes.php

Add routes for the encrypted export endpoints.

Step 5: Add Unit Test

File: tests/Unit/EncryptedExportServiceTest.php

Test ZIP creation, encryption flag usage, audit logging.

Acceptance Criteria Checklist

  1. Sensitive exports prompt for password and produce AES-256 encrypted ZIP
  2. ZIP contains the original PDF or CSV file inside
  3. ZipArchive with EM_AES_256 encryption is used
  4. Fallback handling if ZipArchive encryption is not available
  5. Audit log entry for every sensitive export (who exported what, when)
  6. Permission check: only users with banking visibility can export banking reports
  7. Clear separation of encrypted vs. plain export endpoints
  8. POST method used for encrypted endpoints (password not in URL)