import { useState, useEffect } from 'react' import { adminApi } from '../../api/client' import { useToast } from '../shared/Toast' import { Key, Trash2, User, Loader2, Shield } from 'lucide-react' import { useTranslation } from '../../i18n' interface AdminOAuthSession { id: number client_id: string client_name: string user_id: number username: string scopes: string[] access_token_expires_at: string refresh_token_expires_at: string created_at: string } interface AdminMcpToken { id: number name: string token_prefix: string created_at: string last_used_at: string | null user_id: number username: string } export default function AdminMcpTokensPanel() { const [sessions, setSessions] = useState([]) const [sessionsLoading, setSessionsLoading] = useState(true) const [tokens, setTokens] = useState([]) const [tokensLoading, setTokensLoading] = useState(true) const [revokeConfirmId, setRevokeConfirmId] = useState(null) const [deleteConfirmId, setDeleteConfirmId] = useState(null) const toast = useToast() const { t, locale } = useTranslation() useEffect(() => { adminApi.oauthSessions() .then(d => setSessions(d.sessions || [])) .catch(() => toast.error(t('admin.oauthSessions.loadError'))) .finally(() => setSessionsLoading(false)) adminApi.mcpTokens() .then(d => setTokens(d.tokens || [])) .catch(() => toast.error(t('admin.mcpTokens.loadError'))) .finally(() => setTokensLoading(false)) }, []) const handleRevoke = async (id: number) => { try { await adminApi.revokeOAuthSession(id) setSessions(prev => prev.filter(s => s.id !== id)) setRevokeConfirmId(null) toast.success(t('admin.oauthSessions.revokeSuccess')) } catch { toast.error(t('admin.oauthSessions.revokeError')) } } const handleDelete = async (id: number) => { try { await adminApi.deleteMcpToken(id) setTokens(prev => prev.filter(tk => tk.id !== id)) setDeleteConfirmId(null) toast.success(t('admin.mcpTokens.deleteSuccess')) } catch { toast.error(t('admin.mcpTokens.deleteError')) } } return (

{t('admin.mcpTokens.title')}

{t('admin.mcpTokens.subtitle')}

{/* OAuth Sessions */}

{t('admin.oauthSessions.sectionTitle')}

{sessionsLoading ? (
) : sessions.length === 0 ? (

{t('admin.oauthSessions.empty')}

) : ( <>
{t('admin.oauthSessions.clientName')} {t('admin.oauthSessions.owner')} {t('admin.oauthSessions.scopes')} {t('admin.oauthSessions.created')}
{sessions.map((session, i) => (

{session.client_name}

{session.client_id}

{session.username}
{session.scopes.join(', ')} {new Date(session.created_at).toLocaleDateString(locale)}
))} )}
{/* MCP Tokens */}

{t('admin.mcpTokens.sectionTitle')}

{tokensLoading ? (
) : tokens.length === 0 ? (

{t('admin.mcpTokens.empty')}

) : ( <>
{t('admin.mcpTokens.tokenName')} {t('admin.mcpTokens.owner')} {t('admin.mcpTokens.created')} {t('admin.mcpTokens.lastUsed')}
{tokens.map((token, i) => (

{token.name}

{token.token_prefix}...

{token.username}
{new Date(token.created_at).toLocaleDateString(locale)} {token.last_used_at ? new Date(token.last_used_at).toLocaleDateString(locale) : t('admin.mcpTokens.never')}
))} )}
{/* Revoke OAuth session modal */} {revokeConfirmId !== null && (
{ if (e.target === e.currentTarget) setRevokeConfirmId(null) }}>

{t('admin.oauthSessions.revokeTitle')}

{t('admin.oauthSessions.revokeMessage')}

)} {/* Delete MCP token modal */} {deleteConfirmId !== null && (
{ if (e.target === e.currentTarget) setDeleteConfirmId(null) }}>

{t('admin.mcpTokens.deleteTitle')}

{t('admin.mcpTokens.deleteMessage')}

)}
) }