docs(cache): add comprehensive cache configuration and permission handling guides
- Introduce `cache-configuration.md` for detailed instructions on cache setup, permission troubleshooting, and best practices. - Add `cache-permissions-quick-fix.md` for concise resolutions to common permission errors. - Include a detailed `FILECACHE_PERMISSION_FIX_PLAN.md` outlining solutions for permission-related issues. - Enhance `docker-entrypoint.sh` with permission fixes for multi-user caches. - Update `Makefile` with cache clear commands for local and staging environments. - Improve `FileCache` for graceful degradation on permission errors, ensuring reliability under multi-user scenarios.
This commit is contained in:
217
docs/FILECACHE_PERMISSION_FIX_PLAN.md
Normal file
217
docs/FILECACHE_PERMISSION_FIX_PLAN.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# FileCache Permission Problem - L?sungsplan
|
||||
|
||||
## Problem-Analyse
|
||||
|
||||
### Fehler
|
||||
```
|
||||
PHP Fatal error: Uncaught App\Framework\Filesystem\Exceptions\FilePermissionException [FS007]:
|
||||
Permission denied for delete on file: var/www/html/storage/cache/8993618a07a0f5ee371a4d3b029abf09_1762296020.cache.php
|
||||
(File is not writable)
|
||||
```
|
||||
|
||||
### Root Cause
|
||||
|
||||
1. **Bug in `FileStorage::delete()`** (Zeile 222):
|
||||
- Die Methode pr?ft `is_writable($resolvedPath)` auf die Datei selbst
|
||||
- **FALSCH**: F?r das L?schen einer Datei braucht man nur Schreibrechte im **Verzeichnis**, nicht auf der Datei selbst!
|
||||
- Unix-Regel: `unlink()` ben?tigt nur Schreibrechte im Parent-Verzeichnis
|
||||
|
||||
2. **Cache-Dateien werden mit 0644 erstellt**:
|
||||
- Owner: `rw-` (read-write)
|
||||
- Group: `r--` (read-only)
|
||||
- Others: `r--` (read-only)
|
||||
- Problem: Wenn verschiedene Prozesse/User Dateien erstellen, k?nnen sie Dateien des anderen nicht l?schen (Owner-Mismatch)
|
||||
|
||||
3. **Staging-Server Infrastruktur**:
|
||||
- M?glicherweise werden Cache-Dateien von verschiedenen Usern/Prozessen erstellt
|
||||
- PHP-Prozess l?uft als anderer User als der, der die Dateien erstellt hat
|
||||
|
||||
## L?sungsplan
|
||||
|
||||
### L?sung 1: Bug-Fix in `FileStorage::delete()` (H?CHSTE PRIORIT?T)
|
||||
|
||||
**Problem**: Falsche Pr?fung - Datei muss nicht beschreibbar sein zum L?schen
|
||||
|
||||
**Fix**: Entferne `is_writable()` Pr?fung auf die Datei selbst
|
||||
|
||||
```php
|
||||
public function delete(string $path): void
|
||||
{
|
||||
$resolvedPath = $this->resolvePath($path);
|
||||
|
||||
// ... existing validation ...
|
||||
|
||||
if (! is_file($resolvedPath)) {
|
||||
throw new FileNotFoundException($path);
|
||||
}
|
||||
|
||||
// Pr?fe Directory-Permissions (DAS IST WICHTIG!)
|
||||
$dir = dirname($resolvedPath);
|
||||
if (! is_writable($dir)) {
|
||||
throw FilePermissionException::delete($path, 'Directory is not writable: ' . $dir);
|
||||
}
|
||||
|
||||
// ENTFERNT: Pr?fe File-Permissions
|
||||
// F?r unlink() braucht man nur Verzeichnis-Rechte!
|
||||
// if (! is_writable($resolvedPath)) {
|
||||
// throw FilePermissionException::delete($path, 'File is not writable');
|
||||
// }
|
||||
|
||||
if (! @unlink($resolvedPath)) {
|
||||
$error = error_get_last();
|
||||
if ($error && str_contains($error['message'], 'Permission denied')) {
|
||||
throw FilePermissionException::delete($path, $error['message']);
|
||||
}
|
||||
|
||||
throw new FileDeleteException($path);
|
||||
}
|
||||
|
||||
// ... logging ...
|
||||
}
|
||||
```
|
||||
|
||||
**Warum**: Unix `unlink()` ben?tigt nur Schreibrechte im Parent-Verzeichnis, nicht auf der Datei selbst.
|
||||
|
||||
---
|
||||
|
||||
### L?sung 2: Graceful Degradation in FileCache (HOHE PRIORIT?T)
|
||||
|
||||
**Problem**: FileCache wirft Fatal Error bei Permission-Exceptions
|
||||
|
||||
**Fix**: Catch FilePermissionException in FileCache-Methoden
|
||||
|
||||
**Betroffene Stellen**:
|
||||
1. `getSingleKey()` - beim L?schen abgelaufener Dateien
|
||||
2. `set()` - beim L?schen alter Cache-Dateien
|
||||
3. `forget()` - beim expliziten L?schen
|
||||
4. `clear()` - beim L?schen aller Cache-Dateien
|
||||
|
||||
**Implementierung**:
|
||||
```php
|
||||
// In getSingleKey()
|
||||
if ($expiresAt > 0 && $expiresAt < time()) {
|
||||
try {
|
||||
$this->fileSystem->delete($fullPath);
|
||||
} catch (\App\Framework\Filesystem\Exceptions\FilePermissionException $e) {
|
||||
// Permission denied - continue (graceful degradation)
|
||||
// Datei wird beim n?chsten Cleanup gel?scht
|
||||
continue;
|
||||
} catch (\Throwable $e) {
|
||||
// Other errors - continue
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// In set(), forget(), clear() - ?hnlich
|
||||
```
|
||||
|
||||
**Vorteil**: Cache funktioniert weiter, auch wenn einzelne Dateien nicht gel?scht werden k?nnen.
|
||||
|
||||
---
|
||||
|
||||
### L?sung 3: Optionale Auto-Fix vor L?schen (NIEDRIGE PRIORIT?T)
|
||||
|
||||
**Option**: Versuche Berechtigungen zu fixen, bevor gel?scht wird
|
||||
|
||||
**Implementierung**:
|
||||
```php
|
||||
private function tryDeleteWithFix(string $path): bool
|
||||
{
|
||||
try {
|
||||
$this->fileSystem->delete($path);
|
||||
return true;
|
||||
} catch (\App\Framework\Filesystem\Exceptions\FilePermissionException $e) {
|
||||
// Versuche Berechtigungen zu fixen
|
||||
try {
|
||||
// Versuche chmod auf 0644 (falls m?glich)
|
||||
@chmod($path, 0644);
|
||||
// Versuche erneut zu l?schen
|
||||
$this->fileSystem->delete($path);
|
||||
return true;
|
||||
} catch (\Throwable $e2) {
|
||||
// Auto-fix fehlgeschlagen
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Warnung**: Funktioniert nur, wenn der Prozess Owner oder root ist. Sonst wird `chmod()` fehlschlagen.
|
||||
|
||||
---
|
||||
|
||||
### L?sung 4: Infrastruktur-Fix f?r Staging (MITTEL PRIORIT?T)
|
||||
|
||||
**Problem**: Cache-Dateien werden von verschiedenen Usern/Prozessen erstellt
|
||||
|
||||
**L?sungen**:
|
||||
|
||||
#### Option A: Fix Berechtigungen im Entrypoint-Script
|
||||
```bash
|
||||
# In docker/php/docker-entrypoint.sh
|
||||
# Nach Volume-Mounting:
|
||||
chown -R appuser:appuser /var/www/html/storage/cache 2>/dev/null || true
|
||||
chmod -R 775 /var/www/html/storage/cache 2>/dev/null || true
|
||||
```
|
||||
|
||||
#### Option B: Fix Berechtigungen bei Cache-Erstellung
|
||||
```php
|
||||
// In FileStorage::put() - nach dem Schreiben
|
||||
// Stelle sicher, dass Owner/Group korrekt ist
|
||||
if (function_exists('posix_geteuid')) {
|
||||
$currentUid = posix_geteuid();
|
||||
@chown($resolvedPath, $currentUid);
|
||||
}
|
||||
```
|
||||
|
||||
#### Option C: Verwendung von Group-Writable Permissions
|
||||
```php
|
||||
// In FileStorage::put() - statt 0644
|
||||
$this->permissions->setPermissions(
|
||||
$path,
|
||||
ValueObjects\FilePermissions::readWriteOwnerReadGroupWritable() // 0664
|
||||
);
|
||||
```
|
||||
|
||||
**Empfehlung**: Option A + Option C kombiniert
|
||||
|
||||
---
|
||||
|
||||
## Implementierungsreihenfolge
|
||||
|
||||
1. ? **L?sung 1** (Bug-Fix) - SOFORT
|
||||
- Behebt das Hauptproblem
|
||||
- Semantisch korrekt (Unix-Verhalten)
|
||||
|
||||
2. ? **L?sung 2** (Graceful Degradation) - SOFORT
|
||||
- Verhindert Fatal Errors
|
||||
- Cache bleibt funktionsf?hig
|
||||
|
||||
3. ?? **L?sung 4** (Infrastruktur) - NACH Code-Fix
|
||||
- Verhindert zuk?nftige Probleme
|
||||
- Dokumentiere in `docs/deployment/`
|
||||
|
||||
4. ?? **L?sung 3** (Auto-Fix) - NUR WENN N?TIG
|
||||
- Kann Probleme verschlimmern, wenn nicht richtig implementiert
|
||||
- Nur verwenden, wenn L?sungen 1+2+4 nicht ausreichen
|
||||
|
||||
## Testing
|
||||
|
||||
Nach Implementierung testen:
|
||||
|
||||
1. **Unit-Test**: `delete()` sollte funktionieren, auch wenn Datei nicht beschreibbar ist
|
||||
2. **Integration-Test**: FileCache sollte funktionieren, auch wenn einige Dateien nicht gel?scht werden k?nnen
|
||||
3. **Staging-Test**: Cache-Operationen sollten keine Fatal Errors mehr werfen
|
||||
|
||||
## Dokumentation
|
||||
|
||||
? **Dokumentation erstellt**:
|
||||
- ? `docs/deployment/cache-configuration.md` - Vollst?ndige Cache-Konfigurations-Dokumentation
|
||||
- `docs/claude/error-handling.md` - Cache-specific error handling (optional)
|
||||
|
||||
## Status
|
||||
|
||||
? **L?sung 1**: Bug-Fix in `delete()` - IMPLEMENTIERT
|
||||
? **L?sung 2**: Graceful Degradation in FileCache - IMPLEMENTIERT
|
||||
? **L?sung 4**: Infrastruktur-Dokumentation - IMPLEMENTIERT
|
||||
?? **L?sung 3**: Auto-Fix mit chmod() - NUR WENN N?TIG
|
||||
Reference in New Issue
Block a user