# FilePermissionException Verbesserungs-Plan ## Ziel Verbesserung der `FilePermissionException` um detaillierte Permission- und User-Informationen f?r besseres Debugging. ## Problem-Analyse ### Aktueller Zustand Die `FilePermissionException` gibt momentan nur minimale Informationen: ```php FilePermissionException::delete($path, 'Directory is not writable: ' . $dir); // Output: "Permission denied for delete on file: /path/to/file (Directory is not writable: /path/to/dir)" ``` **Fehlende Informationen:** - Aktuelle Permissions der Datei/Verzeichnisses - Owner/Group der Datei - Aktueller Process-User - Erwartete Permissions - Octal-Darstellung der Permissions ### Verf?gbare Infrastruktur ? **PermissionChecker** hat bereits `getDiagnosticInfo()`: - Liefert owner, group, permissions, parent_dir info - Nutzt `posix_getpwuid()` und `posix_getgrgid()` ? **ExceptionContext** hat `withData()`, `withDebug()`, `withMetadata()` ? **posix_geteuid()** verf?gbar f?r Process-User ## L?sungsplan ### L?sung 1: Erweitere FilePermissionException (HOHE PRIORIT?T) **Neue statische Factory-Methoden mit Permission-Details:** ```php public static function delete( string $path, ?string $reason = null, ?PermissionChecker $permissionChecker = null ): self { $diagnosticInfo = $permissionChecker?->getDiagnosticInfo($path) ?? []; $currentUser = self::getCurrentUserInfo(); return new self( path: $path, operation: 'delete', reason: $reason, diagnosticInfo: $diagnosticInfo, currentUser: $currentUser ); } ``` **Neue Properties:** - `?array $diagnosticInfo` - Permission-Details vom PermissionChecker - `?array $currentUser` - Aktueller Process-User Info **Verbesserte Message-Formatierung:** ```php $message = "Permission denied for {$operation} on file: {$path}"; if ($reason) { $message .= " ({$reason})"; } // Add detailed info if available if ($this->diagnosticInfo) { $message .= sprintf( "\n File owner: %s, group: %s, permissions: %s", $this->diagnosticInfo['owner'] ?? 'unknown', $this->diagnosticInfo['group'] ?? 'unknown', $this->diagnosticInfo['permissions'] ?? 'unknown' ); if (isset($this->diagnosticInfo['parent_dir'])) { $parentInfo = $permissionChecker?->getDiagnosticInfo($this->diagnosticInfo['parent_dir']) ?? []; $message .= sprintf( "\n Parent directory: %s (owner: %s, permissions: %s)", $this->diagnosticInfo['parent_dir'], $parentInfo['owner'] ?? 'unknown', $parentInfo['permissions'] ?? 'unknown' ); } } if ($this->currentUser) { $message .= sprintf( "\n Current process user: %s (uid: %d, gid: %d)", $this->currentUser['name'], $this->currentUser['uid'], $this->currentUser['gid'] ); } ``` ### L?sung 2: Helper-Methode f?r Process-User Info **Neue private Methode in FilePermissionException:** ```php private static function getCurrentUserInfo(): ?array { if (!function_exists('posix_geteuid')) { return null; } $uid = posix_geteuid(); $gid = posix_getegid(); $userInfo = posix_getpwuid($uid); $groupInfo = posix_getgrgid($gid); return [ 'uid' => $uid, 'gid' => $gid, 'name' => $userInfo['name'] ?? 'unknown', 'group' => $groupInfo['name'] ?? 'unknown', ]; } ``` ### L?sung 3: Integration in FileStorage-Methoden **Anpassung aller FilePermissionException Aufrufe:** **Vorher:** ```php if (! is_writable($dir)) { throw FilePermissionException::delete($path, 'Directory is not writable: ' . $dir); } ``` **Nachher:** ```php if (! is_writable($dir)) { throw FilePermissionException::delete( path: $path, reason: 'Directory is not writable: ' . $dir, permissionChecker: $this->permissions ); } ``` **Betroffene Stellen:** 1. `FileStorage::get()` - read exception 2. `FileStorage::put()` - write exception, createDirectory exception 3. `FileStorage::delete()` - delete exception 4. `FileStorage::createDirectory()` - createDirectory exception 5. Alle anderen Stellen, die FilePermissionException werfen ### L?sung 4: ExceptionContext erweitern **Erweiterte Context-Daten in Exception:** ```php $context = ExceptionContext::forOperation('file.permission', 'filesystem') ->withData([ 'path' => $path, 'operation' => $operation, 'reason' => $reason, ]) ->withDebug([ 'file_permissions' => $diagnosticInfo['permissions'] ?? null, 'file_owner' => $diagnosticInfo['owner'] ?? null, 'file_group' => $diagnosticInfo['group'] ?? null, 'parent_dir' => $diagnosticInfo['parent_dir'] ?? null, 'parent_writable' => $diagnosticInfo['parent_writable'] ?? null, ]) ->withMetadata([ 'current_user' => $currentUser, 'file_exists' => $diagnosticInfo['exists'] ?? false, 'is_file' => $diagnosticInfo['is_file'] ?? false, 'is_dir' => $diagnosticInfo['is_dir'] ?? false, ]); ``` ## Implementierungsreihenfolge 1. ? **L?sung 2** - Helper-Methode f?r Process-User (einfach, keine Dependencies) 2. ? **L?sung 1** - Erweitere FilePermissionException Constructor und Factory-Methoden 3. ? **L?sung 3** - Integration in FileStorage-Methoden 4. ? **L?sung 4** - ExceptionContext erweitern ## Beispiel-Output ### Vorher: ``` Permission denied for delete on file: /var/www/html/storage/cache/file.cache.php (Directory is not writable: /var/www/html/storage/cache) ``` ### Nachher: ``` Permission denied for delete on file: /var/www/html/storage/cache/file.cache.php (Directory is not writable: /var/www/html/storage/cache) File owner: www-data, group: www-data, permissions: drwxrwxr-x Parent directory: /var/www/html/storage/cache (owner: root, permissions: drwxr-xr-x) Current process user: www-data (uid: 33, gid: 33) ``` ## Vorteile 1. **Besseres Debugging**: Sofort sichtbar, welche Permissions falsch sind 2. **User-Info**: Zeigt Owner-Mismatch sofort 3. **Context**: Vollst?ndige Permission-Info in Exception-Context f?r Logging 4. **R?ckw?rtskompatibel**: Alte Aufrufe funktionieren weiterhin (optional Parameter) ## Performance-?berlegungen - `getDiagnosticInfo()` ist relativ teuer (mehrere `stat()` Calls) - **L?sung**: Nur bei Exception-Throw aufrufen (nicht bei jedem Check) - Optional: K?nnte in `withDebug()` ausgelagert werden, wenn Performance kritisch ist ## Testing 1. **Unit-Tests**: FilePermissionException mit Permission-Details 2. **Integration-Tests**: FileStorage-Methoden mit verschiedenen Permission-Szenarien 3. **E2E-Tests**: Cache-Operationen mit Permission-Problemen ## Dokumentation Nach Implementierung aktualisieren: - `docs/claude/error-handling.md` - FilePermissionException mit Details - `docs/deployment/cache-configuration.md` - Exception-Beispiele