mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 22:54:45 -05:00
Add roles system
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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<Date | null>`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 });
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -75,19 +75,21 @@ export function Trials() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Card className="card-level-1">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-2xl font-bold">Trials</CardTitle>
|
||||
<CreateTrialDialog onCreateTrial={createTrial} />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{trials.length > 0 ? (
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
<div className="grid sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{trials.map(trial => (
|
||||
<Card key={trial.id} className="bg-gray-100 p-3 flex items-center justify-between">
|
||||
<Card key={trial.id} className="card-level-2 p-3 flex items-center justify-between">
|
||||
<div>
|
||||
<h3 className="font-semibold">{trial.title}</h3>
|
||||
<p className="text-sm text-gray-500">Participants: {trial.participantIds.join(', ')}</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
Participants: {trial.participantIds ? trial.participantIds.join(', ') : 'None'}
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
|
||||
20
src/lib/permissions.ts
Normal file
20
src/lib/permissions.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { auth } from "@clerk/nextjs/server";
|
||||
import { Participant } from "../types/Participant";
|
||||
|
||||
export const isUserAuthorized = (userId: string | null): boolean => {
|
||||
// Implement your logic to determine if the user is authorized to see participant names
|
||||
// For example, you might check if the user is an admin or has a specific role
|
||||
// return userId !== null; // Placeholder logic, replace with your actual authorization logic
|
||||
return false;
|
||||
};
|
||||
|
||||
export const anonymizeParticipants = (participants: Participant[], userId: string | null): Participant[] => {
|
||||
if (isUserAuthorized(userId)) {
|
||||
return participants; // Return original participants if authorized
|
||||
}
|
||||
|
||||
return participants.map(participant => ({
|
||||
...participant,
|
||||
name: `Participant ${participant.id}`, // Anonymize the name
|
||||
}));
|
||||
};
|
||||
@@ -17,7 +17,8 @@ if (env.NODE_ENV !== "production") globalForDb.conn = conn;
|
||||
|
||||
export const db = drizzle(conn, { schema });
|
||||
|
||||
import { initializeContentTypes } from "./init";
|
||||
import { initializeContentTypes, initializeRoles } from "./init";
|
||||
|
||||
// Initialize content types
|
||||
initializeContentTypes().catch(console.error);
|
||||
initializeRoles().catch(console.error);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { db } from "./index";
|
||||
import { contentTypes } from "./schema";
|
||||
import { roles } from "./schema";
|
||||
|
||||
export async function initializeContentTypes() {
|
||||
const existingTypes = await db.select().from(contentTypes);
|
||||
@@ -11,5 +12,21 @@ export async function initializeContentTypes() {
|
||||
// Add other content types as needed
|
||||
]);
|
||||
console.log("Content types initialized");
|
||||
} else {
|
||||
console.log("Content types already initialized");
|
||||
}
|
||||
}
|
||||
|
||||
export async function initializeRoles() {
|
||||
const existingRoles = await db.select().from(roles);
|
||||
|
||||
if (existingRoles.length === 0) {
|
||||
await db.insert(roles).values([
|
||||
{ name: "Basic User" }, // Role ID 0
|
||||
{ name: "Admin" }, // Role ID 1
|
||||
]);
|
||||
console.log("Roles initialized");
|
||||
} else {
|
||||
console.log("Roles already initialized");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
serial,
|
||||
varchar,
|
||||
timestamp,
|
||||
integer
|
||||
integer,
|
||||
boolean
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { sql } from "drizzle-orm";
|
||||
|
||||
@@ -85,6 +86,7 @@ export const users = pgTable(
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
email: varchar("email", { length: 256 }).notNull().unique(),
|
||||
roleId: integer("role_id").references(() => roles.id).default(0), // Link to roles
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
.notNull(),
|
||||
@@ -110,3 +112,45 @@ export const trialParticipants = pgTable(
|
||||
participantId: integer("participant_id").references(() => participants.id).notNull(),
|
||||
}
|
||||
);
|
||||
|
||||
export const roles = pgTable(
|
||||
"role",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name", { length: 50 }).notNull().unique(),
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
.notNull(),
|
||||
}
|
||||
);
|
||||
|
||||
export const permissions = pgTable(
|
||||
"permission",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name", { length: 50 }).notNull().unique(),
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
.notNull(),
|
||||
}
|
||||
);
|
||||
|
||||
export const rolePermissions = pgTable(
|
||||
"role_permissions",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
roleId: integer("role_id").references(() => roles.id).notNull(),
|
||||
permissionId: integer("permission_id").references(() => permissions.id).notNull(),
|
||||
}
|
||||
);
|
||||
|
||||
export const permissionTypes = pgTable(
|
||||
"permission_type",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name", { length: 50 }).notNull().unique(),
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
.notNull(),
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user