Removed obsolete documentation and planning.
This commit is contained in:
@@ -1,136 +0,0 @@
|
|||||||
# Slip It In – Architektur-Updates (Phase 2b & 3b)
|
|
||||||
|
|
||||||
Dieses Dokument fasst die Sicherheits- und Stabilitäts-Erweiterungen zusammen, die dem ProjectPlan.md hinzugefügt wurden.
|
|
||||||
|
|
||||||
## 🔒 Backend-Sicherheit (Phase 2b)
|
|
||||||
|
|
||||||
### 1. JWT-Claims Validation im GameHub
|
|
||||||
- **Problem**: Clients könnten falsche PlayerId-Claims senden (Spoofing)
|
|
||||||
- **Lösung**: `GetAuthenticatedUserId()` extrahiert User-ID aus JWT-Claims
|
|
||||||
- **Implementierung**: Jede Hub-Methode validiert `Context.User?.FindFirst(ClaimTypes.NameIdentifier)`
|
|
||||||
|
|
||||||
### 2. IDbContextFactory statt Scoped DbContext
|
|
||||||
- **Problem**: Bei parallelen SignalR-Aufrufen kann es zu Race Conditions kommen
|
|
||||||
- **Lösung**: `IDbContextFactory<SlipItInDbContext>` erzeugt isolierte Sessions pro Aufruf
|
|
||||||
- **Vorteil**: Phrase-Transfer ist thread-safe, keine Conflicts bei 2 gleichzeitigen Challenges
|
|
||||||
|
|
||||||
### 3. Serverseitige Validierung
|
|
||||||
- **Regel**: Clients senden nur "Ich möchte X machen", Server prüft ALLES
|
|
||||||
- **Beispiel**: `SubmitSlipAsync()` prüft auf dem Server:
|
|
||||||
- ✅ Gehört die Phrase dem Spieler?
|
|
||||||
- ✅ Ist die Runde aktiv?
|
|
||||||
- ✅ Ist der Spieler noch im Spiel?
|
|
||||||
|
|
||||||
### 4. Daten-Isolation (GameStateDto vs. PlayerHandDto)
|
|
||||||
- **GameStateDto**: Öffentliche Daten (Username, Score, CardCount) → für ALLE sichtbar
|
|
||||||
- **PlayerHandDto**: Private Daten (Text der eigenen Karten) → nur für den Spieler selbst
|
|
||||||
- **Ergebnis**: Gegner sehen nicht, welche Phrasen ich habe!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📱 Client-Stabilität (Phase 3b)
|
|
||||||
|
|
||||||
### 1. WeakReferenceMessenger für Event-Entkopplung
|
|
||||||
- **Problem**: Services rufen ViewModels direkt auf → Memory Leaks wenn VM disposed
|
|
||||||
- **Lösung**: Services senden Messages via `WeakReferenceMessenger.Default.Send()`
|
|
||||||
- **Vorteil**: ViewModels können sich abmelden ohne zirkuläre Abhängigkeiten
|
|
||||||
|
|
||||||
**Beispiel:**
|
|
||||||
```csharp
|
|
||||||
// Service sendet Event
|
|
||||||
WeakReferenceMessenger.Default.Send(new GameStateChangedMessage(newState));
|
|
||||||
|
|
||||||
// ViewModel empfängt (mit auto-cleanup beim Dispose)
|
|
||||||
WeakReferenceMessenger.Default.Register<GameStateChangedMessage>(this, (r, m) =>
|
|
||||||
{
|
|
||||||
CurrentGameState = m.Value;
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Automatischer Reconnect
|
|
||||||
- **Strategie**: Exponential Backoff (0s → 2s → 10s → 30s)
|
|
||||||
- **Pufferung**: Offline-Aktionen werden in lokale Queue geschrieben
|
|
||||||
- **Resync**: Nach Reconnect wird `ResyncAsync()` aufgerufen
|
|
||||||
|
|
||||||
**Flow:**
|
|
||||||
1. SignalR-Verbindung getrennt
|
|
||||||
2. Client speichert "Slip zu Phrase X" in lokale Queue
|
|
||||||
3. Nach 2s Automatischer Reconnect-Versuch
|
|
||||||
4. Nach erfolgreichem Reconnect: Queued Actions werden abgesendet
|
|
||||||
|
|
||||||
### 3. State Restoration
|
|
||||||
- **App-Pause**: `GameStateService` speichert aktuellen State in `SecureStorage`
|
|
||||||
- **App-Resume**: `ResyncAsync()` wird aufgerufen
|
|
||||||
- ✅ Holt aktuellen GameState vom Server
|
|
||||||
- ✅ Sendet gepufferte Offline-Aktionen erneut
|
|
||||||
- ✅ UI zeigt "Syncing..." bis fertig
|
|
||||||
|
|
||||||
### 4. Dual-Layer Storage
|
|
||||||
- **In-Memory Layer**: `GameStateService` halten aktuellen State
|
|
||||||
- **Persistent Layer**: `SecureStorage`/`Preferences` speichern Backup
|
|
||||||
- **Fehler-Handling**: Nach App-Crash kann State aus Persistent Layer wiederhergestellt werden
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Schnellreferenz: Neue Components
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
```
|
|
||||||
GameHub
|
|
||||||
├─ GetAuthenticatedUserId() → JWT-Validierung
|
|
||||||
├─ ValidatePlayerAccessAsync() → Authorization Check
|
|
||||||
└─ Alle Methoden nutzen IDbContextFactory
|
|
||||||
|
|
||||||
Program.cs
|
|
||||||
├─ AddDbContextFactory<SlipItInDbContext>()
|
|
||||||
├─ AddAuthentication(JwtBearerDefaults)
|
|
||||||
└─ AddSignalR() mit JWT-Filter
|
|
||||||
|
|
||||||
DTOs
|
|
||||||
├─ GameStateDto (öffentlich)
|
|
||||||
├─ PlayerHandDto (privat)
|
|
||||||
└─ Keine CardText in GameStateDto!
|
|
||||||
```
|
|
||||||
|
|
||||||
### Client
|
|
||||||
```
|
|
||||||
GameStateService
|
|
||||||
├─ CurrentGameState (in-memory)
|
|
||||||
├─ CurrentPlayerHand (in-memory)
|
|
||||||
├─ UpdateGameStateAsync() → speichert + sendet Message
|
|
||||||
└─ ResyncAsync() → bei App-Resume
|
|
||||||
|
|
||||||
SignalRService
|
|
||||||
├─ ConnectAsync(token) mit Auto-Reconnect
|
|
||||||
├─ RequestGameStateAsync()
|
|
||||||
└─ On<> Handler senden Messages
|
|
||||||
|
|
||||||
Messages (WeakReferenceMessenger)
|
|
||||||
├─ GameStateChangedMessage
|
|
||||||
├─ PlayerHandChangedMessage
|
|
||||||
└─ ChallengeReceivedMessage
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 Wichtigste Tests
|
|
||||||
|
|
||||||
| Test | Ziel |
|
|
||||||
|------|------|
|
|
||||||
| **JWT-Auth** | Hub lehnt Requests ohne gültiges Token ab |
|
|
||||||
| **Player-Access** | User A kann nicht auf Players von User B zugreifen |
|
|
||||||
| **Race Condition** | Phrase-Transfer ist thread-safe bei 2 gleichzeitigen Challenges |
|
|
||||||
| **Offline-Queue** | Aktionen während Netzwerk-Ausfall werden gepuffert und später gesendet |
|
|
||||||
| **Memory Leaks** | Keine Leaks wenn ViewModels disposed werden (WeakReference) |
|
|
||||||
| **State-Sync** | App-Resume synct korrekt mit Server-State |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Implementierungs-Reihenfolge
|
|
||||||
|
|
||||||
1. **Backend zuerst**: JWT-Auth + IDbContextFactory konfigurieren
|
|
||||||
2. **GameService erweitern**: Serverseitige Validierung in alle Methoden
|
|
||||||
3. **Client-Services**: GameStateService + SignalRService implementieren
|
|
||||||
4. **Messaging**: WeakReferenceMessenger in ViewModels integrieren
|
|
||||||
5. **Tests**: Integrationstest-Suite schreiben
|
|
||||||
6. **UI**: Views an neue Message-Events binden
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user