/**
* PermissionGate Component - Page-level permission guard
* Protects entire pages or sections with permission checks
*/
'use client';
import { ReactNode } from 'react';
import { useRouter } from 'next/navigation';
import { usePermissions } from '@/lib/hooks/use-permissions';
import { AlertCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
export interface PermissionGateProps {
/**
* Permissions required - user must have ALL (AND logic)
* @example ["invoice:view"]
*/
required?: string[];
/**
* Permissions required - user must have ANY (OR logic)
* @example ["invoice:view", "invoice:*"]
*/
anyRequired?: string[];
/**
* Roles required - user must have ALL (AND logic)
* @example ["admin"]
*/
requiredRoles?: string[];
/**
* Roles required - user must have ANY (OR logic)
* @example ["admin", "manager"]
*/
anyRequiredRole?: string[];
/**
* Custom fallback component when permission check fails
*/
fallback?: ReactNode;
/**
* Show default access denied message
* @default true
*/
showAccessDenied?: boolean;
/**
* Redirect to this path when permission check fails
* @example "/dashboard"
*/
redirectTo?: string;
/**
* Children to render when permission check passes
*/
children: ReactNode;
}
/**
* Default access denied message
*/
function AccessDenied({ onGoBack }: { onGoBack: () => void }) {
return (
Access Denied
You don't have permission to access this page. Please contact your
administrator if you believe this is a mistake.
);
}
/**
* Page-level permission guard
*
* @example
* // Require single permission
*
*
*
*
* @example
* // Require any of multiple permissions
*
*
*
*
* @example
* // Require multiple permissions (all must be present)
*
*
*
*
* @example
* // With custom fallback
* }
* >
*
*
*
* @example
* // Redirect to another page
*
*
*
*
* @example
* // Role-based protection
*
*
*
*/
export function PermissionGate({
required,
anyRequired,
requiredRoles,
anyRequiredRole,
fallback,
showAccessDenied = true,
redirectTo,
children,
}: PermissionGateProps) {
const router = useRouter();
const {
hasAllPermissions,
hasAnyPermission,
hasAllRoles,
hasAnyRole,
isInitialized,
} = usePermissions();
// Wait for initialization
if (!isInitialized) {
return (
);
}
// Check permissions
let hasAccess = true;
if (required && !hasAllPermissions(required)) {
hasAccess = false;
}
if (anyRequired && !hasAnyPermission(anyRequired)) {
hasAccess = false;
}
if (requiredRoles && !hasAllRoles(requiredRoles)) {
hasAccess = false;
}
if (anyRequiredRole && !hasAnyRole(anyRequiredRole)) {
hasAccess = false;
}
// Access granted
if (hasAccess) {
return <>{children}>;
}
// Access denied - handle redirect
if (redirectTo) {
router.push(redirectTo);
return null;
}
// Access denied - show custom fallback
if (fallback) {
return <>{fallback}>;
}
// Access denied - show default message
if (showAccessDenied) {
return router.back()} />;
}
// Don't show anything
return null;
}