Revert Clerk - keeping existing Supabase auth, add security middleware
This commit is contained in:
@@ -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;
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
import type { Metadata, Viewport } from "next";
|
import type { Metadata, Viewport } from "next";
|
||||||
import { ClerkProvider } from "@clerk/nextjs";
|
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { Providers } from "@/components/Providers";
|
import { Providers } from "@/components/Providers";
|
||||||
|
|
||||||
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://routecommerce.com";
|
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 = {
|
export const viewport: Viewport = {
|
||||||
width: "device-width",
|
width: "device-width",
|
||||||
initialScale: 1,
|
initialScale: 1,
|
||||||
@@ -54,9 +50,7 @@ export default function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en" suppressHydrationWarning>
|
||||||
<body>
|
<body>
|
||||||
<ClerkProvider publishableKey={publishableKey}>
|
|
||||||
<Providers>{children}</Providers>
|
<Providers>{children}</Providers>
|
||||||
</ClerkProvider>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
+53
-52
@@ -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 = [
|
const publicRoutes = [
|
||||||
"/",
|
"/",
|
||||||
"/login",
|
"/login",
|
||||||
@@ -15,80 +16,80 @@ const publicRoutes = [
|
|||||||
"/privacy-policy",
|
"/privacy-policy",
|
||||||
"/contact",
|
"/contact",
|
||||||
"/api/health",
|
"/api/health",
|
||||||
"/api/webhooks/clerk",
|
"/api/stripe/webhook",
|
||||||
|
"/api/resend/webhook",
|
||||||
// Brand storefronts are public
|
// Brand storefronts are public
|
||||||
"/tuxedo",
|
"/tuxedo",
|
||||||
"/tuxedo/*",
|
"/tuxedo/*",
|
||||||
"/indian-river-direct",
|
"/indian-river-direct",
|
||||||
"/indian-river-direct/*",
|
"/indian-river-direct/*",
|
||||||
|
"/cart",
|
||||||
|
"/cart/*",
|
||||||
|
"/checkout",
|
||||||
|
"/checkout/*",
|
||||||
// Error pages
|
// Error pages
|
||||||
"/error",
|
"/error",
|
||||||
"/not-found",
|
"/not-found",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Define routes that require specific roles
|
// Admin routes that require auth
|
||||||
const roleProtectedRoutes = [
|
const adminRoutes = ["/admin", "/water/admin"];
|
||||||
{ path: "/admin/*", roles: ["platform_admin", "brand_admin", "store_employee"] },
|
|
||||||
{ path: "/wholesale/portal/*", roles: ["wholesale_customer"] },
|
|
||||||
{ path: "/water/admin/*", roles: ["platform_admin", "brand_admin"] },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default authMiddleware({
|
// Wholesale routes
|
||||||
// Public routes - don't require auth
|
const wholesaleRoutes = ["/wholesale"];
|
||||||
publicRoutes,
|
|
||||||
|
|
||||||
// Ignore auth for these paths (API routes with their own auth)
|
export async function middleware(request: NextRequest) {
|
||||||
ignoredRoutes: [
|
const { pathname } = request.nextUrl;
|
||||||
"/api/*", // API routes handle their own auth
|
|
||||||
"/_next/*", // Next.js internals
|
|
||||||
"/favicon.ico",
|
|
||||||
"/robots.txt",
|
|
||||||
"/sitemap.xml",
|
|
||||||
],
|
|
||||||
|
|
||||||
// After auth middleware - check roles
|
// Check if route is public
|
||||||
afterAuth: (auth, req, evt) => {
|
const isPublicRoute = publicRoutes.some(
|
||||||
const { userId, sessionId } = auth;
|
(route) => pathname === route || pathname.startsWith(route.replace("/*", ""))
|
||||||
const path = req.nextUrl.pathname;
|
);
|
||||||
|
|
||||||
// Skip role check for public routes
|
if (isPublicRoute) {
|
||||||
if (publicRoutes.some(route => path.startsWith(route.replace("/*", "")))) {
|
return NextResponse.next();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if route is role-protected
|
// Check for auth cookie (Supabase session)
|
||||||
for (const protectedRoute of roleProtectedRoutes) {
|
const hasAuthCookie =
|
||||||
if (path.startsWith(protectedRoute.path.replace("/*", ""))) {
|
request.cookies.get("rc_auth_uid")?.value ||
|
||||||
if (!userId) {
|
request.cookies.get("rc_uid")?.value ||
|
||||||
// Redirect to login if not authenticated
|
request.cookies.get("dev_session")?.value;
|
||||||
const signInUrl = new URL("/login", req.url);
|
|
||||||
signInUrl.searchParams.set("redirect_url", path);
|
if (!hasAuthCookie) {
|
||||||
return Response.redirect(signInUrl);
|
// Redirect to login
|
||||||
|
const loginUrl = new URL("/login", request.url);
|
||||||
|
loginUrl.searchParams.set("redirect", pathname);
|
||||||
|
return NextResponse.redirect(loginUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For admin routes, check session and role
|
// Check for admin routes (may need additional role checking)
|
||||||
if (protectedRoute.path.startsWith("/admin")) {
|
const isAdminRoute = adminRoutes.some((route) => pathname.startsWith(route));
|
||||||
// Admin routes require one of the allowed roles
|
if (isAdminRoute) {
|
||||||
// This is handled by the admin-permissions module in app layer
|
// 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protectedRoute.path.startsWith("/wholesale/portal")) {
|
// Add security headers to all responses
|
||||||
// Wholesale portal requires wholesale_customer role
|
const response = NextResponse.next();
|
||||||
// This is handled by wholesale-auth module in app layer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Debug in development
|
response.headers.set("X-Content-Type-Options", "nosniff");
|
||||||
debug: process.env.NODE_ENV === "development",
|
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 = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
// Skip Next.js internals and all files in the _next directory
|
// 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)).*)",
|
"/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
|
||||||
// Always run for API routes
|
// Run for API routes that need auth checking
|
||||||
"/(api|trpc)(.*)",
|
"/(api)(?!.*\\.(?:json|ico|png|jpg|jpeg|gif|webp|svg|ttf|woff|woff2|less|css)).*)",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -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/(.*)",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user