import React, { useState, useEffect } from 'react'; import { Card, Button, Form, Input, Select, Space, Typography, Alert, Divider, Row, Col, Tag, Checkbox, message, Modal, Steps, } from 'antd'; import { PlayCircleOutlined, CheckCircleOutlined, ExclamationCircleOutlined, CopyOutlined, ReloadOutlined, LinkOutlined, } from '@ant-design/icons'; import { apiService, Application } from '../services/apiService'; const { Title, Text, Paragraph } = Typography; const { Option } = Select; const { TextArea } = Input; const { Step } = Steps; interface LoginTestResult { success: boolean; token?: string; redirectUrl?: string; userId?: string; appId?: string; expiresIn?: number; error?: string; timestamp: string; } interface CallbackTestResult { success: boolean; token?: string; verified?: boolean; permissions?: string[]; error?: string; timestamp: string; } const availablePermissions = [ 'app.read', 'app.write', 'app.delete', 'token.read', 'token.create', 'token.revoke', 'repo.read', 'repo.write', 'repo.admin', 'permission.read', 'permission.write', 'permission.grant', 'permission.revoke', ]; const TokenTester: React.FC = () => { const [applications, setApplications] = useState([]); const [loading, setLoading] = useState(false); const [testLoading, setTestLoading] = useState(false); const [callbackLoading, setCallbackLoading] = useState(false); const [loginResult, setLoginResult] = useState(null); const [callbackResult, setCallbackResult] = useState(null); const [currentStep, setCurrentStep] = useState(0); const [callbackModalVisible, setCallbackModalVisible] = useState(false); const [form] = Form.useForm(); const [callbackForm] = Form.useForm(); useEffect(() => { loadApplications(); }, []); const loadApplications = async () => { try { setLoading(true); const response = await apiService.getApplications(); setApplications(response.data); } catch (error) { console.error('Failed to load applications:', error); message.error('Failed to load applications'); } finally { setLoading(false); } }; const handleLoginTest = async (values: any) => { try { setTestLoading(true); setCurrentStep(1); const selectedApp = applications.find(app => app.app_id === values.app_id); const callbackUrl = `${window.location.origin}/token-tester/callback`; // Store test data in localStorage for the callback page const testData = { app_id: values.app_id, permissions: values.permissions || [], use_callback: values.use_callback, timestamp: new Date().toISOString(), }; localStorage.setItem('token_tester_data', JSON.stringify(testData)); console.log('Testing login flow with:', { app_id: values.app_id, permissions: values.permissions || [], redirect_uri: values.use_callback ? callbackUrl : undefined, }); const response = await apiService.login( values.app_id, values.permissions || [], values.use_callback ? callbackUrl : undefined ); console.log('Login response:', response); const result: LoginTestResult = { success: true, token: response.token, redirectUrl: response.redirect_url, userId: response.user_id, appId: values.app_id, expiresIn: response.expires_in, timestamp: new Date().toISOString(), }; setLoginResult(result); setCurrentStep(2); message.success('Login test completed successfully!'); // If we have a redirect URL, show the callback modal if (response.redirect_url && values.use_callback) { setCallbackModalVisible(true); // Pre-fill the callback form with the token from the redirect URL const urlParams = new URLSearchParams(response.redirect_url.split('?')[1]); const token = urlParams.get('token'); if (token) { callbackForm.setFieldsValue({ app_id: values.app_id, token: token, permissions: values.permissions || [], }); } } } catch (error: any) { console.error('Login test failed:', error); const result: LoginTestResult = { success: false, error: error.response?.data?.message || error.message || 'Login test failed', timestamp: new Date().toISOString(), }; setLoginResult(result); setCurrentStep(2); message.error('Login test failed'); } finally { setTestLoading(false); } }; const handleCallbackTest = async (values: any) => { try { setCallbackLoading(true); setCurrentStep(3); console.log('Testing callback with token verification:', values); // Verify the token received in the callback (type will be auto-detected) const verifyResponse = await apiService.verifyToken({ app_id: values.app_id, token: values.token, permissions: values.permissions || [], }); console.log('Token verification response:', verifyResponse); const result: CallbackTestResult = { success: verifyResponse.valid, token: values.token, verified: verifyResponse.valid, permissions: verifyResponse.permissions, error: verifyResponse.error, timestamp: new Date().toISOString(), }; setCallbackResult(result); setCurrentStep(4); if (verifyResponse.valid) { message.success('Callback test completed successfully!'); } else { message.warning('Callback test completed - token verification failed'); } } catch (error: any) { console.error('Callback test failed:', error); const result: CallbackTestResult = { success: false, error: error.response?.data?.message || error.message || 'Callback test failed', timestamp: new Date().toISOString(), }; setCallbackResult(result); setCurrentStep(4); message.error('Callback test failed'); } finally { setCallbackLoading(false); } }; const resetTest = () => { setCurrentStep(0); setLoginResult(null); setCallbackResult(null); setCallbackModalVisible(false); form.resetFields(); callbackForm.resetFields(); // Clear stored test data localStorage.removeItem('token_tester_data'); }; const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text); message.success('Copied to clipboard'); }; const openCallbackUrl = () => { if (loginResult?.redirectUrl) { window.open(loginResult.redirectUrl, '_blank'); } }; return (
Token Tester Test the /login flow and callback handling for user tokens
{/* Test Progress */} {/* Test Configuration */}
Use callback URL (test full flow) {availablePermissions.map(permission => ( {permission} ))}
{/* Login Test Results */} {loginResult && ( {loginResult.success ? ( ) : ( )} Login Test Results
} > {loginResult.success && (
{loginResult.token && (