Allow an event owner to add co-organizers who can scan tickets #50

Open
opened 2026-09-26 12:27:22 +00:00 by padreug · 0 comments
Owner

Right now only the account that owns the event's wallet can scan tickets at the door. Anyone else helping run the event has no way in — they land on the public event page and the only thing offered is a Buy button.

We want the organizer to be able to name additional accounts as co-organizers of an event. A co-organizer doesn't buy a ticket; when they open the event page they get the scanner instead.

Where the ownership check lives today

Both scanner paths resolve the caller to a wallet and require that wallet to own the event:

  • transport_rpcs.py — handle_events_ticket_register and handle_events_list_event_tickets: if event.wallet not in owned_wallet_ids: raise PermissionError("You do not own this event")
  • the equivalent HTTP register / list endpoints in views_api.py
  • webapp: EventDetailPage.vue decides via loadOwnedEvent() — it calls fetchMyEvents(invoiceKey) and looks for the event id in the result. An event the user co-organizes isn't in "my events", so ownedLnbitsEvent stays null and the scanner block never renders.

So it's three places: storage for the co-organizer list, an authorization helper both scanner paths use, and something the webapp can ask "can I scan this?".

Sketch

  • Store co-organizers on the event (extra.co_organizers, list of LNbits user ids). migrations_fork.py if it needs a column.
  • One helper, e.g. can_manage_event(event, user) -> bool, returning true for the wallet owner or a listed co-organizer. Both RPCs and both HTTP endpoints call it instead of the inline event.wallet not in owned_wallet_ids check.
  • Keep the split between manage and scan: a co-organizer should scan and see the roster, but editing the event, pricing, promo codes and refunds stay with the owner. Two predicates rather than one if that's cleaner.
  • Admin UI: a field on the event form to add/remove co-organizers by user id (or by npub, resolved server-side).
  • Webapp: the current "am I the organizer?" test is fetchMyEvents membership, which won't cover this. Needs either a co_organizer flag on the event payload or a small "can I scan this event" call, and EventDetailPage.vue gating the scanner on that instead of ownedLnbitsEvent.

Open questions

  • Identity: LNbits user id, or npub? npub is nicer for the webapp (the user is already logged in with Nostr) but the register RPC authenticates to a wallet, so it has to resolve to an account either way.
  • How does a co-organizer find the event? They'd need the link, or it shows up in some "events I help run" list.
  • Nothing about this should go in the published NIP-52 event — co-organizer list stays server-side.
Right now only the account that owns the event's wallet can scan tickets at the door. Anyone else helping run the event has no way in — they land on the public event page and the only thing offered is a Buy button. We want the organizer to be able to name additional accounts as co-organizers of an event. A co-organizer doesn't buy a ticket; when they open the event page they get the scanner instead. ## Where the ownership check lives today Both scanner paths resolve the caller to a wallet and require that wallet to own the event: - `transport_rpcs.py` — `handle_events_ticket_register` and `handle_events_list_event_tickets`: `if event.wallet not in owned_wallet_ids: raise PermissionError("You do not own this event")` - the equivalent HTTP register / list endpoints in `views_api.py` - webapp: `EventDetailPage.vue` decides via `loadOwnedEvent()` — it calls `fetchMyEvents(invoiceKey)` and looks for the event id in the result. An event the user co-organizes isn't in "my events", so `ownedLnbitsEvent` stays null and the scanner block never renders. So it's three places: storage for the co-organizer list, an authorization helper both scanner paths use, and something the webapp can ask "can I scan this?". ## Sketch - Store co-organizers on the event (`extra.co_organizers`, list of LNbits user ids). `migrations_fork.py` if it needs a column. - One helper, e.g. `can_manage_event(event, user) -> bool`, returning true for the wallet owner or a listed co-organizer. Both RPCs and both HTTP endpoints call it instead of the inline `event.wallet not in owned_wallet_ids` check. - Keep the split between manage and scan: a co-organizer should scan and see the roster, but editing the event, pricing, promo codes and refunds stay with the owner. Two predicates rather than one if that's cleaner. - Admin UI: a field on the event form to add/remove co-organizers by user id (or by npub, resolved server-side). - Webapp: the current "am I the organizer?" test is `fetchMyEvents` membership, which won't cover this. Needs either a `co_organizer` flag on the event payload or a small "can I scan this event" call, and `EventDetailPage.vue` gating the scanner on that instead of `ownedLnbitsEvent`. ## Open questions - Identity: LNbits user id, or npub? npub is nicer for the webapp (the user is already logged in with Nostr) but the register RPC authenticates to a wallet, so it has to resolve to an account either way. - How does a co-organizer find the event? They'd need the link, or it shows up in some "events I help run" list. - Nothing about this should go in the published NIP-52 event — co-organizer list stays server-side.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/events#50
No description provided.