Skip to content

Commit 7e9658b

Browse files
authored
Add v2 membership route (#246)
Requires authentication for checking membership
1 parent e1e35dc commit 7e9658b

File tree

12 files changed

+451
-189
lines changed

12 files changed

+451
-189
lines changed

src/api/routes/membership.ts

Lines changed: 2 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,13 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
8686
"/",
8787
{
8888
schema: withTags(["Membership"], {
89-
querystring: z.object({
90-
list: z.string().min(1).optional().meta({
91-
description:
92-
"Membership list to check from (defaults to ACM Paid Member list).",
93-
}),
94-
}),
9589
headers: z.object({
9690
"x-uiuc-token": z.jwt().min(1).meta({
9791
description:
9892
"An access token for the user in the UIUC Entra ID tenant.",
9993
}),
10094
}),
101-
summary:
102-
"Authenticated check ACM @ UIUC paid membership (or partner organization membership) status.",
95+
summary: "Check self ACM @ UIUC paid membership.",
10396
response: {
10497
200: {
10598
description: "List membership status.",
@@ -110,7 +103,6 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
110103
givenName: z.string().min(1),
111104
surname: z.string().min(1),
112105
netId: illinoisNetId,
113-
list: z.optional(z.string().min(1)),
114106
isPaidMember: z.boolean(),
115107
})
116108
.meta({
@@ -143,7 +135,7 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
143135
message: "ID token could not be parsed.",
144136
});
145137
}
146-
const list = request.query.list || "acmpaid";
138+
const list = "acmpaid";
147139
const cacheKey = `membership:${netId}:${list}`;
148140
const result = await getKey<{ isMember: boolean }>({
149141
redisClient: fastify.redisClient,
@@ -234,131 +226,6 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
234226
.send({ givenName, surname, netId, isPaidMember: false });
235227
},
236228
);
237-
fastify.withTypeProvider<FastifyZodOpenApiTypeProvider>().get(
238-
"/:netId",
239-
{
240-
schema: withTags(["Membership"], {
241-
params: z.object({ netId: illinoisNetId }),
242-
querystring: z.object({
243-
list: z.string().min(1).optional().meta({
244-
description:
245-
"Membership list to check from (defaults to ACM Paid Member list).",
246-
}),
247-
}),
248-
summary:
249-
"Check ACM @ UIUC paid membership (or partner organization membership) status.",
250-
response: {
251-
200: {
252-
description: "List membership status.",
253-
content: {
254-
"application/json": {
255-
schema: z
256-
.object({
257-
netId: illinoisNetId,
258-
list: z.optional(z.string().min(1)),
259-
isPaidMember: z.boolean(),
260-
})
261-
.meta({
262-
example: {
263-
netId: "rjjones",
264-
isPaidMember: false,
265-
},
266-
}),
267-
},
268-
},
269-
},
270-
},
271-
}),
272-
},
273-
async (request, reply) => {
274-
const netId = request.params.netId.toLowerCase();
275-
const list = request.query.list || "acmpaid";
276-
const cacheKey = `membership:${netId}:${list}`;
277-
const result = await getKey<{ isMember: boolean }>({
278-
redisClient: fastify.redisClient,
279-
key: cacheKey,
280-
logger: request.log,
281-
});
282-
if (result) {
283-
return reply.header("X-ACM-Data-Source", "cache").send({
284-
netId,
285-
list: list === "acmpaid" ? undefined : list,
286-
isPaidMember: result.isMember,
287-
});
288-
}
289-
if (list !== "acmpaid") {
290-
const isMember = await checkExternalMembership(
291-
netId,
292-
list,
293-
fastify.dynamoClient,
294-
);
295-
await setKey({
296-
redisClient: fastify.redisClient,
297-
key: cacheKey,
298-
data: JSON.stringify({ isMember }),
299-
expiresIn: MEMBER_CACHE_SECONDS,
300-
logger: request.log,
301-
});
302-
return reply.header("X-ACM-Data-Source", "dynamo").send({
303-
netId,
304-
list,
305-
isPaidMember: isMember,
306-
});
307-
}
308-
const isDynamoMember = await checkPaidMembershipFromTable(
309-
netId,
310-
fastify.dynamoClient,
311-
);
312-
if (isDynamoMember) {
313-
await setKey({
314-
redisClient: fastify.redisClient,
315-
key: cacheKey,
316-
data: JSON.stringify({ isMember: true }),
317-
expiresIn: MEMBER_CACHE_SECONDS,
318-
logger: request.log,
319-
});
320-
return reply
321-
.header("X-ACM-Data-Source", "dynamo")
322-
.send({ netId, isPaidMember: true });
323-
}
324-
const entraIdToken = await getEntraIdToken({
325-
clients: await getAuthorizedClients(),
326-
clientId: fastify.environmentConfig.AadValidClientId,
327-
secretName: genericConfig.EntraSecretName,
328-
logger: request.log,
329-
});
330-
const paidMemberGroup = fastify.environmentConfig.PaidMemberGroupId;
331-
const isAadMember = await checkPaidMembershipFromEntra(
332-
netId,
333-
entraIdToken,
334-
paidMemberGroup,
335-
);
336-
if (isAadMember) {
337-
await setKey({
338-
redisClient: fastify.redisClient,
339-
key: cacheKey,
340-
data: JSON.stringify({ isMember: true }),
341-
expiresIn: MEMBER_CACHE_SECONDS,
342-
logger: request.log,
343-
});
344-
reply
345-
.header("X-ACM-Data-Source", "aad")
346-
.send({ netId, isPaidMember: true });
347-
await setPaidMembershipInTable(netId, fastify.dynamoClient);
348-
return;
349-
}
350-
await setKey({
351-
redisClient: fastify.redisClient,
352-
key: cacheKey,
353-
data: JSON.stringify({ isMember: false }),
354-
expiresIn: MEMBER_CACHE_SECONDS,
355-
logger: request.log,
356-
});
357-
return reply
358-
.header("X-ACM-Data-Source", "aad")
359-
.send({ netId, isPaidMember: false });
360-
},
361-
);
362229
fastify.withTypeProvider<FastifyZodOpenApiTypeProvider>().get(
363230
"/externalList",
364231
{

0 commit comments

Comments
 (0)