-
Notifications
You must be signed in to change notification settings - Fork 147
Open
Description
Cart checkout allows overselling when lock is skipped
The Problem
Found a race condition in eventyay/base/services/orders.py (lines 1180-1188) that lets multiple people buy the last ticket simultaneously.
The code has a "performance optimization" that skips locking the event during checkout when:
- No voucher is used
- Cart isn't expiring soon (>2 minutes left)
- No seat selection
if positions.filter(
Q(voucher__isnull=False) | Q(expires__lt=now() + timedelta(minutes=2)) | Q(seat__isnull=False)
).exists():
# Performance optimization comment...
locked = True
lockfn = event.lock
with lockfn() as now_dt:
# order creationWhen that condition is false, lockfn stays as a no-op function and multiple checkouts can happen at once.
What Happens
Expected: If there's 1 ticket left and 2 people checkout, only 1 should succeed.
Actual: Both succeed. You get 2 orders for a quota of 1.
How to Reproduce
- Create an event with 1 ticket available
- Open two browser windows
- Add the product to cart in both (make sure cart expires >2 mins away, no vouchers)
- Click checkout in both windows at the same time
- Both orders go through → quota shows 2/1 sold
Works consistently in testing, confirmed on test event aer/xgzvvq on local device
Related
Found this while fixing #1344 (payment duplicate confirmation bug). Same pattern.
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
Status
In progress