Initial commit: Beisel Rallye Graz Project with full documentation
This commit is contained in:
+174
@@ -0,0 +1,174 @@
|
||||
# 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*
|
||||
Reference in New Issue
Block a user