middleware fix wip

This commit is contained in:
2026-01-04 23:02:28 +01:00
parent 691e6e2c7e
commit cd3d9ae34f
8 changed files with 74 additions and 13 deletions

View File

@@ -12,11 +12,15 @@ interface AdminLayoutProps {
* Uses RouteGuard to enforce access control server-side.
*/
export default async function AdminLayout({ children }: AdminLayoutProps) {
console.log('[ADMIN LAYOUT] ========== ADMIN LAYOUT CALLED ==========');
const headerStore = await headers();
const pathname = headerStore.get('x-pathname') || '/';
console.log('[ADMIN LAYOUT] Pathname:', pathname);
const guard = createRouteGuard();
console.log('[ADMIN LAYOUT] About to call guard.enforce');
await guard.enforce({ pathname });
console.log('[ADMIN LAYOUT] guard.enforce completed successfully');
return (
<div className="min-h-screen bg-deep-graphite">

View File

@@ -47,6 +47,18 @@ export class EnhancedErrorBoundary extends Component<Props, State> {
}
static getDerivedStateFromError(error: Error): State {
// Don't catch Next.js navigation errors (redirect, notFound, etc.)
if (error && typeof error === 'object' && 'digest' in error) {
const digest = (error as any).digest;
if (typeof digest === 'string' && (
digest.startsWith('NEXT_REDIRECT') ||
digest.startsWith('NEXT_NOT_FOUND')
)) {
// Re-throw Next.js navigation errors so they can be handled properly
throw error;
}
}
return {
hasError: true,
error,
@@ -56,6 +68,18 @@ export class EnhancedErrorBoundary extends Component<Props, State> {
}
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
// Don't catch Next.js navigation errors (redirect, notFound, etc.)
if (error && typeof error === 'object' && 'digest' in error) {
const digest = (error as any).digest;
if (typeof digest === 'string' && (
digest.startsWith('NEXT_REDIRECT') ||
digest.startsWith('NEXT_NOT_FOUND')
)) {
// Re-throw Next.js navigation errors so they can be handled properly
throw error;
}
}
// Add to React error history
const reactErrors = (window as any).__GRIDPILOT_REACT_ERRORS__ || [];
reactErrors.push({

View File

@@ -227,8 +227,11 @@ export function handleAuthFlow(
return { shouldRedirect: false, shouldShowPage: true };
case AuthActionType.SHOW_PERMISSION_ERROR:
const errorUrl = router.getLoginRedirectUrl();
logger.info('[handleAuthFlow] Returning SHOW_PERMISSION_ERROR', { errorUrl });
return { shouldRedirect: true, redirectUrl: errorUrl };
// Redirect to user's home page instead of login (they're already logged in)
const homeUrl = session?.role === 'sponsor' ? routes.sponsor.dashboard :
session?.role === 'admin' ? routes.admin.root :
routes.protected.dashboard;
logger.info('[handleAuthFlow] Returning SHOW_PERMISSION_ERROR, redirecting to home', { homeUrl, userRole: session?.role });
return { shouldRedirect: true, redirectUrl: homeUrl };
}
}

View File

@@ -49,7 +49,9 @@ export class RouteAccessPolicy {
*/
requiredRoles(logicalPathname: string): string[] | null {
// Use catalog's role-based access method
return this.catalog.getRequiredRoles(logicalPathname);
const roles = this.catalog.getRequiredRoles(logicalPathname);
console.log(`[RouteAccessPolicy] requiredRoles for ${logicalPathname}:`, roles);
return roles;
}
/**

View File

@@ -4,6 +4,9 @@ import { RouteAccessPolicy } from './RouteAccessPolicy';
import { SessionGateway } from '../gateways/SessionGateway';
import { AuthRedirectBuilder } from './AuthRedirectBuilder';
import type { AuthSessionDTO } from '../types/generated/AuthSessionDTO';
import { ConsoleLogger } from '../infrastructure/logging/ConsoleLogger';
const logger = new ConsoleLogger();
export class RouteGuard {
constructor(
@@ -14,43 +17,55 @@ export class RouteGuard {
) {}
async enforce({ pathname }: { pathname: string }): Promise<void> {
logger.info('[RouteGuard] enforce called', { pathname });
// Step 1: Interpret the pathname
const { logicalPathname } = this.interpreter.interpret(pathname);
logger.info('[RouteGuard] logicalPathname', { logicalPathname });
// Step 2: Check if public non-auth page
if (this.policy.isPublic(logicalPathname) && !this.policy.isAuthPage(logicalPathname)) {
logger.info('[RouteGuard] Public non-auth page, allowing access');
return; // Allow access
}
// Step 3: Handle auth pages
if (this.policy.isAuthPage(logicalPathname)) {
logger.info('[RouteGuard] Auth page detected');
const session = await this.gateway.getSession();
if (session) {
// User is logged in, redirect away from auth page
const redirectPath = this.builder.awayFromAuthPage({ session, currentPathname: pathname });
logger.info('[RouteGuard] Redirecting away from auth page', { redirectPath });
redirect(redirectPath);
}
// No session, allow access to auth page
logger.info('[RouteGuard] No session, allowing access to auth page');
return;
}
// Step 4: Handle protected pages
const session = await this.gateway.getSession();
logger.info('[RouteGuard] Protected page, session', { hasSession: !!session, role: session?.user?.role, sessionData: JSON.stringify(session, null, 2) });
// No session, redirect to login
if (!session) {
const loginPath = this.builder.toLogin({ currentPathname: pathname });
logger.info('[RouteGuard] No session, redirecting to login', { loginPath });
redirect(loginPath);
}
// Check required roles
const reqRoles = this.policy.requiredRoles(logicalPathname);
logger.info('[RouteGuard] Checking required roles', { reqRoles, userRole: session.user?.role });
if (reqRoles && session.user?.role && !reqRoles.includes(session.user.role)) {
const loginPath = this.builder.toLogin({ currentPathname: pathname });
logger.info('[RouteGuard] Role mismatch, redirecting to login', { loginPath, reqRoles, userRole: session.user.role });
redirect(loginPath);
}
// All checks passed, allow access
logger.info('[RouteGuard] All checks passed, allowing access');
return;
}
}

View File

@@ -78,7 +78,8 @@ export class SessionGateway {
// Parse and return session data
const session = await response.json();
console.log(`[SESSION] Session parsed successfully`);
console.log(`[SESSION] Session parsed successfully:`, JSON.stringify(session, null, 2));
console.log(`[SESSION] Session user role:`, session?.user?.role);
return session as AuthSessionDTO;
} catch (error) {
console.log(`[SESSION] Error occurred:`, error);