Skip to main content

Planners

What it is​

Governs co-planner access to an event — who besides the event owner can manage what. Nearly every other guide on this site references isEventPlanner([EventSections.X]) middleware gating a route; this module is where those permissions actually get granted, checked, and revoked.

Core concepts​

  • EventSections is the permission unit — PartyBank, Rsvp, Vendor, TicketHero, MiniShop, GiftRegistry, PlannerAccessControl, and others, each independently grantable per co-planner. A planner might have Rsvp access but not PartyBank — permissions aren't all-or-nothing.
  • PlannerAccessControl is itself a section — managing other planners' permissions is gated the same way as any other section, meaning a co-planner could theoretically be granted the ability to manage other planners without being the event owner.
  • Owner vs. planner is a separate axis from sections — isEventOwner (only the true event creator) gates a narrower set of actions than isEventPlanner([...]) (any planner with the right section access). Toggling whether planners are even allowed to invite others (allow-planner-invite) is owner-only, not delegable via PlannerAccessControl.

How it works​

  1. GET /planners/event-sections — the full catalog of sections and their metadata (what a client renders as togglable permissions in an invite/manage UI).
  2. POST /planners/event/:eventId/invite — invite a co-planner (requires PlannerAccessControl + transaction PIN).
  3. POST /planners/event/:eventId/planner/:plannerId/permissions — grant/adjust which sections a specific planner has (also PlannerAccessControl + PIN-gated).
  4. GET /planners/event/:eventId/my-permissions — the calling user's own access, for client-side UI to know what to show/hide.
  5. PATCH /planners/event/:eventId/allow-planner-invite — owner-only toggle for whether planners (not just the owner) can invite further planners.
  6. DELETE /planners/event/:eventId/planner/:id — remove a co-planner (PIN-gated).
  7. GET /planners/public/event/:eventId — public, unauthenticated list of an event's planners (for guest-facing display, e.g. "hosted by").

Key business rules & edge cases​

  • Permission-management actions are transaction-PIN-gated, not just role-gated — inviting, changing permissions, and removing a planner all require encryptedPinMiddleware in addition to PlannerAccessControl access. This is the same step-up pattern used for money movement elsewhere, applied here because planner access is itself a sensitive capability (a malicious or compromised co-planner with the right sections could reach PartyBank).
  • Because PlannerAccessControl can be granted to a non-owner, don't assume only the event owner can add/remove other planners — check the actual granted sections, not just "is this the owner."
  • allow-planner-invite being owner-only (not delegable) is a deliberate ceiling — even a planner with full PlannerAccessControl can't turn on the ability for other planners to invite if the owner has it switched off.

GET /v1/planners/event-sections, GET /v1/planners/event/{eventId}/my-permissions, POST /v1/planners/event/{eventId}/invite, POST /v1/planners/event/{eventId}/planner/{plannerId}/permissions, DELETE /v1/planners/event/{eventId}/planner/{id}. Not yet in the generated OpenAPI spec.

  • src/modules/planners/planner.routes.ts, planners.controllers.ts
  • src/shared/enum/event.enum.ts — EventSections
  • src/shared/middlewares/iseventplanner.middleware.ts, iseventowner.middleware.ts
  • src/shared/validations/planners.validation.ts