1 Commits

7442 changed files with 499550 additions and 119998 deletions

3
.gitignore vendored
View File

@@ -6,6 +6,3 @@ frontend/.env
backend/.env
backend/images/*
backend/backend-debug.log
backend/*.log
backend/.env.local

View File

@@ -1,86 +0,0 @@
# Server-Prüfung: i18n-Fixes
## Lokale Prüfung (bereits durchgeführt)
✅ Alle Dateien sind lokal korrekt:
- `TeamManagementView.vue` - Alle `$t()` durch `t()` ersetzt, `t` im return Statement
- `PermissionsView.vue` - Alle `$t()` durch `t()` ersetzt, `t` im return Statement
- `LogsView.vue` - Alle `$t()` durch `t()` ersetzt, `t` im return Statement
- `SeasonSelector.vue` - Bereits korrekt
## Server-Prüfung
### 1. Prüfskript auf den Server kopieren
```bash
# Vom lokalen Rechner aus:
scp check-i18n-fixes.sh rv2756:/var/www/tt-tagebuch.de/
```
### 2. Auf dem Server ausführen
```bash
# Auf dem Server:
cd /var/www/tt-tagebuch.de
chmod +x check-i18n-fixes.sh
./check-i18n-fixes.sh
```
### 3. Falls Dateien nicht aktualisiert sind
```bash
# Auf dem Server:
cd /var/www/tt-tagebuch.de
git pull origin main
cd backend
npm install # Erstellt automatisch den Frontend-Build (via postinstall script)
```
### 4. Backend neu starten (falls nötig)
```bash
# Falls als systemd-Service:
sudo systemctl restart tt-tagebuch
# Oder falls als PM2-Prozess:
pm2 restart tt-tagebuch-backend
```
## Erwartete Ergebnisse
Das Prüfskript sollte folgende Ausgabe zeigen:
```
1. TeamManagementView.vue:
✓ Enthält 'const t = (key, params) => i18n.global.t'
✓ Enthält keine $t() Aufrufe mehr
✓ 't' ist im return Statement enthalten
2. PermissionsView.vue:
✓ Enthält 'const t = (key, params) => i18n.global.t'
✓ Enthält keine $t() Aufrufe mehr
✓ 't' ist im return Statement enthalten
3. LogsView.vue:
✓ Enthält 'const t = (key, params) => i18n.global.t'
✓ Enthält keine $t() Aufrufe mehr
✓ 't' ist im return Statement enthalten
4. SeasonSelector.vue:
✓ Enthält 'const t = (key, params) => i18n.global.t'
✓ Enthält keine $t() Aufrufe mehr
```
## Commits, die auf den Server müssen
Die folgenden Commits müssen auf dem Server sein:
- `b0e610f` - Fix: Replace all $t() calls with t() in PermissionsView and LogsView templates
- `0285c05` - Fix: Replace all $t() calls with t() in TeamManagementView template
- `5d4f2eb` - Update localization handling in TeamManagementView
Prüfe mit:
```bash
git log --oneline -5
```

View File

@@ -1,191 +0,0 @@
# Deployment-Anleitung: Socket.IO mit SSL
Socket.IO läuft jetzt direkt auf HTTPS-Port 3051 (nicht über Apache-Proxy).
## Schritte nach dem Deployment
### 1. Firewall-Port öffnen
```bash
# UFW (Ubuntu Firewall)
sudo ufw allow 3051/tcp
```
### 2. Apache-Konfiguration aktualisieren
```bash
sudo cp /var/www/tt-tagebuch.de/apache.conf.example /etc/apache2/sites-available/tt-tagebuch.de-le-ssl.conf
sudo systemctl restart apache2
```
### 3. systemd-Service konfigurieren (als www-data)
**WICHTIG:** Der Service sollte als `www-data` laufen, nicht als `nobody`!
```bash
# Service-Datei installieren
sudo cp /var/www/tt-tagebuch.de/tt-tagebuch.service /etc/systemd/system/
sudo systemctl daemon-reload
```
Die Service-Datei konfiguriert:
- User: `www-data` (Standard-Webserver-Benutzer)
- Group: `www-data`
- Port: 3050 (HTTP) und 3051 (HTTPS)
### 4. SSL-Zertifikat-Berechtigungen setzen
**WICHTIG:** Der Node.js-Prozess muss Zugriff auf die SSL-Zertifikate haben!
```bash
cd /var/www/tt-tagebuch.de/backend
chmod +x scripts/fixCertPermissions.sh
sudo ./scripts/fixCertPermissions.sh
```
Dieses Skript:
- Erstellt die Gruppe `ssl-cert` (falls nicht vorhanden)
- Fügt den Service-Benutzer (`www-data`) zur Gruppe hinzu
- Setzt die Berechtigungen für die Zertifikate
### 5. Backend neu starten
**WICHTIG:** Der Backend-Server muss neu gestartet werden, damit der HTTPS-Server auf Port 3051 läuft!
```bash
# Falls als systemd-Service:
sudo systemctl restart tt-tagebuch
# Oder falls als PM2-Prozess:
pm2 restart tt-tagebuch-backend
```
### 6. Prüfen, ob HTTPS-Server läuft
```bash
# Prüfe, ob Port 3051 geöffnet ist
sudo netstat -tlnp | grep 3051
# Oder:
sudo ss -tlnp | grep 3051
# Prüfe Backend-Logs
sudo journalctl -u tt-tagebuch -f
# Oder bei PM2:
pm2 logs tt-tagebuch-backend
```
Du solltest folgende Meldung sehen:
```
🚀 HTTPS-Server für Socket.IO läuft auf Port 3051
```
### 7. Diagnose-Skript ausführen
```bash
cd /var/www/tt-tagebuch.de/backend
node scripts/checkSocketIOServer.js
```
Dieses Skript prüft:
- Ob SSL-Zertifikate existieren
- Ob Port 3051 geöffnet ist
- Ob der Server erreichbar ist
### 8. Testen
Im Browser sollte Socket.IO jetzt direkt zu `wss://tt-tagebuch.de:3051` verbinden.
## Troubleshooting
### Port 3051 ist nicht erreichbar
1. **Prüfe Firewall:**
```bash
sudo ufw status
sudo ufw allow 3051/tcp
```
2. **Prüfe, ob der Server läuft:**
```bash
sudo netstat -tlnp | grep 3051
sudo ss -tlnp | grep 3051
```
3. **Prüfe Backend-Logs auf Fehler:**
```bash
sudo journalctl -u tt-tagebuch -n 50
# Oder:
pm2 logs tt-tagebuch-backend --lines 50
```
4. **Prüfe, ob HTTPS-Server gestartet wurde:**
- Suche in den Logs nach: `🚀 HTTPS-Server für Socket.IO läuft auf Port 3051`
- Falls nicht vorhanden, prüfe auf Fehler: `⚠️ HTTPS-Server konnte nicht gestartet werden`
### SSL-Zertifikat-Fehler / Berechtigungsfehler
**Fehler:** `EACCES: permission denied, open '/etc/letsencrypt/live/tt-tagebuch.de/privkey.pem'`
**Lösung:**
```bash
cd /var/www/tt-tagebuch.de/backend
chmod +x scripts/fixCertPermissions.sh
sudo ./scripts/fixCertPermissions.sh
sudo systemctl restart tt-tagebuch
```
Stelle sicher, dass die Zertifikate existieren:
```bash
ls -la /etc/letsencrypt/live/tt-tagebuch.de/
```
Falls die Zertifikate nicht existieren:
```bash
sudo certbot certonly --standalone -d tt-tagebuch.de
```
### Service läuft als "nobody"
**Problem:** Der Service läuft als `nobody`, was zu eingeschränkt ist.
**Lösung:**
1. Installiere die Service-Datei (siehe Schritt 3)
2. Führe das Berechtigungs-Skript aus (siehe Schritt 4)
3. Starte den Service neu
```bash
# Prüfe aktuellen Service-User
sudo systemctl show -p User tt-tagebuch.service
# Installiere Service-Datei
sudo cp /var/www/tt-tagebuch.de/tt-tagebuch.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl restart tt-tagebuch
# Prüfe, ob jetzt als www-data läuft
sudo systemctl show -p User tt-tagebuch.service
```
### Frontend verbindet nicht
1. **Prüfe Browser-Konsole auf Fehler**
2. **Prüfe, ob `import.meta.env.PROD` korrekt gesetzt ist:**
- In Produktion sollte die Socket.IO-URL `https://tt-tagebuch.de:3051` sein
- In Entwicklung sollte sie `http://localhost:3005` sein
3. **Prüfe, ob die Socket.IO-URL korrekt ist:**
- Öffne Browser-Entwicklertools → Network
- Suche nach WebSocket-Verbindungen
- Die URL sollte `wss://tt-tagebuch.de:3051/socket.io/...` sein
### Server lauscht nur auf localhost
Der Server sollte auf `0.0.0.0` lauschen (nicht nur auf `localhost`).
Dies ist bereits in der Konfiguration eingestellt:
```javascript
httpsServer.listen(httpsPort, '0.0.0.0', () => {
console.log(`🚀 HTTPS-Server für Socket.IO läuft auf Port ${httpsPort}`);
});
```
Falls der Server trotzdem nicht erreichbar ist, prüfe die Backend-Logs.

View File

@@ -1,342 +0,0 @@
# DSGVO-Konformitäts-Checkliste für Trainingstagebuch
## Status: ⚠️ PRÜFUNG ERFORDERLICH
Diese Checkliste dokumentiert den aktuellen Stand der DSGVO-Konformität der Anwendung.
---
## 1. Datenschutzerklärung ✅ / ⚠️
### Status: ⚠️ Teilweise vorhanden, muss aktualisiert werden
**Vorhanden:**
- ✅ Datenschutzerklärung vorhanden (`/datenschutz`)
- ✅ Impressum vorhanden (`/impressum`)
- ✅ Verlinkung im Footer
**Fehlend/Verbesserungsbedarf:**
- ⚠️ MyTischtennis-Integration nicht erwähnt (Drittlandübermittlung?)
- ⚠️ Logging von API-Requests nicht erwähnt
- ⚠️ Verschlüsselung von Mitgliederdaten nicht erwähnt
- ⚠️ Speicherdauer für Logs nicht konkretisiert
- ⚠️ Keine Informationen zu automatischer Löschung
---
## 2. Einwilligungen ⚠️
### Status: ⚠️ Teilweise vorhanden
**Vorhanden:**
-`picsInInternetAllowed` bei Mitgliedern (Einwilligung für Fotos im Internet)
- ✅ MyTischtennis: `savePassword` und `autoUpdateRatings` (Einwilligungen)
**Fehlend/Verbesserungsbedarf:**
- ⚠️ Keine explizite Einwilligung bei Registrierung zur Datenschutzerklärung
- ⚠️ Keine Einwilligung für Logging von API-Requests
- ⚠️ Keine Einwilligung für Datenübertragung an MyTischtennis.de
- ⚠️ Keine Möglichkeit, Einwilligungen zu widerrufen (außer manuell)
---
## 3. Löschrechte (Art. 17 DSGVO) ⚠️
### Status: ⚠️ Teilweise implementiert
**Vorhanden:**
- ✅ DELETE-Endpunkte für viele Ressourcen (Member, Tournament, etc.)
- ✅ MyTischtennis-Account kann gelöscht werden
**Fehlend/Verbesserungsbedarf:**
-**KRITISCH:** Kein Endpunkt zum vollständigen Löschen eines User-Accounts
-**KRITISCH:** Keine automatische Löschung aller zugehörigen Daten (Cascade-Delete)
- ❌ Keine Löschung von Logs nach Ablauf der Speicherdauer
- ⚠️ Keine Anonymisierung statt Löschung (falls gesetzliche Aufbewahrungspflichten bestehen)
- ⚠️ Keine Bestätigung vor Löschung kritischer Daten
**Empfehlung:**
- Implementiere `/api/user/delete` Endpunkt
- Implementiere automatische Löschung aller zugehörigen Daten:
- UserClub-Einträge
- MyTischtennis-Account
- Alle Logs (nach Anonymisierung)
- Alle Mitglieder, die nur diesem User zugeordnet sind
- Implementiere automatische Löschung von Logs nach 90 Tagen
---
## 4. Auskunftsrechte (Art. 15 DSGVO) ❌
### Status: ❌ Nicht implementiert
**Fehlend:**
-**KRITISCH:** Kein Endpunkt zur Auskunft über gespeicherte Daten
- ❌ Keine Übersicht über alle personenbezogenen Daten eines Users
- ❌ Keine Übersicht über alle Mitgliederdaten
- ❌ Keine Übersicht über Logs, die einen User betreffen
**Empfehlung:**
- Implementiere `/api/user/data-export` Endpunkt
- Exportiere alle Daten in strukturiertem Format (JSON)
- Inkludiere:
- User-Daten
- Vereinszugehörigkeiten
- Mitgliederdaten (falls User Zugriff hat)
- Logs
- MyTischtennis-Daten
---
## 5. Datenportabilität (Art. 20 DSGVO) ❌
### Status: ❌ Nicht implementiert
**Fehlend:**
-**KRITISCH:** Kein Export in maschinenlesbarem Format
- ❌ Keine JSON/XML-Export-Funktion
- ⚠️ PDF-Export für Trainingstage vorhanden, aber nicht für alle Daten
**Empfehlung:**
- Implementiere `/api/user/data-export` mit JSON-Format
- Implementiere Export für:
- Alle eigenen Daten
- Alle Mitgliederdaten (falls berechtigt)
- Alle Trainingsdaten
- Alle Turnierdaten
---
## 6. Verschlüsselung ✅ / ⚠️
### Status: ✅ Gut implementiert
**Vorhanden:**
- ✅ AES-256-CBC Verschlüsselung für Mitgliederdaten:
- firstName, lastName
- birthDate
- phone, street, city, postalCode
- email
- notes (Participant)
- ✅ Passwörter werden mit bcrypt gehasht
- ✅ HTTPS für alle Verbindungen
**Verbesserungsbedarf:**
- ⚠️ Verschlüsselungsschlüssel sollte in separater, sicherer Konfiguration sein
-**BEHOBEN:** MyTischtennis-Daten werden jetzt vollständig verschlüsselt (E-Mail, Zugriffstoken, Refresh-Token, Cookie, Benutzerdaten, Vereinsinformationen)
- ⚠️ Keine Verschlüsselung für Logs (können personenbezogene Daten enthalten)
---
## 7. Logging ⚠️
### Status: ⚠️ Verbesserungsbedarf
**Vorhanden:**
- ✅ Aktivitäts-Logging (`log` Tabelle) - protokolliert wichtige Aktionen
- ✅ Server-Logs - Standard-Server-Logs für Fehlerbehebung
-**ENTFERNT:** API-Logging für MyTischtennis-Requests wurde deaktiviert
**Probleme:**
-**BEHOBEN:** API-Logging für MyTischtennis-Requests wurde komplett entfernt (keine personenbezogenen Daten mehr in API-Logs)
- ⚠️ Keine automatische Löschung von Aktivitätslogs (noch zu implementieren)
-**BEHOBEN:** In Datenschutzerklärung dokumentiert, was geloggt wird
**Empfehlung:**
- ⚠️ Implementiere automatische Löschung von Aktivitätslogs nach angemessener Frist (noch ausstehend)
---
## 8. MyTischtennis-Integration ⚠️
### Status: ⚠️ Verbesserungsbedarf
**Vorhanden:**
- ✅ Verschlüsselung von Passwörtern
- ✅ Einwilligungen (`savePassword`, `autoUpdateRatings`)
- ✅ DELETE-Endpunkt für Account
**Probleme:**
-**BEHOBEN:** Drittlandübermittlung in Datenschutzerklärung erwähnt
- ⚠️ Keine explizite Einwilligung für Datenübertragung an MyTischtennis.de
-**BEHOBEN:** Informationen über Datenschutz bei MyTischtennis.de in Datenschutzerklärung
-**BEHOBEN:** Alle MyTischtennis-Daten werden jetzt verschlüsselt gespeichert
**Empfehlung:**
- Aktualisiere Datenschutzerklärung:
- Erwähne MyTischtennis-Integration
- Erkläre, welche Daten übertragen werden
- Verweise auf Datenschutzerklärung von MyTischtennis.de
- Erkläre Rechtsgrundlage (Einwilligung)
- Implementiere explizite Einwilligung bei Einrichtung der Integration
- Verschlüssele auch Zugriffstoken
---
## 9. Cookies & Local Storage ✅
### Status: ✅ Konform
**Vorhanden:**
- ✅ Nur technisch notwendige Cookies/Storage:
- Session-Token (Session Storage)
- Username, Clubs, Permissions (Local Storage)
- ✅ Keine Tracking-Cookies
- ✅ Keine Werbe-Cookies
- ✅ Dokumentiert in Datenschutzerklärung
**Hinweis:**
- Local Storage wird für persistente Daten verwendet (Clubs, Permissions)
- Dies ist technisch notwendig und DSGVO-konform
---
## 10. Berechtigungssystem ✅
### Status: ✅ Gut implementiert
**Vorhanden:**
- ✅ Rollenbasierte Zugriffe (Admin, Trainer, Mannschaftsführer, Mitglied)
- ✅ Individuelle Berechtigungen pro Ressource
- ✅ Transparente Zugriffskontrolle
- ✅ Logging von Aktivitäten
**Hinweis:**
- Berechtigungssystem ist DSGVO-konform
- Ermöglicht Datenminimierung (Zugriff nur auf notwendige Daten)
---
## 11. Datenminimierung ⚠️
### Status: ⚠️ Teilweise konform
**Vorhanden:**
- ✅ Nur notwendige Daten werden gespeichert
- ✅ Berechtigungssystem ermöglicht minimale Datenzugriffe
**Verbesserungsbedarf:**
- ⚠️ Logs enthalten möglicherweise zu viele Daten (Request/Response-Bodies)
- ⚠️ Keine automatische Löschung alter Daten
- ⚠️ Keine Option, Daten zu anonymisieren statt zu löschen
---
## 12. Technische und organisatorische Maßnahmen (TOM) ✅ / ⚠️
### Status: ✅ Gut, aber verbesserungsbedürftig
**Vorhanden:**
- ✅ Verschlüsselung sensibler Daten
- ✅ HTTPS für alle Verbindungen
- ✅ Passwort-Hashing (bcrypt)
- ✅ Authentifizierung und Autorisierung
- ✅ Berechtigungssystem
**Verbesserungsbedarf:**
- ⚠️ Keine Dokumentation der TOM
- ⚠️ Keine regelmäßigen Sicherheitsupdates dokumentiert
- ⚠️ Keine Backup-Strategie dokumentiert
- ⚠️ Keine Notfallpläne dokumentiert
---
## 13. Auftragsverarbeitung ⚠️
### Status: ⚠️ Nicht dokumentiert
**Fehlend:**
- ⚠️ Keine Informationen über Hosting-Provider
- ⚠️ Keine Informationen über Auftragsverarbeitungsverträge (AVV)
- ⚠️ Keine Informationen über Subunternehmer
**Empfehlung:**
- Dokumentiere alle Auftragsverarbeiter (Hosting, etc.)
- Erwähne in Datenschutzerklärung, dass AVV abgeschlossen wurden
---
## 14. Betroffenenrechte - Umsetzung ❌
### Status: ❌ Nicht vollständig implementiert
**Fehlend:**
-**KRITISCH:** Kein Endpunkt für Auskunft (Art. 15)
-**KRITISCH:** Kein Endpunkt für Löschung (Art. 17)
-**KRITISCH:** Kein Endpunkt für Datenexport (Art. 20)
- ❌ Kein Endpunkt für Berichtigung (Art. 16) - teilweise vorhanden über normale Edit-Endpunkte
- ❌ Kein Endpunkt für Einschränkung (Art. 18)
- ❌ Kein Endpunkt für Widerspruch (Art. 21)
**Empfehlung:**
- Implementiere zentrale Endpunkte für alle Betroffenenrechte:
- `GET /api/user/rights/information` - Auskunft
- `DELETE /api/user/rights/deletion` - Löschung
- `GET /api/user/rights/export` - Datenexport
- `PUT /api/user/rights/restriction` - Einschränkung
- `POST /api/user/rights/objection` - Widerspruch
---
## 15. Kontakt für Datenschutz ✅
### Status: ✅ Vorhanden
**Vorhanden:**
- ✅ E-Mail-Adresse in Datenschutzerklärung: tsschulz@tsschulz.de
- ✅ Vollständige Anschrift im Impressum
---
## Zusammenfassung
### ✅ Gut implementiert:
1. Verschlüsselung sensibler Daten
2. HTTPS
3. Berechtigungssystem
4. Cookies/Local Storage (nur technisch notwendig)
5. Datenschutzerklärung vorhanden
### ⚠️ Verbesserungsbedarf:
1. Datenschutzerklärung aktualisieren (MyTischtennis, Logging)
2. Logging von personenbezogenen Daten reduzieren/anonymisieren
3. Automatische Löschung von Logs implementieren
4. MyTischtennis-Integration in Datenschutzerklärung erwähnen
### ❌ Kritisch - Muss implementiert werden:
1. **Löschrechte-API** (Art. 17 DSGVO)
2. **Auskunftsrechte-API** (Art. 15 DSGVO)
3. **Datenexport-API** (Art. 20 DSGVO)
4. **Automatische Löschung von Logs** nach Retention-Periode
---
## Prioritäten
### Sofort (vor Live-Betrieb):
1. Datenschutzerklärung aktualisieren
2. Löschrechte-API implementieren
3. Auskunftsrechte-API implementieren
4. Datenexport-API implementieren
### Kurzfristig (innerhalb 1 Monat):
1. Automatische Löschung von Logs implementieren
2. Logging von personenbezogenen Daten reduzieren/anonymisieren
3. MyTischtennis-Integration in Datenschutzerklärung dokumentieren
### Mittelfristig (innerhalb 3 Monate):
1. Einwilligungsmanagement implementieren
2. TOM dokumentieren
3. Auftragsverarbeitung dokumentieren
---
## Nächste Schritte
1. ✅ Diese Checkliste erstellen
2. ⏳ Datenschutzerklärung aktualisieren
3. ⏳ Löschrechte-API implementieren
4. ⏳ Auskunftsrechte-API implementieren
5. ⏳ Datenexport-API implementieren
6. ⏳ Logging verbessern

View File

@@ -1,210 +0,0 @@
# Berechtigungssystem - Dokumentation
## Übersicht
Das Trainingstagebuch verfügt nun über ein vollständiges rollenbasiertes Berechtigungssystem (RBAC - Role-Based Access Control). Der Club-Ersteller hat automatisch Admin-Rechte und kann anderen Mitgliedern Rollen und spezifische Berechtigungen zuweisen.
## Rollen
### 1. Administrator (admin)
- **Vollzugriff** auf alle Funktionen
- Kann Berechtigungen anderer Benutzer verwalten
- Der Club-Ersteller ist automatisch Administrator und kann nicht degradiert werden
### 2. Trainer (trainer)
- Kann Trainingseinheiten planen und verwalten
- Kann Mitglieder anlegen und bearbeiten
- Kann Spielpläne einsehen und bearbeiten
- Kann Turniere organisieren
- **Kann nicht**: Einstellungen ändern, Berechtigungen verwalten
### 3. Mannschaftsführer (team_manager)
- Kann Teams und Spielpläne verwalten
- Kann Spieler für Matches einteilen
- Kann Spielergebnisse eintragen
- **Kann nicht**: Trainingseinheiten planen, Mitglieder verwalten
### 4. Mitglied (member)
- Nur Lesezugriff auf alle Bereiche
- Kann eigene Daten einsehen
- **Kann nicht**: Daten ändern oder löschen
## Berechtigungsbereiche
- **diary**: Trainingstagebuch
- **members**: Mitgliederverwaltung
- **teams**: Team-Management
- **schedule**: Spielpläne
- **tournaments**: Turniere
- **statistics**: Statistiken
- **settings**: Einstellungen
- **permissions**: Berechtigungsverwaltung
- **mytischtennis**: MyTischtennis-Integration (für alle zugänglich)
## Backend-Integration
### Migration ausführen
```sql
mysql -u username -p database_name < backend/migrations/add_permissions_to_user_club.sql
```
### Authorization Middleware verwenden
```javascript
import { authorize, requireAdmin, requireOwner } from '../middleware/authorizationMiddleware.js';
// Beispiel: Nur Lesezugriff erforderlich
router.get('/diary/:clubId', authenticate, authorize('diary', 'read'), getDiary);
// Beispiel: Schreibzugriff erforderlich
router.post('/diary/:clubId', authenticate, authorize('diary', 'write'), createDiary);
// Beispiel: Admin-Rechte erforderlich
router.put('/settings/:clubId', authenticate, requireAdmin(), updateSettings);
// Beispiel: Nur Owner
router.delete('/club/:clubId', authenticate, requireOwner(), deleteClub);
```
### Permission Service verwenden
```javascript
import permissionService from '../services/permissionService.js';
// Berechtigungen prüfen
const hasPermission = await permissionService.hasPermission(userId, clubId, 'diary', 'write');
// Rolle setzen
await permissionService.setUserRole(userId, clubId, 'trainer', adminUserId);
// Custom Permissions setzen
await permissionService.setCustomPermissions(
userId,
clubId,
{ diary: { write: false }, members: { write: true } },
adminUserId
);
```
## Frontend-Integration
### Composable verwenden
```vue
<script setup>
import { usePermissions } from '@/composables/usePermissions.js';
const { can, canWrite, canDelete, isAdmin, isOwner, userRole } = usePermissions();
// Beispiel
if (can('diary', 'write')) {
// Zeige Bearbeitungsbutton
}
</script>
```
### Direktiven verwenden
```vue
<template>
<!-- Nur anzeigen, wenn Schreibrechte für diary vorhanden -->
<button v-can:diary.write>Bearbeiten</button>
<!-- Nur anzeigen, wenn Löschrechte für members vorhanden -->
<button v-can:members.delete>Löschen</button>
<!-- Alternative Syntax -->
<div v-can="'diary.write'">Inhalt nur für Berechtigte</div>
<!-- Nur für Admins -->
<div v-admin>Admin-Bereich</div>
<!-- Nur für Owner -->
<div v-owner>Owner-Bereich</div>
</template>
```
### Store verwenden
```javascript
import { useStore } from 'vuex';
const store = useStore();
// Berechtigungen abrufen
const permissions = store.getters.currentPermissions;
const hasPermission = store.getters.hasPermission('diary', 'write');
const isOwner = store.getters.isClubOwner;
const userRole = store.getters.userRole;
// Berechtigungen laden (wird automatisch beim Club-Wechsel gemacht)
await store.dispatch('loadPermissions', clubId);
```
## Admin-UI
Die Berechtigungsverwaltung ist unter `/permissions` verfügbar und nur für Administratoren sichtbar.
**Funktionen:**
- Übersicht aller Clubmitglieder mit ihren Rollen
- Rollen zuweisen/ändern
- Custom Permissions für einzelne Benutzer definieren
- Erklärung der verfügbaren Rollen
## MyTischtennis-Integration
Die MyTischtennis-Einstellungen und -Funktionen sind für **alle Club-Mitglieder** zugänglich, unabhängig von ihrer Rolle. Dies ermöglicht es jedem, die Anbindung einzurichten und Daten abzurufen.
## Sicherheitshinweise
1. **Der Club-Ersteller** (Owner) kann nicht degradiert oder gelöscht werden
2. **Owner-Rechte** können nicht übertragen werden
3. **Backend-Validierung** wird immer durchgeführt, auch wenn das Frontend Elemente ausblendet
4. **Alle API-Routen** sind durch Middleware geschützt
5. **Permissions werden gecacht** im localStorage für bessere Performance
## Beispiel-Szenarien
### Szenario 1: Trainer hinzufügen
1. Admin öffnet `/permissions`
2. Wählt Benutzer aus
3. Ändert Rolle zu "Trainer"
4. Benutzer kann jetzt Trainingseinheiten planen
### Szenario 2: Custom Permissions
1. Admin öffnet `/permissions`
2. Wählt Benutzer aus
3. Klickt auf "Anpassen"
4. Setzt individuelle Berechtigungen (z.B. nur Diary-Schreibrecht)
5. Speichert
### Szenario 3: Neues Mitglied
1. Mitglied registriert sich und fordert Zugang an
2. Admin genehmigt Anfrage (Standardrolle: "member")
3. Mitglied hat Lesezugriff
4. Bei Bedarf kann Admin die Rolle später ändern
## Troubleshooting
**Problem**: Berechtigungen werden nicht aktualisiert
- **Lösung**: Seite neu laden oder Club neu auswählen
**Problem**: "Keine Berechtigung" trotz korrekter Rolle
- **Lösung**: Prüfen, ob Custom Permissions die Rolle überschreiben
**Problem**: Owner kann keine Änderungen vornehmen
- **Lösung**: Owner sollte automatisch alle Rechte haben. Prüfen Sie die `isOwner`-Flag in der Datenbank
## API-Endpunkte
```
GET /api/permissions/:clubId - Eigene Berechtigungen abrufen
GET /api/permissions/:clubId/members - Alle Mitglieder mit Berechtigungen (Admin)
PUT /api/permissions/:clubId/user/:userId/role - Rolle ändern (Admin)
PUT /api/permissions/:clubId/user/:userId/permissions - Custom Permissions setzen (Admin)
GET /api/permissions/roles/available - Verfügbare Rollen abrufen
GET /api/permissions/structure/all - Berechtigungsstruktur abrufen
```

View File

@@ -1,235 +0,0 @@
# Berechtigungssystem - Migrations-Anleitung
## Übersicht
Diese Anleitung hilft Ihnen, das neue Berechtigungssystem für bestehende Clubs einzurichten.
## Schritt 1: Datenbank-Schema erweitern
Führen Sie zuerst die SQL-Migration aus, um die neuen Spalten hinzuzufügen:
```bash
mysql -u username -p database_name < backend/migrations/add_permissions_to_user_club.sql
```
Dies fügt folgende Spalten zur `user_club` Tabelle hinzu:
- `role` (VARCHAR) - Benutzerrolle (admin, trainer, team_manager, member)
- `permissions` (JSON) - Custom Permissions
- `is_owner` (BOOLEAN) - Markiert den Club-Ersteller
## Schritt 2: Bestehende Daten migrieren
Sie haben zwei Optionen:
### Option A: Node.js Script (Empfohlen)
Das Script identifiziert automatisch den ersten Benutzer jedes Clubs (nach `createdAt`) und setzt ihn als Owner.
```bash
cd /home/torsten/Programs/trainingstagebuch/backend
node scripts/migratePermissions.js
```
**Ausgabe:**
```
Starting permissions migration...
Found 3 club(s)
--- Club: TTC Beispiel (ID: 1) ---
Members found: 5
First member (will be owner): admin@example.com
✓ Updated admin@example.com: role=admin, isOwner=true
✓ Updated user1@example.com: role=member, isOwner=false
✓ Updated user2@example.com: role=member, isOwner=false
...
✅ Migration completed successfully!
Summary:
Club Owners (3):
- TTC Beispiel: admin@example.com
- SV Teststadt: owner@test.de
- TSC Demo: demo@example.com
Role Distribution:
- Admins: 3
- Members: 12
```
### Option B: SQL Script
Wenn Sie lieber SQL verwenden möchten:
```bash
mysql -u username -p database_name < backend/migrations/update_existing_user_club_permissions.sql
```
Dieses Script:
1. Setzt `role = 'member'` für alle genehmigten Benutzer ohne Rolle
2. Markiert den Benutzer mit der niedrigsten `user_id` pro Club als Owner
## Schritt 3: Manuelle Anpassungen (Optional)
### Falscher Owner?
Falls das Script den falschen Benutzer als Owner markiert hat, können Sie dies manuell korrigieren:
```sql
-- Alten Owner zurücksetzen
UPDATE user_club
SET is_owner = 0, role = 'member'
WHERE club_id = 1 AND user_id = 123;
-- Neuen Owner setzen
UPDATE user_club
SET is_owner = 1, role = 'admin'
WHERE club_id = 1 AND user_id = 456;
```
### Weitere Admins ernennen
```sql
UPDATE user_club
SET role = 'admin'
WHERE club_id = 1 AND user_id = 789;
```
### Trainer ernennen
```sql
UPDATE user_club
SET role = 'trainer'
WHERE club_id = 1 AND user_id = 101;
```
## Schritt 4: Verifizierung
### Backend neu starten
```bash
# Server neu starten (wenn er läuft)
sudo systemctl restart tt-tagebuch
```
### Im Browser testen
1. Loggen Sie sich ein
2. Wählen Sie einen Club aus
3. Navigieren Sie zu "Berechtigungen" (nur für Admins sichtbar)
4. Überprüfen Sie, dass alle Mitglieder korrekt angezeigt werden
### SQL Verifizierung
```sql
-- Alle Club-Mitglieder mit ihren Berechtigungen anzeigen
SELECT
c.name as club_name,
u.email as user_email,
uc.role,
uc.is_owner,
uc.approved
FROM user_club uc
JOIN club c ON c.id = uc.club_id
JOIN user u ON u.id = uc.user_id
WHERE uc.approved = 1
ORDER BY c.name, uc.is_owner DESC, uc.role, u.email;
```
## Troubleshooting
### Problem: "Keine Berechtigung" trotz Owner-Status
**Lösung:** Überprüfen Sie in der Datenbank:
```sql
SELECT role, is_owner, approved
FROM user_club
WHERE user_id = YOUR_USER_ID AND club_id = YOUR_CLUB_ID;
```
Sollte sein: `role='admin'`, `is_owner=1`, `approved=1`
### Problem: Owner kann nicht geändert werden
Das ist korrekt! Der Owner (Club-Ersteller) kann seine eigenen Rechte nicht verlieren. Dies ist eine Sicherheitsmaßnahme.
### Problem: Berechtigungen werden nicht geladen
**Lösung:**
1. Browser-Cache leeren
2. LocalStorage leeren: `localStorage.clear()` in der Browser-Console
3. Neu einloggen
### Problem: "Lade Mitglieder..." bleibt hängen
**Mögliche Ursachen:**
1. Migration noch nicht ausgeführt
2. Backend nicht neu gestartet
3. Frontend nicht neu gebaut
**Lösung:**
```bash
# Backend
cd /home/torsten/Programs/trainingstagebuch/backend
node scripts/migratePermissions.js
# Frontend
cd /home/torsten/Programs/trainingstagebuch/frontend
npm run build
# Server neu starten
sudo systemctl restart tt-tagebuch
```
## Nach der Migration
### Neue Clubs
Bei neuen Clubs wird der Ersteller automatisch als Owner mit Admin-Rechten eingerichtet. Keine manuelle Aktion erforderlich.
### Neue Mitglieder
Neue Mitglieder erhalten automatisch die Rolle "member" (Lesezugriff). Admins können die Rolle später ändern.
### Berechtigungen verwalten
Admins können über die Web-UI unter `/permissions` Berechtigungen verwalten:
1. Rollen zuweisen (Admin, Trainer, Mannschaftsführer, Mitglied)
2. Custom Permissions definieren (für spezielle Anwendungsfälle)
## Wichtige Hinweise
⚠️ **Sicherung erstellen:**
```bash
mysqldump -u username -p database_name > backup_before_permissions_$(date +%Y%m%d).sql
```
⚠️ **Owner-Rechte:**
- Der Owner (is_owner=1) kann nicht degradiert oder gelöscht werden
- Jeder Club hat genau einen Owner
- Owner-Rechte können nicht übertragen werden (nur durch direkte DB-Änderung)
⚠️ **MyTischtennis:**
- MyTischtennis-Funktionen sind für ALLE Mitglieder zugänglich
- Keine Berechtigungsprüfung für MyTischtennis-Endpunkte
## Rollback (falls nötig)
Falls Sie das Berechtigungssystem zurücknehmen müssen:
```sql
-- Spalten entfernen (Achtung: Datenverlust!)
ALTER TABLE user_club
DROP COLUMN role,
DROP COLUMN permissions,
DROP COLUMN is_owner;
-- Indizes entfernen
DROP INDEX idx_user_club_role ON user_club;
DROP INDEX idx_user_club_owner ON user_club;
```
Dann Backend-Code auf vorherige Version zurücksetzen.

View File

@@ -1,69 +0,0 @@
# Server Node.js Upgrade-Anleitung
## Problem
Der Server verwendet Node.js 20.17.0, aber Vite 7.2.4 benötigt Node.js 20.19+ oder 22.12+.
## Lösung 1: Node.js auf dem Server upgraden (Empfohlen)
### Option A: Node.js 20.19+ installieren
```bash
# Auf dem Server:
# Mit nvm (falls installiert):
nvm install 20.19.0
nvm use 20.19.0
nvm alias default 20.19.0
# Oder mit NodeSource Repository:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs=20.19.0-1nodesource1
# Prüfe Version:
node --version # Sollte 20.19.0 oder höher sein
```
### Option B: Node.js 22.12+ installieren (LTS)
```bash
# Auf dem Server:
# Mit nvm:
nvm install 22.12.0
nvm use 22.12.0
nvm alias default 22.12.0
# Oder mit NodeSource Repository:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# Prüfe Version:
node --version # Sollte 22.12.0 oder höher sein
```
### Nach dem Upgrade
```bash
cd /var/www/tt-tagebuch.de/backend
npm install # Erstellt automatisch den Frontend-Build
sudo systemctl restart tt-tagebuch
```
## Lösung 2: Vite auf Version 6 downgraden (Temporär)
Falls Node.js nicht upgradet werden kann, wurde Vite bereits auf Version 6.0.0 downgraded.
```bash
cd /var/www/tt-tagebuch.de/backend
npm install # Erstellt automatisch den Frontend-Build
sudo systemctl restart tt-tagebuch
```
**Hinweis:** Vite 6 funktioniert mit Node.js 20.17.0, aber Vite 7 bietet bessere Performance und Features.
## Empfehlung
**Node.js upgraden** ist die bessere Lösung, da:
- Vite 7 bessere Performance bietet
- Zukünftige Updates einfacher sind
- Node.js 20.19+ oder 22.12+ LTS-Versionen sind

View File

@@ -1,109 +0,0 @@
# Sitemap für Google Search Console einreichen
## Aktuelle Sitemap
Die Sitemap ist verfügbar unter: `https://tt-tagebuch.de/sitemap.xml`
Sie enthält folgende öffentliche Seiten:
- `/` (Home) - Priorität: 1.0
- `/register` (Registrierung) - Priorität: 0.8
- `/login` (Anmeldung) - Priorität: 0.7
- `/impressum` (Impressum) - Priorität: 0.3
- `/datenschutz` (Datenschutz) - Priorität: 0.3
## Sitemap aktualisieren
### Automatisch (empfohlen)
```bash
./update-sitemap.sh
```
Das Skript aktualisiert automatisch das `lastmod`-Datum auf das heutige Datum.
### Manuell
Die Sitemap-Datei befindet sich in: `frontend/public/sitemap.xml`
Nach Änderungen:
1. Frontend neu bauen: `cd frontend && npm run build`
2. Backend neu starten (falls nötig)
## Sitemap in Google Search Console einreichen
### Schritt 1: Google Search Console öffnen
1. Gehe zu: https://search.google.com/search-console
2. Wähle die Property für `tt-tagebuch.de` aus
### Schritt 2: Sitemap hinzufügen
1. Klicke im linken Menü auf **"Sitemaps"**
2. Im Feld **"Neue Sitemap hinzufügen"** eingeben:
```
sitemap.xml
```
Oder die vollständige URL:
```
https://tt-tagebuch.de/sitemap.xml
```
3. Klicke auf **"Senden"**
### Schritt 3: Status prüfen
- Google wird die Sitemap innerhalb weniger Minuten verarbeiten
- Der Status wird angezeigt:
- ✅ **Erfolgreich**: Sitemap wurde erfolgreich verarbeitet
- ⚠️ **Warnung**: Sitemap wurde verarbeitet, aber es gibt Warnungen
- ❌ **Fehler**: Sitemap konnte nicht verarbeitet werden
### Schritt 4: Indexierung anfordern
Nach dem Einreichen der Sitemap kannst du auch einzelne URLs zur Indexierung anfordern:
1. Gehe zu **"URL-Prüfung"**
2. Gib die URL ein: `https://tt-tagebuch.de/`
3. Klicke auf **"Indexierung anfordern"**
## Sitemap testen
### Online-Tools
- Google Sitemap Tester: https://www.xml-sitemaps.com/validate-xml-sitemap.html
- Sitemap Validator: https://validator.w3.org/
### Per Kommandozeile
```bash
# Sitemap abrufen
curl https://tt-tagebuch.de/sitemap.xml
# XML-Validierung (falls xmllint installiert ist)
curl -s https://tt-tagebuch.de/sitemap.xml | xmllint --noout -
```
## Wichtige Hinweise
1. **robots.txt**: Die Sitemap ist bereits in der `robots.txt` referenziert:
```
Sitemap: https://tt-tagebuch.de/sitemap.xml
```
2. **lastmod-Datum**: Wird automatisch beim Ausführen von `update-sitemap.sh` aktualisiert
3. **Nur öffentliche Seiten**: Die Sitemap enthält nur öffentlich zugängliche Seiten. Geschützte Seiten (die eine Anmeldung erfordern) sind nicht enthalten.
4. **Prioritäten**:
- Homepage: 1.0 (höchste Priorität)
- Registrierung/Login: 0.7-0.8 (wichtig für neue Nutzer)
- Rechtliche Seiten: 0.3 (niedrige Priorität, ändern sich selten)
## Troubleshooting
### Sitemap wird nicht gefunden
- Prüfe, ob die Sitemap unter `https://tt-tagebuch.de/sitemap.xml` erreichbar ist
- Stelle sicher, dass das Frontend gebaut wurde: `cd frontend && npm run build`
- Prüfe die Apache-Konfiguration (sollte statische Dateien aus `/var/www/tt-tagebuch.de` servieren)
### Sitemap wird nicht indexiert
- Warte einige Stunden/Tage - Google braucht Zeit zum Crawlen
- Prüfe in der Search Console, ob es Fehler gibt
- Stelle sicher, dass die URLs in der Sitemap erreichbar sind
- Prüfe, ob die `robots.txt` die Seiten nicht blockiert
### Sitemap enthält Fehler
- Validiere die XML-Struktur mit einem XML-Validator
- Prüfe, ob alle URLs korrekt sind (keine 404-Fehler)
- Stelle sicher, dass alle URLs HTTPS verwenden (nicht HTTP)

View File

@@ -1,2 +0,0 @@
#Thu Mar 05 14:01:17 CET 2026
gradle.version=8.7

View File

@@ -1,92 +0,0 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.serialization")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
namespace = "de.trainingstagebuch.app"
compileSdk = 34
defaultConfig {
applicationId = "de.trainingstagebuch.app"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
tasks.register<Exec>("checkI18nHardcodedUiStrings") {
workingDir = rootProject.projectDir
commandLine("bash", "scripts/check_no_hardcoded_ui_strings.sh")
}
tasks.named("preBuild").configure {
dependsOn("checkI18nHardcodedUiStrings")
}
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2024.10.01")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
implementation("androidx.activity:activity-compose:1.9.3")
implementation(composeBom)
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("androidx.navigation:navigation-compose:2.8.3")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7")
implementation("androidx.datastore:datastore-preferences:1.1.1")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
testImplementation("junit:junit:4.13.2")
debugImplementation(composeBom)
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}

View File

@@ -1,2 +0,0 @@
#- File Locator -
listingFile=../../../../outputs/apk/debug/output-metadata.json

View File

@@ -1,2 +0,0 @@
appMetadataVersion=1.1
androidGradlePluginVersion=8.5.2

View File

@@ -1,10 +0,0 @@
{
"version": 3,
"artifactType": {
"type": "COMPATIBLE_SCREEN_MANIFEST",
"kind": "Directory"
},
"applicationId": "de.trainingstagebuch.app",
"variantName": "debug",
"elements": []
}

Some files were not shown because too many files have changed in this diff Show More