11import { FastifyPluginAsync } from "fastify" ;
22import rateLimiter from "api/plugins/rateLimiter.js" ;
33import { withRoles , withTags } from "api/components/index.js" ;
4- import { QueryCommand } from "@aws-sdk/client-dynamodb" ;
5- import { unmarshall } from "@aws-sdk/util-dynamodb" ;
6- import { getUserOrgRoles } from "api/functions/organizations.js" ;
4+ import { QueryCommand , PutItemCommand } from "@aws-sdk/client-dynamodb" ;
5+ import { unmarshall , marshall } from "@aws-sdk/util-dynamodb" ;
76import {
7+ DatabaseFetchError ,
88 UnauthenticatedError ,
99 UnauthorizedError ,
1010 ValidationError ,
@@ -14,14 +14,7 @@ import { verifyUiucAccessToken } from "api/functions/uin.js";
1414import { checkPaidMembership } from "api/functions/membership.js" ;
1515import { FastifyZodOpenApiTypeProvider } from "fastify-zod-openapi" ;
1616import { genericConfig } from "common/config.js" ;
17-
18- const rsvpItemSchema = z . object ( {
19- eventId : z . string ( ) ,
20- userId : z . string ( ) ,
21- isPaidMember : z . boolean ( ) ,
22- createdAt : z . string ( ) ,
23- } ) ;
24- const rsvpListSchema = z . array ( rsvpItemSchema ) ;
17+ import { AppRoles } from "common/roles.js" ;
2518
2619const rsvpRoutes : FastifyPluginAsync = async ( fastify , _options ) => {
2720 await fastify . register ( rateLimiter , {
@@ -38,6 +31,9 @@ const rsvpRoutes: FastifyPluginAsync = async (fastify, _options) => {
3831 eventId : z . string ( ) . min ( 1 ) . meta ( {
3932 description : "The previously-created event ID in the events API." ,
4033 } ) ,
34+ orgId : z . string ( ) . min ( 1 ) . meta ( {
35+ description : "The organization ID the event belongs to." ,
36+ } ) ,
4137 } ) ,
4238 headers : z . object ( {
4339 "x-uiuc-token" : z . jwt ( ) . min ( 1 ) . meta ( {
@@ -76,41 +72,53 @@ const rsvpRoutes: FastifyPluginAsync = async (fastify, _options) => {
7672 isPaidMember,
7773 createdAt : "" ,
7874 } ;
75+ const putCommand = new PutItemCommand ( {
76+ TableName : genericConfig . RSVPDynamoTableName ,
77+ Item : marshall ( entry ) ,
78+ } ) ;
79+ await fastify . dynamoClient . send ( putCommand ) ;
80+ return reply . status ( 201 ) . send ( entry ) ;
7981 } ,
8082 ) ;
8183 fastify . withTypeProvider < FastifyZodOpenApiTypeProvider > ( ) . get (
8284 "/:orgId/event/:eventId" ,
8385 {
84- schema : withTags ( [ "RSVP" ] , {
85- summary : "Get all RSVPs for an event." ,
86- params : z . object ( {
87- eventId : z . string ( ) . min ( 1 ) . meta ( {
88- description : "The previously-created event ID in the events API." ,
89- } ) ,
90- orgId : z . string ( ) . min ( 1 ) . meta ( {
91- description : "The organization ID the event belongs to." ,
92- } ) ,
93- } ) ,
94- headers : z . object ( {
95- "x-uiuc-token" : z . jwt ( ) . min ( 1 ) . meta ( {
96- description :
97- "An access token for the user in the UIUC Entra ID tenant." ,
86+ schema : withRoles (
87+ [ AppRoles . VIEW_RSVPS ] ,
88+ withTags ( [ "RSVP" ] , {
89+ summary : "Get all RSVPs for an event." ,
90+ params : z . object ( {
91+ eventId : z . string ( ) . min ( 1 ) . meta ( {
92+ description : "The previously-created event ID in the events API." ,
93+ } ) ,
94+ orgId : z . string ( ) . min ( 1 ) . meta ( {
95+ description : "The organization ID the event belongs to." ,
96+ } ) ,
9897 } ) ,
9998 } ) ,
100- } ) ,
99+ ) ,
100+ onRequest : fastify . authorizeFromSchema ,
101101 } ,
102102 async ( request , reply ) => {
103- const commnand = new QueryCommand ( {
104- TableName : genericConfig . EventsDynamoTableName ,
103+ const command = new QueryCommand ( {
104+ TableName : genericConfig . RSVPDynamoTableName ,
105105 IndexName : "EventIdIndex" ,
106106 KeyConditionExpression : "eventId = :eid" ,
107107 ExpressionAttributeValues : {
108108 ":eid" : { S : request . params . eventId } ,
109109 } ,
110110 } ) ;
111- const response = await fastify . dynamoClient . send ( commnand ) ;
112- const items = response . Items ?. map ( ( item ) => unmarshall ( item ) ) || [ ] ;
113- return reply . send ( items as z . infer < typeof rsvpListSchema > ) ;
111+ const response = await fastify . dynamoClient . send ( command ) ;
112+ if ( ! response || ! response . Items ) {
113+ throw new DatabaseFetchError ( {
114+ message : "Failed to get all member lists." ,
115+ } ) ;
116+ }
117+ const rsvps = response . Items . map ( ( x ) => unmarshall ( x ) ) ;
118+ const uniqueRsvps = [
119+ ...new Map ( rsvps . map ( ( item ) => [ item . userId , item ] ) ) . values ( )
120+ ] ;
121+ return reply . send ( uniqueRsvps ) ;
114122 } ,
115123 ) ;
116124} ;
0 commit comments