From 9d9aa52285012b35db5158f3ecdc23d0f486f30d Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Thu, 3 Oct 2024 17:50:07 -0400 Subject: [PATCH] Add roles system --- src/app/api/forms/route.ts | 10 ++++++- src/app/api/participants/route.ts | 9 +++++- src/app/api/users/route.ts | 8 +++++- src/components/trial/Trials.tsx | 10 ++++--- src/lib/permissions.ts | 20 ++++++++++++++ src/server/db/index.ts | 3 +- src/server/db/init.ts | 17 ++++++++++++ src/server/db/schema.ts | 46 ++++++++++++++++++++++++++++++- 8 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 src/lib/permissions.ts diff --git a/src/app/api/forms/route.ts b/src/app/api/forms/route.ts index 1f4d48e..33eb9e1 100644 --- a/src/app/api/forms/route.ts +++ b/src/app/api/forms/route.ts @@ -6,6 +6,8 @@ import { eq } from "drizzle-orm"; import { saveFile } from "~/lib/fileStorage"; import fs from 'fs/promises'; import { studies, participants } from "~/server/db/schema"; +import { anonymizeParticipants } from "~/lib/permissions"; // Import the anonymize function + // Function to generate a random string const generateRandomString = (length: number) => { const characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; @@ -37,7 +39,13 @@ export async function GET(request: Request) { .innerJoin(studies, eq(informedConsentForms.studyId, studies.id)) .innerJoin(participants, eq(informedConsentForms.participantId, participants.id)); - return NextResponse.json(forms); + // Anonymize participant names + const anonymizedForms = forms.map(form => ({ + ...form, + participantName: `Participant ${form.participantId}` // Anonymizing logic + })); + + return NextResponse.json(anonymizedForms); } export async function POST(request: Request) { diff --git a/src/app/api/participants/route.ts b/src/app/api/participants/route.ts index 6ad7aec..44315cd 100644 --- a/src/app/api/participants/route.ts +++ b/src/app/api/participants/route.ts @@ -2,8 +2,11 @@ import { db } from "~/server/db"; import { participants, trialParticipants, trials } from "~/server/db/schema"; import { NextResponse } from "next/server"; import { eq, sql } from "drizzle-orm"; +import { auth } from "@clerk/nextjs/server"; // Import auth to get userId +import { anonymizeParticipants } from "~/lib/permissions"; // Import the anonymize function export async function GET(request: Request) { + const { userId } = auth(); // Get the userId from auth try { const { searchParams } = new URL(request.url); const studyId = searchParams.get('studyId'); @@ -16,6 +19,7 @@ export async function GET(request: Request) { .select({ id: participants.id, name: participants.name, + studyId: participants.studyId, createdAt: participants.createdAt, latestTrialTimestamp: sql`MAX(${trials.createdAt})`.as('latestTrialTimestamp') }) @@ -26,7 +30,10 @@ export async function GET(request: Request) { .groupBy(participants.id) .orderBy(sql`COALESCE(MAX(${trials.createdAt}), ${participants.createdAt}) DESC`); - return NextResponse.json(participantsWithLatestTrial); + // Anonymize participant names + const anonymizedParticipants = anonymizeParticipants(participantsWithLatestTrial, userId); + + return NextResponse.json(anonymizedParticipants); } catch (error) { console.error('Error in GET /api/participants:', error); return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }); diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 2dd2050..af0b25f 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -1,7 +1,7 @@ import { db } from "~/server/db"; import { users } from "~/server/db/schema"; import { NextResponse } from "next/server"; - +import { eq } from "drizzle-orm"; export async function POST(request: Request) { try { const { email } = await request.json(); @@ -11,6 +11,12 @@ export async function POST(request: Request) { return NextResponse.json({ error: "Email is required" }, { status: 400 }); } + // Check if the user already exists + const existingUser = await db.select().from(users).where(eq(users.email, email)).limit(1); + if (existingUser) { + return NextResponse.json({ error: "User already exists" }, { status: 409 }); + } + // Insert the new user into the database const newUser = await db.insert(users).values({ email }).returning(); return NextResponse.json(newUser[0]); diff --git a/src/components/trial/Trials.tsx b/src/components/trial/Trials.tsx index f918237..712162b 100644 --- a/src/components/trial/Trials.tsx +++ b/src/components/trial/Trials.tsx @@ -75,19 +75,21 @@ export function Trials() { }; return ( - + Trials {trials.length > 0 ? ( -
+
{trials.map(trial => ( - +

{trial.title}

-

Participants: {trial.participantIds.join(', ')}

+

+ Participants: {trial.participantIds ? trial.participantIds.join(', ') : 'None'} +