175 lines
3.3 KiB
Markdown
175 lines
3.3 KiB
Markdown
# API-Design: Beisel Rallye 🍺
|
|
|
|
## Übersicht
|
|
|
|
Die API ermöglicht server-seitige Speicherung aller Rallye-Einträge und unterstützt echte Multi-User-Funktionalität über verschiedene Geräte hinweg.
|
|
|
|
## Endpunkte
|
|
|
|
### 1. Bezirk besuchen (POST /api/visit)
|
|
|
|
**Zweck:** Neuen Besuch eines Bezirks speichern
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"user_name": "Gregor",
|
|
"district": "I. Innere Stadt",
|
|
"beisel_name": "Schloßhotel Greising"
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Bezirk gespeichert!",
|
|
"data": {
|
|
"id": 6,
|
|
"user_name": "Gregor",
|
|
"district": "I. Innere Stadt",
|
|
"beisel_name": "Schloßhotel Greising",
|
|
"timestamp": "2026-06-29T10:30:00.000Z"
|
|
},
|
|
"progress": {
|
|
"visited_count": 8,
|
|
"total_districts": 17,
|
|
"percentage": 47
|
|
}
|
|
}
|
|
```
|
|
|
|
**Fehler (400 Bad Request):**
|
|
```json
|
|
{
|
|
"success": false,
|
|
"error": "Ungültige Eingabe",
|
|
"details": {
|
|
"user_name": "Pflichtfeld",
|
|
"district": "Ungültiger Bezirk"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2. Fortschritt abrufen (GET /api/status/:username)
|
|
|
|
**Zweck:** Aktuelle Rallye-Statistik für einen Benutzer laden
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"user_name": "Gregor",
|
|
"progress": {
|
|
"visited_count": 8,
|
|
"total_districts": 17,
|
|
"percentage": 47
|
|
},
|
|
"visits": [
|
|
{
|
|
"district": "I. Innere Stadt",
|
|
"beisel_name": "Schloßhotel Greising",
|
|
"timestamp": "2026-06-29T10:30:00.000Z"
|
|
},
|
|
{
|
|
"district": "II. St. Leonhard",
|
|
"beisel_name": "Jazzkeller",
|
|
"timestamp": "2026-06-29T11:15:00.000Z"
|
|
}
|
|
],
|
|
"last_updated": "2026-06-29T11:15:00.000Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Alle Teilnehmer anzeigen (GET /api/all-users)
|
|
|
|
**Zweck:** Leaderboard mit allen aktiven Teilnehmern
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"users": [
|
|
{
|
|
"user_name": "Gregor",
|
|
"visited_count": 8,
|
|
"last_active": "2026-06-29T11:15:00.000Z"
|
|
},
|
|
{
|
|
"user_name": "Maria",
|
|
"visited_count": 12,
|
|
"last_active": "2026-06-29T10:45:00.000Z"
|
|
}
|
|
],
|
|
"total_users": 2,
|
|
"generated_at": "2026-06-29T12:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4. Reset für User (DELETE /api/reset/:username)
|
|
|
|
**Zweck:** Alle Einträge eines Users löschen
|
|
|
|
**Response (200 OK):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Alle Einträge für 'Gregor' gelöscht",
|
|
"deleted_count": 5
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Fehlerbehandlung
|
|
|
|
### Allgemeine Fehler (4xx/5xx)
|
|
```json
|
|
{
|
|
"error_code": "INTERNAL_ERROR",
|
|
"message": "Unerwarteter Serverfehler",
|
|
"timestamp": "2026-06-29T12:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
### Validierungsfehler (400)
|
|
```json
|
|
{
|
|
"error_code": "VALIDATION_ERROR",
|
|
"message": "Ungültige Eingabe",
|
|
"details": {
|
|
"field_name": ["Fehlermeldung"]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Implementierungs-Hinweise
|
|
|
|
### Datenbank-Operationen
|
|
- Verwende `sqlite3` Package für asynchrone Operationen
|
|
- Parameterisierte Queries gegen SQL Injection schützen
|
|
- Connection Pooling für bessere Performance
|
|
|
|
### Rate Limiting
|
|
- Max. 10 Anfragen pro Minute pro IP
|
|
- Besonders bei POST /api/visit wichtig
|
|
|
|
### Sicherheit
|
|
- Input Validation auf allen Endpunkten
|
|
- User-Namen sanitieren (keine Script-Injection)
|
|
- CORS Headers setzen falls nötig
|
|
|
|
### Performance
|
|
- SQLite ist ausreichend für diese Anwendung
|
|
- Keine komplexen Joins notwendig
|
|
- Periodische Datenbank-Vacuum Operationen empfohlen
|
|
|
|
---
|
|
*Stand: 2026-06-29 | Version: 1.0*
|