Add organizer-only attendee list to event detail view (011)
New GET /events/{token}/attendees endpoint returns attendee names when
a valid organizer token is provided (403 otherwise). The frontend
conditionally renders the list below the attendee count for organizers,
silently degrading for visitors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
72
specs/011-view-attendee-list/data-model.md
Normal file
72
specs/011-view-attendee-list/data-model.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Data Model: View Attendee List (011)
|
||||
|
||||
**Date**: 2026-03-08
|
||||
|
||||
## Entities
|
||||
|
||||
### Rsvp (existing — no schema changes)
|
||||
|
||||
The attendee list feature reads from the existing `rsvps` table. No new tables or columns are required.
|
||||
|
||||
| Field | Type | Constraints | Notes |
|
||||
|-------|------|-------------|-------|
|
||||
| id | BIGSERIAL | PK, auto-increment | Chronological order proxy |
|
||||
| rsvp_token | UUID | UNIQUE, NOT NULL | Public identifier |
|
||||
| event_id | BIGINT | FK → events.id, NOT NULL | CASCADE DELETE |
|
||||
| name | VARCHAR(100) | NOT NULL | Display name shown to organizer |
|
||||
|
||||
**Existing indexes**: `idx_rsvps_event_id` (on `event_id`), `idx_rsvps_rsvp_token` (on `rsvp_token`).
|
||||
|
||||
### Event (existing — no schema changes)
|
||||
|
||||
The `organizer_token` column on the `events` table is used for authorization. The endpoint verifies that the provided organizer token matches the event's stored token.
|
||||
|
||||
| Field | Type | Notes |
|
||||
|-------|------|-------|
|
||||
| organizer_token | UUID | UNIQUE, NOT NULL — used for attendee list authorization |
|
||||
|
||||
## Query Patterns
|
||||
|
||||
### Get attendees by event token
|
||||
|
||||
```sql
|
||||
SELECT r.name
|
||||
FROM rsvps r
|
||||
JOIN events e ON r.event_id = e.id
|
||||
WHERE e.event_token = :eventToken
|
||||
ORDER BY r.id ASC;
|
||||
```
|
||||
|
||||
**Performance**: Uses existing `idx_rsvps_event_id` index. Expected result set is small (spec assumes small-to-medium events, no pagination needed).
|
||||
|
||||
### Organizer token verification
|
||||
|
||||
```sql
|
||||
SELECT e.organizer_token
|
||||
FROM events e
|
||||
WHERE e.event_token = :eventToken;
|
||||
```
|
||||
|
||||
Already implemented in `EventService.getByEventToken()` — the event entity includes the organizer token. The use case compares the provided token against the stored one.
|
||||
|
||||
## Domain Model Changes
|
||||
|
||||
### New Outbound Port Method
|
||||
|
||||
```java
|
||||
// RsvpRepository (existing interface)
|
||||
List<Rsvp> findByEventId(Long eventId); // NEW
|
||||
```
|
||||
|
||||
### New Inbound Port
|
||||
|
||||
```java
|
||||
// GetAttendeesUseCase (new interface)
|
||||
List<String> getAttendeeNames(EventToken eventToken, OrganizerToken organizerToken);
|
||||
```
|
||||
|
||||
Returns a list of attendee display names. Throws `EventNotFoundException` if event token is invalid. Throws `AccessDeniedException` (or similar) if organizer token does not match.
|
||||
|
||||
## No Migration Required
|
||||
|
||||
All required data structures already exist from changeset `003-create-rsvps-table.xml`. This feature only adds read access to existing data.
|
||||
Reference in New Issue
Block a user