import type { AccountProviderConnection, AccountProviderConnector } from '@shared/api/account' import { Check, Link2, ShieldCheck } from 'lucide-react' import { useState } from 'react' import { ProviderIcon } from '@/components/provider-icon' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle } from '@/components/ui/sheet' import { createProviderConnectionIntent, disconnectAccountProviderConnection, linkAccount } from '@/lib/api/account' import { tt } from '@/lib/i18n' import { AccountAccessNavigation } from './account-navigation' import { AccountEmptyState, AccountObjectSection, AccountPageHeader, AccountRow, AccountRows } from './account-page' import { AccountSurface } from './account-surface' import { DestructiveConfirmationDialog, useDestructiveConfirmation } from './primitives' import { accountQueryKeys, useAccountMutation, useAccountProviderConnections, useAccountProviderConnectors, } from './queries' import { formatDate, readRedirectUrl } from './utils' export function AccountConnectionsPage() { const connectorsQuery = useAccountProviderConnectors() const connectionsQuery = useAccountProviderConnections() const mutate = useAccountMutation() const [selected, setSelected] = useState(null) const [confirmation, setConfirmation] = useDestructiveConfirmation() const connections = connectionsQuery.data?.items ?? [] const connectors = connectorsQuery.data?.items ?? [] const connectedConnectorIds = new Set(connections.map((connection) => connection.connector.id)) const available = connectors.filter((connector) => !connectedConnectorIds.has(connector.id)) const loading = connectorsQuery.isLoading || connectionsQuery.isLoading const error = connectorsQuery.error ?? connectionsQuery.error async function authorizeProvider(connector: AccountProviderConnector) { const intent = await mutate(tt('Redirecting to {{providerName}}.', { providerName: connector.displayName }), () => createProviderConnectionIntent(connector.id), ) if (intent) window.location.assign(intent.authorizationUrl) } async function linkProviderSignIn(connector: AccountProviderConnector) { const result = await mutate(tt('Redirecting to {{providerName}}.', { providerName: connector.displayName }), () => linkAccount({ providerType: connector.providerType === 'generic_oauth' ? 'generic_oauth' : 'social', providerId: connector.providerId, callbackURL: `${window.location.origin}/connections`, errorCallbackURL: `${window.location.origin}/connections`, }), ) const redirectUrl = readRedirectUrl(result) if (redirectUrl) window.location.assign(redirectUrl) } async function connect(connector: AccountProviderConnector) { if (connector.capabilities.connection.method === 'provider_authorization') { await authorizeProvider(connector) return } if (connector.capabilities.connection.method !== 'sign_in') return await linkProviderSignIn(connector) } function disconnect(connection: AccountProviderConnection) { setConfirmation({ title: tt('Disconnect {{providerName}}?', { providerName: connection.connector.displayName }), description: tt( 'This removes the Provider from sign-in and revokes its active Agent Resource authorizations and token leases.', ), actionLabel: tt('Disconnect'), onConfirm: async () => { let failed = false await mutate( tt('{{providerName}} disconnected.', { providerName: connection.connector.displayName }), () => disconnectAccountProviderConnection(connection.id), { invalidate: [accountQueryKeys.providerConnections, accountQueryKeys.linkedAccounts], onError: () => { failed = true }, }, ) if (!failed) setSelected(null) }, }) } return ( {() => ( <> {loading ?

{tt('Loading Provider Connections…')}

: null} {error ? (

{error instanceof Error ? error.message : tt('Unable to load Provider Connections.')}

) : null} {!loading && !error ? (
{connections.map((connection) => ( setSelected(connection)} variant="outline"> {tt('Manage')} } key={connection.id} label={ } value={} /> ))} {!connections.length ? ( } title={tt('No Provider Connections')} /> ) : null} {available.map((connector) => ( void connect(connector)} variant="outline"> {tt('Connect')} ) : undefined } key={connector.id} label={} value={undefined} /> ))} {!available.length ? ( } title={tt('All Providers connected')} /> ) : null}
) : null} setSelected(null)} onDisconnect={disconnect} onLinkSignIn={(connection) => linkProviderSignIn(connection.connector)} onReauthorize={(connection) => authorizeProvider(connection.connector)} /> setConfirmation(null)} /> )}
) } function ProviderLabel({ connector, details = [] }: { connector: AccountProviderConnector; details?: string[] }) { return ( {connector.displayName} {details.map((detail) => ( {detail} ))} ) } function CapabilityBadges({ connection }: { connection: AccountProviderConnection }) { return ( {connection.capabilities.signIn.active ? {tt('Sign-in')} : null} {connection.capabilities.agentAccess.active ? ( {tt('Agent resource access')} ) : null} {!connection.capabilities.signIn.active && !connection.capabilities.agentAccess.active ? ( {tt('Needs attention')} ) : null} ) } function ConnectionSheet({ connection, onClose, onDisconnect, onLinkSignIn, onReauthorize, }: { connection: AccountProviderConnection | null onClose: () => void onDisconnect: (connection: AccountProviderConnection) => void onLinkSignIn: (connection: AccountProviderConnection) => Promise onReauthorize: (connection: AccountProviderConnection) => Promise }) { return ( !open && onClose()} open={connection !== null}> {connection?.connector.displayName ?? tt('Provider Connection')} {connection ? tt('{{displayName}} · Connected {{date}}', { displayName: connection.displayName, date: formatDate(connection.createdAt), }) : ''} {connection ? (
{connection.externalSubject}} /> {connection.capabilities.agentAccess.resourceNames.length ? ( {connection.capabilities.agentAccess.resourceNames.map((name) => ( ))} ) : ( } title={tt('No Agent resource access')} /> )}
) : null} {connection ? ( ) : null}
{connection?.capabilities.signIn.available && !connection.capabilities.signIn.active ? ( ) : null} {connection?.connector.capabilities.connection.method === 'provider_authorization' ? ( ) : null}
) } function capabilityDescription(connector: AccountProviderConnector) { if (connector.capabilities.signIn.available && connector.capabilities.agentAccess.available) { return tt('Sign-in and Agent resource access') } if (connector.capabilities.signIn.available) return tt('Sign-in only') if (connector.capabilities.agentAccess.available) return tt('Agent resource access only') return tt('No available capabilities') }