Ticket creation never checks the closing date — tickets sellable after the window shuts #60
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
api_ticket_creategates on status,canceledand capacity. It does not checkclosing_date. The window enforcement lives only inapi_get_event(views_api.py:283-298), the public detail endpoint:Nothing equivalent exists in the ticket endpoint —
grep -n "closing_date\|is_window_open" views_api.pyreturns hits only inapi_get_eventand in create/update field handling.So the UI hides the buy button (it reads
api_get_event, which 410s), but a direct POST to the unauthenticated ticket endpoint goes straight through to pricing and ticket creation.Observed
Found on aio-demo while probing the #59 fix.
KVhCGUrGFP6UyBuEaRA5Zd("Tech Meetup") hasclosing_date = 2026-05-22T12:00:00+02:00— four months past:It reached the capacity check, which is downstream of where a window check would sit. A request for a quantity within capacity would have proceeded to create the ticket. I didn't run that — no reason to mint a real ticket to confirm what the control flow already shows.
Why it matters
closing_dateis also what the conditional-event logic keys on:api_get_eventcancels the event and refunds whenconditional and not is_min_tickets_met and not is_window_open. A sale landing after that has run is a ticket for a cancelled event.Fix
Extract the window computation from
api_get_eventinto a helper and call it from both. Worth handling the same three-way fallback (closing_date or event_end_date or event_start_date) and the two date formats in one place rather than duplicating them — the parsing already has afromisoformat/strptimefallback that shouldn't be written twice.Upstream has no equivalent guard in its ticket endpoint either (v1.6.8's
api_ticket_createcheckscanceledandamount_tickets < 1only), so this is a deliberate fork addition rather than a rebase conflict — worth a row indocs/upstream-candidates.md, since it looks like something upstream would want too.Deploy note
Existing instances have live events with past closing dates (demo has at least three). Adding the guard makes those correctly unsellable; no data change needed.