Skip to content

Commit 460c9e8

Browse files
committed
fix membership
1 parent 4404830 commit 460c9e8

File tree

4 files changed

+36
-5
lines changed

4 files changed

+36
-5
lines changed

src/api/functions/membership.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ export async function checkPaidMembershipFromEntra(
6060
paidMemberGroup: string,
6161
): Promise<boolean> {
6262
try {
63-
return isUserInGroup(entraToken, `${netId}@illinois.edu`, paidMemberGroup);
63+
return await isUserInGroup(
64+
entraToken,
65+
`${netId}@illinois.edu`,
66+
paidMemberGroup,
67+
);
6468
} catch (e) {
6569
if (e instanceof EntraGroupError) {
6670
return false;

src/api/functions/validation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ export function validateEmail(email: string): boolean {
88

99
export function validateNetId(netId: string): boolean {
1010
const regex = /^[a-zA-Z]{2}[a-zA-Z\-]*(?:[2-9]|[1-9][0-9]{1,2})?$/;
11-
return netId.length <= 8 && regex.test(netId);
11+
return netId.length >= 3 && netId.length <= 8 && regex.test(netId);
1212
}

src/api/routes/membership.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { getRoleCredentials } from "api/functions/sts.js";
1212
import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
1313
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
1414

15+
const NONMEMBER_CACHE_SECONDS = 1800; // 30 minutes
16+
const MEMBER_CACHE_SECONDS = 43200; // 12 hours
17+
1518
const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
1619
const getAuthorizedClients = async () => {
1720
if (roleArns.Entra) {
@@ -67,12 +70,19 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
6770
message: `${netId} is not a valid Illinois NetID!`,
6871
});
6972
}
73+
if (fastify.nodeCache.get(`isMember_${netId}`) !== undefined) {
74+
return reply.header("X-ACM-Data-Source", "cache").send({
75+
netId,
76+
isPaidMember: fastify.nodeCache.get(`isMember_${netId}`),
77+
});
78+
}
7079
const isDynamoMember = await checkPaidMembershipFromTable(
7180
netId,
7281
fastify.dynamoClient,
7382
);
7483
// check Dynamo cache first
7584
if (isDynamoMember) {
85+
fastify.nodeCache.set(`isMember_${netId}`, true, MEMBER_CACHE_SECONDS);
7686
return reply
7787
.header("X-ACM-Data-Source", "dynamo")
7888
.send({ netId, isPaidMember: true });
@@ -89,12 +99,18 @@ const membershipPlugin: FastifyPluginAsync = async (fastify, _options) => {
8999
paidMemberGroup,
90100
);
91101
if (isAadMember) {
102+
fastify.nodeCache.set(`isMember_${netId}`, true, MEMBER_CACHE_SECONDS);
92103
reply
93104
.header("X-ACM-Data-Source", "aad")
94105
.send({ netId, isPaidMember: true });
95106
await setPaidMembershipInTable(netId, fastify.dynamoClient);
96107
return;
97108
}
109+
fastify.nodeCache.set(
110+
`isMember_${netId}`,
111+
false,
112+
NONMEMBER_CACHE_SECONDS,
113+
);
98114
return reply
99115
.header("X-ACM-Data-Source", "aad")
100116
.send({ netId, isPaidMember: false });

tests/live/membership.test.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ describe("Membership API basic checks", async () => {
1515
netId: "dsingh14",
1616
isPaidMember: true,
1717
});
18-
expect(response.headers.get("x-acm-data-source")).toBe("dynamo");
18+
19+
const wasCached = (value: string | null) => value && value !== "aad";
20+
21+
expect(wasCached(response.headers.get("x-acm-data-source"))).toBe(true);
1922
});
2023
test(
2124
"Test that getting non-members succeeds",
@@ -32,10 +35,9 @@ describe("Membership API basic checks", async () => {
3235
netId: "zzzz",
3336
isPaidMember: false,
3437
});
35-
expect(response.headers.get("x-acm-data-source")).toBe("aad");
3638
},
3739
);
38-
test("Test that invalid NetID is rejected", { timeout: 3000 }, async () => {
40+
test("Test that too long NetID is rejected", { timeout: 3000 }, async () => {
3941
const response = await fetch(
4042
`${baseEndpoint}/api/v1/membership/dsafdsfdsfsdafsfsdfasfsfsfds`,
4143
{
@@ -44,5 +46,14 @@ describe("Membership API basic checks", async () => {
4446
);
4547

4648
expect(response.status).toBe(400);
49+
expect(response.headers.get("x-acm-data-source")).toBeUndefined();
50+
});
51+
test("Test that too short NetID is rejected", { timeout: 3000 }, async () => {
52+
const response = await fetch(`${baseEndpoint}/api/v1/membership/ds`, {
53+
method: "GET",
54+
});
55+
56+
expect(response.status).toBe(400);
57+
expect(response.headers.get("x-acm-data-source")).toBeUndefined();
4758
});
4859
});

0 commit comments

Comments
 (0)