diff --git a/models.py b/models.py index ef6ad6f..1768b44 100644 --- a/models.py +++ b/models.py @@ -58,8 +58,7 @@ class TicketWave(BaseModel): class EventExtraBase(BaseModel): - """Everything in `extra` that is safe to show anyone — ticket waves - included, since a buyer needs a wave id to choose one. `EventExtra` adds + """Everything in `extra` that is safe to show anyone. `EventExtra` adds the organizer-only promo codes on top; `PublicEventExtra` is this base, so anonymous responses can never carry them.""" @@ -74,19 +73,6 @@ class EventExtraBase(BaseModel): # `effective_payment_methods`. Same field name/shape as upstream v2 so the # eventual rebase (#33) merges cleanly. payment_methods: list[str] = Field(default_factory=list) - # Upstream v1.6.8 ticket waves — time-boxed pricing tiers. The - # event-level `currency` / `allow_fiat` / `amount_tickets` / - # `price_per_ticket` fields become derived values (see - # `sync_event_ticket_waves`), which is why fork code that reads them - # needs auditing — aiolabs/events#61. - # - # Public, not organizer-only: a buyer cannot choose a wave without its - # id, and neither the public event response nor the NIP-52 tags carried - # one before. A wave holds price, dates and remaining stock — the sales - # information a buyer needs — so the only thing exposing it reveals is - # the upcoming price schedule, which is what #61 regretted giving up - # when it settled on flat Nostr tags. - ticket_waves: list[TicketWave] = Field(default_factory=list) @validator("payment_methods", pre=True) def normalize_payment_methods(cls, v): @@ -106,6 +92,12 @@ class EventExtraBase(BaseModel): class EventExtra(EventExtraBase): promo_codes: list[PromoCode] = Field(default_factory=list) + # Upstream v1.6.8 ticket waves — time-boxed pricing tiers. The + # event-level `currency` / `allow_fiat` / `amount_tickets` / + # `price_per_ticket` fields become derived values (see + # `sync_event_ticket_waves`), which is why fork code that reads them + # needs auditing — aiolabs/events#61. + ticket_waves: list[TicketWave] = Field(default_factory=list) PublicEventExtra = EventExtraBase diff --git a/tests/test_ticket_models.py b/tests/test_ticket_models.py index 3a42e8f..7d1ab3f 100644 --- a/tests/test_ticket_models.py +++ b/tests/test_ticket_models.py @@ -5,10 +5,6 @@ from ..models import ( CreateEvent, CreateTicket, EventExtra, - PromoCode, - PublicEvent, - PublicEventExtra, - TicketWave, effective_payment_methods, ) @@ -112,63 +108,3 @@ def test_payment_methods_are_normalised_and_deduplicated(): def test_unknown_payment_method_is_rejected(): with pytest.raises(ValidationError): EventExtra(payment_methods=["cash"]) - - -# --- public projection ------------------------------------------------------ - - -def test_public_extra_exposes_waves_but_never_promo_codes(): - """A buyer needs a wave id to choose a tier, so waves are public; promo - codes stay organizer-only (aiolabs/events#61, v1.6.1-aio.12).""" - organizer = EventExtra( - promo_codes=[PromoCode(code="SECRET", discount_percent=50)], - ticket_waves=[ - TicketWave( - id="early", - title="Early", - opening_date="2030-01-01", - closing_date="2030-02-01", - currency="sat", - price_per_ticket=10, - amount_tickets=5, - ) - ], - ) - - public = PublicEventExtra(**organizer.dict()) - - assert [wave.id for wave in public.ticket_waves] == ["early"] - assert public.ticket_waves[0].price_per_ticket == 10 - assert not hasattr(public, "promo_codes") - assert "promo_codes" not in public.dict() - - -def test_public_event_response_carries_waves(): - """End of the chain: what `GET /events/{id}` actually serialises.""" - wave = TicketWave( - id="regular", - title="Regular", - opening_date="2030-01-01", - closing_date="2030-02-01", - currency="sat", - price_per_ticket=25, - amount_tickets=40, - ) - organizer_extra = EventExtra( - ticket_waves=[wave], promo_codes=[PromoCode(code="SECRET")] - ) - public = PublicEvent( - id="evt", - name="Test", - info="", - canceled=False, - event_start_date="2030-01-01", - currency="sat", - price_per_ticket=25, - banner=None, - extra=PublicEventExtra(**organizer_extra.dict()), - ) - body = public.dict() - - assert [w["id"] for w in body["extra"]["ticket_waves"]] == ["regular"] - assert "promo_codes" not in body["extra"]