Skip to content

Commit aee8821

Browse files
committed
more stuff
1 parent aecb83e commit aee8821

7 files changed

Lines changed: 458 additions & 23 deletions

File tree

prisma/schema.prisma

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ enum Role {
4545
VIDEO
4646
INSTRUCTOR
4747
PM
48+
THREE_D_MODELING
49+
ANIMATION
4850
}
4951

5052
enum Level {
@@ -110,6 +112,7 @@ model Member {
110112
major String? @db.VarChar(255)
111113
minor String? @db.VarChar(255)
112114
linkedinUrl String? @map("linkedin_url") @db.Text
115+
githubId String? @map("github_id") @db.VarChar(255)
113116
notionPageId String? @unique @map("notion_page_id") @db.VarChar(255)
114117
currentRole String? @map("current_role") @db.VarChar(255)
115118
roles String[] @default([])
@@ -212,6 +215,8 @@ model Project {
212215
gcalendarUrl String? @map("gcalendar_url") @db.Text
213216
214217
repos Repo[]
218+
slackChannelId String? @map("slack_channel_id") @db.VarChar(255)
219+
githubTeamSlug String? @map("github_team_slug") @db.VarChar(255)
215220
notionPageId String? @unique @map("notion_page_id") @db.VarChar(255)
216221
memberTermRoles MemberTermRole[]
217222
bidsPref1 Bid[] @relation("BidPref1")

prisma/sync-from-notion.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ async function syncMembers(
431431
const classYear = props.year?.multi_select?.[0]?.name ?? null;
432432
const { major, minor } = extractMajorMinor(props);
433433
const linkedinUrl = props.linkedin?.url || props.linkedin?.rich_text?.[0]?.plain_text || null;
434+
const githubId = props.github?.url?.replace(/^https?:\/\/(www\.)?github\.com\//, "").replace(/\/$/, "") || props.github?.rich_text?.[0]?.plain_text || null;
434435

435436
const memberTermNames = extractMemberTermNames(props);
436437
const termIds = memberTermNames.map(t => termIdByName.get(t)).filter((id): id is string => !!id);
@@ -469,8 +470,8 @@ async function syncMembers(
469470
try {
470471
const member = await prisma.member.upsert({
471472
where: { notionPageId },
472-
update: { fullName, imageUrl, daliEmail, classYear, major, minor, linkedinUrl, isAlum, isActive: !isAlum, currentRole, roles, coreRoleNames, termsInDali: { set: termIds.map(id => ({ id })) } },
473-
create: { fullName, imageUrl, daliEmail, joinedTermId, notionPageId, classYear, major, minor, linkedinUrl, isAlum, isActive: !isAlum, currentRole, roles, coreRoleNames, termsInDali: { connect: termIds.map(id => ({ id })) } },
473+
update: { fullName, imageUrl, daliEmail, classYear, major, minor, linkedinUrl, githubId, isAlum, isActive: !isAlum, currentRole, roles, coreRoleNames, termsInDali: { set: termIds.map(id => ({ id })) } },
474+
create: { fullName, imageUrl, daliEmail, joinedTermId, notionPageId, classYear, major, minor, linkedinUrl, githubId, isAlum, isActive: !isAlum, currentRole, roles, coreRoleNames, termsInDali: { connect: termIds.map(id => ({ id })) } },
474475
});
475476

476477
// Sync HiredRoles

src/routes/applications.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,31 @@ import { prisma } from "../../lib/prisma.js";
33

44
const router = Router();
55

6-
// GET /applications?userId=
6+
// GET /applications?userId=&term=&status=
77
router.get("/", async (req, res) => {
88
try {
9-
const { userId } = req.query;
9+
const { userId, term, status } = req.query;
10+
11+
// Admin listing: filter by term (and optionally status), no userId required
1012
if (!userId || typeof userId !== "string") {
11-
return res.status(400).json({ error: "userId query param required" });
13+
const where: any = {};
14+
if (term && typeof term === "string") {
15+
where.term = { name: term };
16+
}
17+
if (status && typeof status === "string") {
18+
where.status = status;
19+
}
20+
21+
const applications = await prisma.application.findMany({
22+
where,
23+
include: {
24+
term: true,
25+
user: { select: { id: true, firstName: true, lastName: true, dartmouthEmail: true } },
26+
},
27+
orderBy: { submittedAt: "desc" },
28+
});
29+
30+
return res.json(applications);
1231
}
1332

1433
const applications = await prisma.application.findMany({

src/routes/auth.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,19 @@ router.post("/google/member", async (req: Request, res: Response) => {
112112
include: { member: true },
113113
});
114114

115+
// Auto-link Member record if not yet linked
116+
if (!user.member) {
117+
await prisma.member.updateMany({
118+
where: { daliEmail: email, userId: null },
119+
data: { userId: user.id },
120+
});
121+
}
122+
123+
const member = user.member ?? await prisma.member.findUnique({ where: { daliEmail: email }, include: { user: true } });
124+
125+
// dartmouthLinked = the member's linked User has a @dartmouth.edu email (not @dali)
126+
const dartmouthLinked = !!(member as any)?.user?.dartmouthEmail?.endsWith("@dartmouth.edu");
127+
115128
const accessToken = await issueTokens(res, user.id, "USER");
116129

117130
return res.json({
@@ -122,7 +135,8 @@ router.post("/google/member", async (req: Request, res: Response) => {
122135
firstName: user.firstName,
123136
lastName: user.lastName,
124137
picture: user.picture,
125-
isMember: !!user.member,
138+
isMember: !!member,
139+
dartmouthLinked,
126140
},
127141
});
128142
} catch (err: any) {
@@ -277,8 +291,9 @@ router.post("/refresh", async (req: Request, res: Response) => {
277291
});
278292

279293
// ── POST /auth/link-member ─────────────────────────────────────────────────
280-
// Links the authenticated User to their Member record by matching
281-
// user.dartmouthEmail === member.daliEmail. Bearer JWT required.
294+
// Called by a logged-in DALI member (@dali.dartmouth.edu). They provide their
295+
// @dartmouth.edu email; we find that User and set Member.userId = dartmouth_user.id
296+
// so that logging in with the Dartmouth account also shows isMember=true.
282297

283298
router.post("/link-member", async (req: Request, res: Response) => {
284299
try {
@@ -298,24 +313,35 @@ router.post("/link-member", async (req: Request, res: Response) => {
298313
return res.status(403).json({ error: "Only USER accounts can link a DALI profile" });
299314
}
300315

301-
const user = await prisma.user.findUnique({
316+
// Caller must be a DALI member user (has a Member record)
317+
const callerUser = await prisma.user.findUnique({
302318
where: { id: payload.id },
303319
include: { member: true },
304320
});
305321

306-
if (!user) return res.status(404).json({ error: "User not found" });
307-
if (user.member) return res.status(409).json({ error: "Account is already linked to a DALI profile" });
322+
if (!callerUser) return res.status(404).json({ error: "User not found" });
308323

309-
const member = await prisma.member.findUnique({
310-
where: { daliEmail: user.dartmouthEmail },
324+
const member = callerUser.member;
325+
if (!member) return res.status(404).json({ error: "No DALI profile found for your account" });
326+
327+
// The Dartmouth email they want to link to
328+
const { dartmouthEmail } = req.body;
329+
if (!dartmouthEmail || !dartmouthEmail.endsWith("@dartmouth.edu")) {
330+
return res.status(400).json({ error: "A valid @dartmouth.edu email is required" });
331+
}
332+
333+
const dartmouthUser = await prisma.user.findUnique({
334+
where: { dartmouthEmail },
335+
include: { member: true },
311336
});
312337

313-
if (!member) return res.status(404).json({ error: "No DALI profile found for your email address" });
314-
if (member.userId !== null) return res.status(409).json({ error: "This DALI profile is already linked to another account" });
338+
if (!dartmouthUser) return res.status(404).json({ error: "No account found for that Dartmouth email. Make sure you have signed in with it at least once." });
339+
if (dartmouthUser.member) return res.status(409).json({ error: "That Dartmouth account is already linked to a DALI profile" });
315340

341+
// Point Member.userId to the Dartmouth User so their login shows isMember=true
316342
await prisma.member.update({
317343
where: { id: member.id },
318-
data: { userId: user.id },
344+
data: { userId: dartmouthUser.id },
319345
});
320346

321347
return res.json({ ok: true, memberId: member.id });

0 commit comments

Comments
 (0)