Skip to content

fix(events): enforce authorization for private event and attendee access #335

Open
Ridanshi wants to merge 1 commit into
Dev-Card:mainfrom
Ridanshi:fix/private-event-visibility
Open

fix(events): enforce authorization for private event and attendee access #335
Ridanshi wants to merge 1 commit into
Dev-Card:mainfrom
Ridanshi:fix/private-event-visibility

Conversation

@Ridanshi
Copy link
Copy Markdown
Contributor

Closes #300

Summary

Fixes a privacy and authorization flaw where private event data and attendee information were accessible to unauthenticated and unauthorized users.

Previously:

  • GET /api/events/:slug
  • GET /api/events/:slug/attendees

returned private event metadata and attendee profile information without enforcing:

  • authentication,
  • event visibility,
  • organizer/attendee authorization,
  • or membership validation.

This allowed unrestricted enumeration of private events and attendee identities.


Authorization Model Implemented

Introduced centralized authorization helpers:

getRequestUserId(request)
canAccessEvent(app, event, userId)

…v-Card#300)

Public events remain fully accessible without authentication.
Private events now require the caller to be the organizer or a
confirmed attendee; unauthenticated callers receive 401 and
authenticated non-members receive 403.

Changes:
- add getRequestUserId() soft-auth helper (returns null gracefully,
  never throws, used only on read endpoints)
- add canAccessEvent() returns 'allowed' | 'unauthenticated' |
  'forbidden' so callers can issue semantically correct 401 vs 403
- GET /api/events/:slug — visibility enforced after DB fetch;
  isPublic field intentionally excluded from response body
- GET /api/events/:slug/attendees — visibility enforced before
  returning any attendee data
- Routes registered with /api/events prefix in app.ts (removes the
  double-prefix issue from the prior implementation)
- 46 tests added covering public access, private 401/403, organizer
  access, attendee access, no-sensitive-field leakage, and unchanged
  pagination/sorting behaviour
}
};

type EventWithAttendees = Prisma.EventGetPayload<{
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than this can you use type.

* Returns null for unauthenticated requests or invalid/expired tokens.
* Never throws — safe to call on any request regardless of auth state.
*/
async function getRequestUserId(request: FastifyRequest): Promise<string | null> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make this util function please?

}>,
reply: FastifyReply,
) => {
let decoded: { id: string };
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You made a function why didn't used it here?

request: FastifyRequest<{ Params: { slug: string } }>,
reply: FastifyReply,
) => {
let decoded: { id: string };
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not here to?

@Harxhit
Copy link
Copy Markdown
Collaborator

Harxhit commented May 26, 2026

The POST /api/events/:slug/join handler fetches the event and creates an attendee record with no check on event.endDate. Users can successfully join an event that ended days or months ago, corrupting attendance data and attendance counts. Also could you please add lint and tests proofs in pr descriptions.

@Harxhit Harxhit added the gssoc:approved Required label for every approved PR. Gives the base +50 points and enables contribution tracking. label May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved Required label for every approved PR. Gives the base +50 points and enables contribution tracking.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Private events and attendee data are fully accessible without authentication

2 participants