Wettlauf beim Reservieren, 500er bei unsinnigen Eingaben

Drei P3-Funde aus der Durchsicht vom 14.09.:

Reservieren: Statusprüfung und Schreiben waren getrennt - zwei
gleichzeitige Anfragen konnten beide passieren, die zweite überschrieb
Name und Token der ersten, ohne dass die es erfuhr. Jetzt entscheidet
ein UPDATE mit Status-Bedingung; der Verlierer bekommt None und die
Route meldet "schon weg" (Seite) bzw. 409 (API).

/?limit=abc lieferte jedem anonymen Besucher einen internen
Serverfehler, limit=-1 hiess in SQLite "alles". _limit_lesen() fällt
bei Unsinn auf die Seitengrösse zurück und deckelt bei 500.

Erfassen/Bearbeiten: int(category_id) und die Pydantic-Prüfung warfen
im Handler - 500 statt Fehlermeldung. Jetzt Meldung; ausserdem werden
die Angaben VOR den Bildern geprüft, damit bei abgelehnten Angaben
keine verwaisten Bilddateien liegen bleiben.

Vier neue Tests, jeder einmal gegen den alten Code gelaufen und dabei
rot geworden. 84 lokal grün (HEIC-Test braucht pillow-heif, Docker).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 17:22:54 +02:00
co-authored by Claude Fable 5
parent feceaacabb
commit c0a18ac735
6 changed files with 133 additions and 26 deletions
+16
View File
@@ -89,3 +89,19 @@ def test_name_ohne_werbung(client, item_id):
json={"reserved_by": "Jetzt billig kaufen http://spam.example"},
)
assert antwort.status_code == 422
def test_wettlauf_beim_reservieren_gewinnt_nur_einer(client, item_id, db_sitzung):
"""Zwei Anfragen können beide die Statusprüfung in der Route passieren,
bevor eine schreibt. Das UPDATE mit Status-Bedingung lässt trotzdem nur
eine gewinnen - die zweite bekommt None und überschreibt nichts."""
from app import crud
item = crud.item_holen(db_sitzung, item_id)
erster = crud.reservieren(db_sitzung, item, "A")
zweiter = crud.reservieren(db_sitzung, item, "B")
assert erster is not None
assert zweiter is None
assert item.reserved_by == "A"
assert item.reservation_token is not None
+23
View File
@@ -263,3 +263,26 @@ def test_farbschema_skript_laeuft_vor_dem_zeichnen(client):
def test_umschalter_ist_vorhanden(client):
assert 'id="schema-knopf"' in client.get("/").text
# ------------------------------------------------- Unsinnige Eingaben ---
def test_unsinniges_limit_ist_kein_serverfehler(gast):
"""?limit= kommt aus der URL - Buchstaben oder negative Werte dürfen
keinen 500er auslösen, sondern fallen auf die Seitengrösse zurück."""
assert gast.get("/?limit=abc").status_code == 200
assert gast.get("/teil/liste?limit=-5").status_code == 200
def test_unsinnige_kategorie_gibt_meldung_statt_500(client, kategorie_id):
antwort = erfasse(client, kategorie_id, category_id="abc")
assert antwort.status_code == 200
assert "Bitte die Angaben prüfen" in antwort.text
def test_zu_langer_titel_gibt_meldung_statt_500(client, kategorie_id):
"""maxlength im HTML schützt nur den Browserweg - die Anwendung muss
es selbst abfangen."""
antwort = erfasse(client, kategorie_id, title="x" * 101)
assert antwort.status_code == 200
assert "Bitte die Angaben prüfen" in antwort.text