mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 22:54:45 -05:00
chore(deps): Update dependencies and enhance API error handling
- Added '@vercel/analytics' to package.json for improved analytics tracking. - Updated 'next' version from 15.0.2 to 15.0.3 to incorporate the latest features and fixes. - Refactored API routes for invitations and studies to improve error handling and response structure. - Enhanced permission checks in the invitations and studies API to ensure proper access control. - Removed the participants dashboard page as part of a restructuring effort. - Updated the database schema to include environment settings for users and studies. - Improved the dashboard components to handle loading states and display statistics more effectively.
This commit is contained in:
75
src/lib/permissions-server.ts
Normal file
75
src/lib/permissions-server.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { eq, and, or } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import { userRolesTable, rolePermissionsTable, permissionsTable } from "~/db/schema";
|
||||
import { ApiError } from "./api-utils";
|
||||
import { auth } from "@clerk/nextjs/server";
|
||||
import { PERMISSIONS } from "./permissions-client";
|
||||
|
||||
export { PERMISSIONS };
|
||||
|
||||
export async function hasStudyAccess(userId: string, studyId: number): Promise<boolean> {
|
||||
const userRoles = await db
|
||||
.select()
|
||||
.from(userRolesTable)
|
||||
.where(
|
||||
and(
|
||||
eq(userRolesTable.userId, userId),
|
||||
eq(userRolesTable.studyId, studyId)
|
||||
)
|
||||
);
|
||||
|
||||
return userRoles.length > 0;
|
||||
}
|
||||
|
||||
export async function hasPermission(
|
||||
userId: string,
|
||||
permissionCode: string,
|
||||
studyId: number
|
||||
): Promise<boolean> {
|
||||
const permissions = await db
|
||||
.selectDistinct({
|
||||
permissionCode: permissionsTable.code,
|
||||
})
|
||||
.from(userRolesTable)
|
||||
.innerJoin(rolePermissionsTable, eq(rolePermissionsTable.roleId, userRolesTable.roleId))
|
||||
.innerJoin(permissionsTable, eq(permissionsTable.id, rolePermissionsTable.permissionId))
|
||||
.where(
|
||||
and(
|
||||
eq(userRolesTable.userId, userId),
|
||||
eq(userRolesTable.studyId, studyId)
|
||||
)
|
||||
);
|
||||
|
||||
return permissions.some(p => p.permissionCode === permissionCode);
|
||||
}
|
||||
|
||||
export type PermissionCheck = {
|
||||
studyId: number;
|
||||
permission?: string;
|
||||
requireStudyAccess?: boolean;
|
||||
};
|
||||
|
||||
export async function checkPermissions(check: PermissionCheck) {
|
||||
const { userId } = await auth();
|
||||
if (!userId) {
|
||||
return { error: ApiError.Unauthorized() };
|
||||
}
|
||||
|
||||
const { studyId, permission, requireStudyAccess = true } = check;
|
||||
|
||||
if (requireStudyAccess) {
|
||||
const hasAccess = await hasStudyAccess(userId, studyId);
|
||||
if (!hasAccess) {
|
||||
return { error: ApiError.NotFound("Study") };
|
||||
}
|
||||
}
|
||||
|
||||
if (permission) {
|
||||
const hasRequiredPermission = await hasPermission(userId, permission, studyId);
|
||||
if (!hasRequiredPermission) {
|
||||
return { error: ApiError.Forbidden() };
|
||||
}
|
||||
}
|
||||
|
||||
return { userId };
|
||||
}
|
||||
Reference in New Issue
Block a user