fix: backend admin page logic was broken (#9616)

<!-- Clearly explain the need for these changes: -->

We're building out admin utilities so we need to bring back the `/admin`
route with RBAC. This PR goes through re-enabling that to work with the
latest changes

### Changes 🏗️
- Adds back removed logic
- Refactors the role checks to fix minor bug for admin page and more
importantly clarify
- Updates routes to the latest 
<!-- Concisely describe all of the changes made in this pull request:
-->

### Checklist 📋

#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  <!-- Put your test plan here: -->
  - [x] Test with admin and authenticated user roles
  - [x] Test with logged out user role
- [x] For the above check the all the existing routes + new ones in the
`middleware.ts`
This commit is contained in:
Nicholas Tindle
2025-03-14 11:37:15 -05:00
committed by Zamil Majdy
parent 8757439192
commit 52b4351961
2 changed files with 41 additions and 31 deletions

View File

@@ -5,10 +5,10 @@ import { NextResponse, type NextRequest } from "next/server";
const PROTECTED_PAGES = [
"/monitor",
"/build",
"/marketplace/profile",
"/marketplace/settings",
"/marketplace/dashboard",
"/onboarding",
"/profile",
"/library",
"/monitoring",
];
const ADMIN_PAGES = ["/admin"];
@@ -62,34 +62,38 @@ export async function updateSession(request: NextRequest) {
// Get the user role
const userRole = user?.role;
const url = request.nextUrl.clone();
const pathname = request.nextUrl.pathname;
// AUTH REDIRECTS
// If not logged in and trying to access a protected page, redirect to login
if (
(!user &&
PROTECTED_PAGES.some((page) => {
const combinedPath = `${page}`;
// console.log("Checking pathname:", request.nextUrl.pathname, "against:", combinedPath);
return request.nextUrl.pathname.startsWith(combinedPath);
})) ||
ADMIN_PAGES.some((page) => {
const combinedPath = `${page}`;
// console.log("Checking pathname:", request.nextUrl.pathname, "against:", combinedPath);
return request.nextUrl.pathname.startsWith(combinedPath);
})
) {
// no user, potentially respond by redirecting the user to the login page
url.pathname = `/login`;
return NextResponse.redirect(url);
// 1. Check if user is not authenticated but trying to access protected content
if (!user) {
// Check if the user is trying to access either a protected page or an admin page
const isAttemptingProtectedPage = PROTECTED_PAGES.some((page) =>
request.nextUrl.pathname.startsWith(page),
);
const isAttemptingAdminPage = ADMIN_PAGES.some((page) =>
request.nextUrl.pathname.startsWith(page),
);
// If trying to access any protected content without being logged in,
// redirect to login page
if (isAttemptingProtectedPage || isAttemptingAdminPage) {
url.pathname = `/login`;
return NextResponse.redirect(url);
}
}
if (
user &&
userRole != "admin" &&
ADMIN_PAGES.some((page) => request.nextUrl.pathname.startsWith(`${page}`))
) {
// no user, potentially respond by redirecting the user to the login page
url.pathname = `/marketplace`;
return NextResponse.redirect(url);
// 2. Check if user is authenticated but lacks admin role when accessing admin pages
if (user && userRole !== "admin") {
const isAttemptingAdminPage = ADMIN_PAGES.some((page) =>
request.nextUrl.pathname.startsWith(page),
);
// If a non-admin user is trying to access admin pages,
// redirect to marketplace
if (isAttemptingAdminPage) {
url.pathname = `/marketplace`;
return NextResponse.redirect(url);
}
}
// IMPORTANT: You *must* return the supabaseResponse object as it is. If you're

View File

@@ -1,14 +1,20 @@
import React from "react";
import * as Sentry from "@sentry/nextjs";
import { redirect } from "next/navigation";
import getServerUser from "./supabase/getServerUser";
export async function withRoleAccess(allowedRoles: string[]) {
console.log("withRoleAccess called:", allowedRoles);
("use server");
"use server";
return await Sentry.withServerActionInstrumentation(
"withRoleAccess",
{},
async () => {
return async function <T extends React.ComponentType<any>>(Component: T) {
const { user, role, error } = await getServerUser();
if (error || !user || !role || !allowedRoles.includes(role)) {
redirect("/unauthorized");
}
return Component;
};
},