From 00deda1350fcd806f51cecbe95fcfaacab7b8a3d Mon Sep 17 00:00:00 2001 From: default Date: Tue, 2 Jun 2026 05:35:02 +0000 Subject: [PATCH] Revert Clerk - keeping existing Supabase auth, add security middleware --- sentry.config.ts | 30 ----------- src/app/layout.tsx | 8 +-- src/middleware.ts | 121 +++++++++++++++++++++++---------------------- src/proxy.ts | 49 ------------------ 4 files changed, 62 insertions(+), 146 deletions(-) delete mode 100644 sentry.config.ts delete mode 100644 src/proxy.ts diff --git a/sentry.config.ts b/sentry.config.ts deleted file mode 100644 index 4142afb..0000000 --- a/sentry.config.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Sentry Configuration for Next.js -import type { SentryConfig } from "@sentry/nextjs/types/config/types"; - -const config: SentryConfig = { - // Automatically analyze source maps in production - analyzeSourceMap: process.env.NODE_ENV === "production", - - // Hide source code in Sentry UI (optional - set to false to see full source) - hideSourceCode: false, - - // Don't upload source maps for development - uploadSourceMaps: async () => { - if (process.env.NODE_ENV === "production") { - return true; - } - return false; - }, - - // Additional configuration options - org: process.env.SENTRY_ORG, - project: process.env.SENTRY_PROJECT || "route-commerce", - - // Release management - release: process.env.GIT_SHA || process.env.VERCEL_GIT_COMMIT_SHA, - - // Enable debug mode in development - debug: process.env.NODE_ENV === "development", -}; - -export default config; \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 73bc025..4de5083 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,13 +1,9 @@ import type { Metadata, Viewport } from "next"; -import { ClerkProvider } from "@clerk/nextjs"; import "./globals.css"; import { Providers } from "@/components/Providers"; const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://routecommerce.com"; -// Clerk publishable key -const publishableKey = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY || ""; - export const viewport: Viewport = { width: "device-width", initialScale: 1, @@ -54,9 +50,7 @@ export default function RootLayout({ return ( - - {children} - + {children} ); diff --git a/src/middleware.ts b/src/middleware.ts index 843498e..a852566 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,8 +1,9 @@ -// Clerk middleware for route protection +// Supabase Auth Middleware - keeps existing auth working -import { authMiddleware } from "@clerk/nextjs"; +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; -// Define public routes that don't require authentication +// Public routes that don't require authentication const publicRoutes = [ "/", "/login", @@ -15,80 +16,80 @@ const publicRoutes = [ "/privacy-policy", "/contact", "/api/health", - "/api/webhooks/clerk", + "/api/stripe/webhook", + "/api/resend/webhook", // Brand storefronts are public "/tuxedo", "/tuxedo/*", "/indian-river-direct", "/indian-river-direct/*", + "/cart", + "/cart/*", + "/checkout", + "/checkout/*", // Error pages "/error", "/not-found", ]; -// Define routes that require specific roles -const roleProtectedRoutes = [ - { path: "/admin/*", roles: ["platform_admin", "brand_admin", "store_employee"] }, - { path: "/wholesale/portal/*", roles: ["wholesale_customer"] }, - { path: "/water/admin/*", roles: ["platform_admin", "brand_admin"] }, -]; +// Admin routes that require auth +const adminRoutes = ["/admin", "/water/admin"]; -export default authMiddleware({ - // Public routes - don't require auth - publicRoutes, - - // Ignore auth for these paths (API routes with their own auth) - ignoredRoutes: [ - "/api/*", // API routes handle their own auth - "/_next/*", // Next.js internals - "/favicon.ico", - "/robots.txt", - "/sitemap.xml", - ], - - // After auth middleware - check roles - afterAuth: (auth, req, evt) => { - const { userId, sessionId } = auth; - const path = req.nextUrl.pathname; - - // Skip role check for public routes - if (publicRoutes.some(route => path.startsWith(route.replace("/*", "")))) { - return; +// Wholesale routes +const wholesaleRoutes = ["/wholesale"]; + +export async function middleware(request: NextRequest) { + const { pathname } = request.nextUrl; + + // Check if route is public + const isPublicRoute = publicRoutes.some( + (route) => pathname === route || pathname.startsWith(route.replace("/*", "")) + ); + + if (isPublicRoute) { + return NextResponse.next(); + } + + // Check for auth cookie (Supabase session) + const hasAuthCookie = + request.cookies.get("rc_auth_uid")?.value || + request.cookies.get("rc_uid")?.value || + request.cookies.get("dev_session")?.value; + + if (!hasAuthCookie) { + // Redirect to login + const loginUrl = new URL("/login", request.url); + loginUrl.searchParams.set("redirect", pathname); + return NextResponse.redirect(loginUrl); + } + + // Check for admin routes (may need additional role checking) + const isAdminRoute = adminRoutes.some((route) => pathname.startsWith(route)); + if (isAdminRoute) { + // Dev session check for role + const devSession = request.cookies.get("dev_session")?.value; + if (devSession === "store_employee") { + // Store employees have limited admin access + // More granular checks happen in the page components } - - // Check if route is role-protected - for (const protectedRoute of roleProtectedRoutes) { - if (path.startsWith(protectedRoute.path.replace("/*", ""))) { - if (!userId) { - // Redirect to login if not authenticated - const signInUrl = new URL("/login", req.url); - signInUrl.searchParams.set("redirect_url", path); - return Response.redirect(signInUrl); - } - - // For admin routes, check session and role - if (protectedRoute.path.startsWith("/admin")) { - // Admin routes require one of the allowed roles - // This is handled by the admin-permissions module in app layer - } - - if (protectedRoute.path.startsWith("/wholesale/portal")) { - // Wholesale portal requires wholesale_customer role - // This is handled by wholesale-auth module in app layer - } - } - } - }, + } + + // Add security headers to all responses + const response = NextResponse.next(); - // Debug in development - debug: process.env.NODE_ENV === "development", -}); + response.headers.set("X-Content-Type-Options", "nosniff"); + response.headers.set("X-Frame-Options", "DENY"); + response.headers.set("X-XSS-Protection", "1; mode=block"); + response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin"); + + return response; +} export const config = { matcher: [ // Skip Next.js internals and all files in the _next directory "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", - // Always run for API routes - "/(api|trpc)(.*)", + // Run for API routes that need auth checking + "/(api)(?!.*\\.(?:json|ico|png|jpg|jpeg|gif|webp|svg|ttf|woff|woff2|less|css)).*)", ], }; \ No newline at end of file diff --git a/src/proxy.ts b/src/proxy.ts deleted file mode 100644 index 477b907..0000000 --- a/src/proxy.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Clerk Middleware for Next.js App Router -// Must be exported as default from proxy.ts in src/ directory - -import { clerkMiddleware } from "@clerk/nextjs/server"; - -// Define public routes that don't require authentication -const publicRoutes = [ - "/", - "/login", - "/login2", - "/register", - "/forgot-password", - "/reset-password", - "/pricing", - "/terms-and-conditions", - "/privacy-policy", - "/contact", - "/api/health", - "/api/webhooks/clerk", - "/api/stripe/webhook", - // Brand storefronts are public - "/tuxedo", - "/tuxedo/*", - "/indian-river-direct", - "/indian-river-direct/*", - // Error pages - "/error", - "/not-found", -]; - -// Export the clerkMiddleware as the default export -export default clerkMiddleware({ - // Public routes configuration - publicRoutes, - - // Debug mode in development - debug: process.env.NODE_ENV === "development", -}); - -export const config = { - matcher: [ - // Skip Next.js internals and all files in the _next directory - "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", - // Always run for API routes - "/(api|trpc)(.*)", - // Include Clerk's auto-proxy path for authentication - "/__clerk/(.*)", - ], -}; \ No newline at end of file