import { ArrowRight, Check, ExternalLink, Lightbulb, X } from 'lucide-react' import Link from 'next/link' import { useRouter } from 'next/router' import { useMemo } from 'react' import { Button, Button_Shadcn_, Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from 'ui' import { PageContainer } from 'ui-patterns/PageContainer' import { PageHeader, PageHeaderAside, PageHeaderDescription, PageHeaderIcon, PageHeaderMeta, PageHeaderSummary, PageHeaderTitle, } from 'ui-patterns/PageHeader' import { PageSection, PageSectionAside, PageSectionContent, PageSectionMeta, PageSectionSummary, PageSectionTitle, } from 'ui-patterns/PageSection' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import type { ProjectSecurityActionDetails, ProjectSecurityActionType, ProjectSecurityTable, } from './ProjectNeedsSecuring.types' import { buildSecurityPromptMarkdown, formatRlsDescription, getTableKey, getTablePoliciesHref, } from './ProjectNeedsSecuring.utils' import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import { AiAssistantDropdown } from '@/components/ui/AiAssistantDropdown' import AlertError from '@/components/ui/AlertError' import { createNavigationHandler } from '@/lib/navigation' import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state' import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state' const StatusCell = ({ enabled, label }: { enabled: boolean; label: string }) => (
{enabled ? (
) export const ProjectNeedsSecuringView = ({ projectRef, issueCount, tables, isLoading, error, onDismiss, onTrackAction, }: { projectRef: string issueCount: number tables: ProjectSecurityTable[] isLoading: boolean error?: { message: string } | null onDismiss: () => void onTrackAction: (type: ProjectSecurityActionType, details?: ProjectSecurityActionDetails) => void }) => { const router = useRouter() const aiSnap = useAiAssistantStateSnapshot() const { openSidebar } = useSidebarManagerSnapshot() const promptMarkdown = useMemo( () => buildSecurityPromptMarkdown(issueCount, tables), [issueCount, tables] ) const handleOpenAssistant = () => { onTrackAction('ask_assistant') openSidebar(SIDEBAR_KEYS.AI_ASSISTANT) aiSnap.newChat({ name: 'Review project security', initialInput: promptMarkdown, }) } return (
Your project needs securing {formatRlsDescription(issueCount)}
Review and fix promptMarkdown} onOpenAssistant={handleOpenAssistant} onCopyPrompt={() => onTrackAction('copy_prompt')} copyLabel="Copy Markdown" disabled={isLoading} /> {isLoading ? ( ) : error ? ( ) : ( Name Schema
Accessible via Data API
RLS
{tables.map((table) => { const policiesHref = getTablePoliciesHref( projectRef, table.schema, table.name ) const handleNavigation = createNavigationHandler(policiesHref, router) const trackViewPolicies = () => onTrackAction('view_policies', { schema: table.schema, tableName: table.name, }) return ( { trackViewPolicies() handleNavigation(event) }} onAuxClick={(event) => { if (event.button === 1) trackViewPolicies() handleNavigation(event) }} onKeyDown={(event) => { if (event.key === 'Enter' || event.key === ' ') trackViewPolicies() handleNavigation(event) }} tabIndex={0} > {table.name} {table.schema} ) })}
)}
) }