role based auth

implemented superadmin -> admin -> traniner
This commit is contained in:
dimitar committed 2026-03-18 06:06:01 +01:00
1 parent 16217f46ff
commit 624cdfc45c
16 files changed
+1105 -54

No files matched your search

@@ -1,11 +1,14 @@
import { NextRequest, NextResponse } from "next/server";
import { getDatabase } from "../../../../lib/database/index";
import { auth } from "@clerk/nextjs/server";
import log from "@/lib/logger";
import { fitnessProfileSchema } from "@/lib/validation/schemas";
import {
validateRequestBody,
validationErrorResponse,
} from "@/lib/validation/helpers";
import { getFitnessProfilesByGym } from "@/lib/gym-context";
import { ensureUserSynced } from "@/lib/sync-user";
export async function POST(request: NextRequest) {
try {
@@ -63,12 +66,47 @@ export async function POST(request: NextRequest) {
export async function GET(request: NextRequest) {
try {
const db = await getDatabase();
const { searchParams } = new URL(request.url);
const userId = searchParams.get("userId");
// First authenticate
const { userId: clerkUserId } = await auth();
if (!clerkUserId) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
if (userId) {
const profile = await db.getFitnessProfileByUserId(userId);
const db = await getDatabase();
const currentUser = await ensureUserSynced(clerkUserId, db);
if (!currentUser) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const { searchParams } = new URL(request.url);
const targetUserId = searchParams.get("userId");
// If accessing another user's profile, verify gym access
if (targetUserId && targetUserId !== clerkUserId) {
const isStaff =
currentUser.role === "admin" ||
currentUser.role === "superAdmin" ||
currentUser.role === "trainer";
if (!isStaff) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
// Staff need to verify target user is in same gym
if (currentUser.role !== "superAdmin") {
const targetUser = await db.getUserById(targetUserId);
if (!targetUser || targetUser.gymId !== currentUser.gymId) {
return NextResponse.json(
{ error: "Forbidden - Cannot access users from other gyms" },
{ status: 403 },
);
}
}
}
if (targetUserId) {
const profile = await db.getFitnessProfileByUserId(targetUserId);
if (!profile) {
return NextResponse.json(
{ error: "Profile not found" },
@@ -78,8 +116,28 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ profile });
}
const profiles = await db.getAllFitnessProfiles();
return NextResponse.json({ profiles });
// Staff get gym-scoped profiles
const isStaff =
currentUser.role === "admin" ||
currentUser.role === "superAdmin" ||
currentUser.role === "trainer";
if (isStaff) {
const targetGymId =
currentUser.role === "superAdmin"
? (searchParams.get("gymId") ?? undefined)
: (currentUser.gymId ?? undefined);
const profiles = targetGymId
? await getFitnessProfilesByGym(targetGymId)
: await db.getAllFitnessProfiles();
return NextResponse.json({ profiles });
}
// Regular users only get their own
const profile = await db.getFitnessProfileByUserId(clerkUserId);
return NextResponse.json({ profile: profile ? [profile] : [] });
} catch (error) {
log.error("Failed to get fitness profiles", error);
return NextResponse.json(