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
9
SlipItIN.slnx
Normal file
9
SlipItIN.slnx
Normal file
@@ -0,0 +1,9 @@
|
||||
<Solution>
|
||||
<Project Path="SlipItIN.AppHost/SlipItIn.AppHost.csproj" />
|
||||
<Project Path="SlipItIn.Server/SlipItIn.Server.csproj" />
|
||||
<Project Path="SlipItIN.ServiceDefaults/SlipItIn.ServiceDefaults.csproj" />
|
||||
<Project Path="SlipItIn.Shared/SlipItIn.Shared.csproj" />
|
||||
<Project Path="SlipItIN/SlipItIn.csproj">
|
||||
<Deploy Solution="Debug|*" />
|
||||
</Project>
|
||||
</Solution>
|
||||
@@ -1,8 +1,4 @@
|
||||
<Solution>
|
||||
<Folder Name="/Projektmappenelemente/">
|
||||
<File Path="Agents/Architecture.md" />
|
||||
<File Path="Agents/ProjectPlan.md" />
|
||||
</Folder>
|
||||
<Project Path="SlipItIN.AppHost/SlipItIn.AppHost.csproj" />
|
||||
<Project Path="SlipItIn.Server/SlipItIn.Server.csproj" />
|
||||
<Project Path="SlipItIN.ServiceDefaults/SlipItIn.ServiceDefaults.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user