harden admin api authorization and add authz regression tests
This commit is contained in:
1 parent
272c9b36dd
commit
10b58245f5
28 files changed
+1336
-240
No files matched your search
@@ -1,13 +1,20 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { auth } from "@clerk/nextjs/server";
|
||||
import { getDatabase } from "@/lib/database";
|
||||
import log from "@/lib/logger";
|
||||
import { ensureUserSynced } from "@/lib/sync-user";
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const { userId: clerkUserId } = await auth();
|
||||
if (!clerkUserId) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await req.json();
|
||||
log.debug("Approve recommendation request body", { body });
|
||||
|
||||
const { recommendationId, status, approvedBy } = body;
|
||||
const { recommendationId, status } = body;
|
||||
|
||||
if (!recommendationId || !status) {
|
||||
log.error("Missing required fields", {
|
||||
@@ -22,12 +29,52 @@ export async function POST(req: Request) {
|
||||
}
|
||||
|
||||
const db = await getDatabase();
|
||||
const currentUser = await ensureUserSynced(clerkUserId, db);
|
||||
|
||||
if (!currentUser) {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
}
|
||||
|
||||
const canApproveRecommendations =
|
||||
currentUser.role === "superAdmin" ||
|
||||
currentUser.role === "admin" ||
|
||||
currentUser.role === "trainer";
|
||||
|
||||
if (!canApproveRecommendations) {
|
||||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
}
|
||||
|
||||
const existingRecommendation = (await db.getAllRecommendations()).find(
|
||||
(recommendation) => recommendation.id === recommendationId,
|
||||
);
|
||||
|
||||
if (!existingRecommendation) {
|
||||
return NextResponse.json(
|
||||
{ error: "Recommendation not found" },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
|
||||
if (currentUser.role !== "superAdmin") {
|
||||
const targetUser = await db.getUserById(existingRecommendation.userId);
|
||||
|
||||
if (
|
||||
!currentUser.gymId ||
|
||||
!targetUser ||
|
||||
targetUser.gymId !== currentUser.gymId
|
||||
) {
|
||||
return NextResponse.json(
|
||||
{ error: "Forbidden - Cannot access users from other gyms" },
|
||||
{ status: 403 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update recommendation status
|
||||
const updates: any = {
|
||||
status,
|
||||
approvedAt: status === "approved" ? new Date() : undefined,
|
||||
approvedBy: status === "approved" ? approvedBy : undefined,
|
||||
approvedBy: status === "approved" ? clerkUserId : undefined,
|
||||
};
|
||||
|
||||
// Remove undefined keys
|
||||
|
||||
Reference in new issue
Block a user