'use client'; import { useState, useEffect } from 'react'; import Link from 'next/link'; import { Button } from '@/components/ui/button'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { RefreshCw, ArrowLeft, Loader2, CheckCircle2, AlertTriangle, Shield, Users, Smartphone, ScrollText, Layers, AppWindow, ChevronDown, ChevronUp, ShieldOff, ShieldAlert, ShieldX } from 'lucide-react'; interface DuoStatus { connected: boolean; syncing: boolean; lastSync: string | null; counts: { accounts: number; users: number; phones: number; authLogs: number; groups: number; integrations: number; bypass: number; disabled: number; }; } interface FlaggedUser { user_id: string; username: string; email: string | null; realname: string | null; status: string; is_enrolled: boolean; last_login: string | null; notes: string | null; account_name: string; } interface DuoAccount { id: number; account_id: string; name: string; api_hostname: string; user_count: number; integration_count: number; is_parent: boolean; synced_at: string | null; autotask_company_id: string | null; autotask_company_name: string | null; } export default function DuoSyncPage() { const [status, setStatus] = useState(null); const [accounts, setAccounts] = useState([]); const [loading, setLoading] = useState(true); const [syncing, setSyncing] = useState(false); const [bypassUsers, setBypassUsers] = useState([]); const [disabledUsers, setDisabledUsers] = useState([]); const [showBypass, setShowBypass] = useState(false); const [showDisabled, setShowDisabled] = useState(false); const fetchData = async () => { try { const [statusRes, accountsRes, flaggedRes] = await Promise.all([ fetch('/api/duo/status'), fetch('/api/duo/accounts'), fetch('/api/duo/users/flagged'), ]); if (statusRes.ok) setStatus(await statusRes.json()); if (accountsRes.ok) { const d = await accountsRes.json(); setAccounts(d.accounts ?? []); } if (flaggedRes.ok) { const d = await flaggedRes.json(); setBypassUsers(d.bypass ?? []); setDisabledUsers(d.disabled ?? []); } } catch (e) { console.error(e); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, []); const triggerSync = async () => { setSyncing(true); try { await fetch('/api/duo/sync', { method: 'POST' }); // Poll for completion const poll = setInterval(async () => { const r = await fetch('/api/duo/sync'); if (r.ok) { const d = await r.json(); if (!d.inProgress) { clearInterval(poll); setSyncing(false); fetchData(); } } }, 5000); } catch (e) { console.error(e); setSyncing(false); } }; const fmtDate = (d: string | null) => { if (!d) return 'Never'; return new Date(d).toLocaleString(); }; if (loading) { return (
); } const childAccounts = accounts.filter(a => !a.is_parent); const parentAccount = accounts.find(a => a.is_parent); return (
{/* Header */}
Duo

Duo Security

2FA / MFA — Accounts & Admin API sync

{/* Status cards */} {status && (
} label="Accounts" value={status.counts.accounts} /> } label="Users" value={status.counts.users} /> } label="Phones" value={status.counts.phones} /> } label="Auth Logs" value={status.counts.authLogs} /> } label="Groups" value={status.counts.groups} /> } label="Integrations" value={status.counts.integrations} />
)} {/* Last sync + warnings */}
Last sync: {fmtDate(status?.lastSync ?? null)} {bypassUsers.length > 0 && ( )} {disabledUsers.length > 0 && ( )}
{/* Bypass users — security concern */} {showBypass && bypassUsers.length > 0 && ( } borderColor="border-red-500/30" bgColor="bg-red-500/5" headerColor="text-red-700 dark:text-red-400" fmtDate={fmtDate} /> )} {/* Disabled users — informational */} {showDisabled && disabledUsers.length > 0 && ( } borderColor="border-border" bgColor="bg-muted/5" headerColor="text-muted-foreground" fmtDate={fmtDate} /> )} {/* Parent account */} {parentAccount && (

Parent Account

Name: {parentAccount.name}
Users: {parentAccount.user_count}
Integrations: {parentAccount.integration_count}
Synced: {fmtDate(parentAccount.synced_at)}
)} {/* Child accounts table */}

Child Accounts ({childAccounts.length})

Account name Users Integrations Matched company Last sync {childAccounts.map(a => ( {a.name} {a.user_count} {a.integration_count} {a.autotask_company_name ? ( {a.autotask_company_name} ) : ( )} {fmtDate(a.synced_at)} ))}
); } function StatCard({ icon, label, value }: { icon: React.ReactNode; label: string; value: number }) { return (
{icon} {label}
{value.toLocaleString()}
); } function FlaggedUsersTable({ title, description, users, icon, borderColor, bgColor, headerColor, fmtDate }: { title: string; description: string; users: FlaggedUser[]; icon: React.ReactNode; borderColor: string; bgColor: string; headerColor: string; fmtDate: (d: string | null) => string; }) { return (
{icon}

{title} ({users.length})

{description}

User Email Account Enrolled Last login Notes {users.map(u => (
{u.realname || u.username}
{u.realname &&
{u.username}
}
{u.email || '\u2014'} {u.account_name} {u.is_enrolled ? : No } {u.last_login ? fmtDate(u.last_login) : 'Never'} {u.notes || '\u2014'}
))}
); }