import React, { useRef } from 'react'; import { useSelector } from 'react-redux'; import { useDarkTheme } from '../hooks'; import { selectToken } from '../preferences/preferenceSlice'; interface ConnectorAuthProps { provider: string; onSuccess: (data: { session_token: string; user_email: string }) => void; onError: (error: string) => void; label?: string; isConnected?: boolean; userEmail?: string; onDisconnect?: () => void; errorMessage?: string; } const ConnectorAuth: React.FC = ({ provider, onSuccess, onError, label, isConnected = false, userEmail = '', onDisconnect, errorMessage, }) => { const token = useSelector(selectToken); const [isDarkTheme] = useDarkTheme(); const completedRef = useRef(false); const intervalRef = useRef(null); const cleanup = () => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } window.removeEventListener('message', handleAuthMessage as any); }; const handleAuthMessage = (event: MessageEvent) => { const successGeneric = event.data?.type === 'connector_auth_success'; const successProvider = event.data?.type === `${provider}_auth_success`; const errorProvider = event.data?.type === `${provider}_auth_error`; if (successGeneric || successProvider) { completedRef.current = true; cleanup(); onSuccess({ session_token: event.data.session_token, user_email: event.data.user_email || 'Connected User', }); } else if (errorProvider) { completedRef.current = true; cleanup(); onError(event.data.error || 'Authentication failed'); } }; const handleAuth = async () => { try { completedRef.current = false; cleanup(); const apiHost = import.meta.env.VITE_API_HOST; const authResponse = await fetch( `${apiHost}/api/connectors/auth?provider=${provider}`, { headers: { Authorization: `Bearer ${token}` }, }, ); if (!authResponse.ok) { throw new Error( `Failed to get authorization URL: ${authResponse.status}`, ); } const authData = await authResponse.json(); if (!authData.success || !authData.authorization_url) { throw new Error(authData.error || 'Failed to get authorization URL'); } const authWindow = window.open( authData.authorization_url, `${provider}-auth`, 'width=500,height=600,scrollbars=yes,resizable=yes', ); if (!authWindow) { throw new Error( 'Failed to open authentication window. Please allow popups.', ); } window.addEventListener('message', handleAuthMessage as any); const checkClosed = window.setInterval(() => { if (authWindow.closed) { clearInterval(checkClosed); window.removeEventListener('message', handleAuthMessage as any); if (!completedRef.current) { onError('Authentication was cancelled'); } } }, 1000); intervalRef.current = checkClosed; } catch (error) { onError(error instanceof Error ? error.message : 'Authentication failed'); } }; return ( <> {errorMessage && (
{errorMessage}
)} {isConnected ? (
Connected as {userEmail}
{onDisconnect && ( )}
) : ( )} ); }; export default ConnectorAuth;