feature:show auth status on settings

This commit is contained in:
simos
2025-11-17 08:48:15 +01:00
parent abe8cd46a2
commit 33834d808b
3 changed files with 374 additions and 35 deletions

View File

@@ -81,10 +81,23 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'tools' }) {
const [newCursorDisallowedCommand, setNewCursorDisallowedCommand] = useState('');
const [cursorMcpServers, setCursorMcpServers] = useState([]);
// Login modal states
const [showLoginModal, setShowLoginModal] = useState(false);
const [loginProvider, setLoginProvider] = useState(''); // 'claude' or 'cursor'
const [loginProvider, setLoginProvider] = useState('');
const [selectedProject, setSelectedProject] = useState(null);
const [claudeAuthStatus, setClaudeAuthStatus] = useState({
authenticated: false,
email: null,
loading: true,
error: null
});
const [cursorAuthStatus, setCursorAuthStatus] = useState({
authenticated: false,
email: null,
loading: true,
error: null
});
// Common tool patterns for Claude
const commonTools = [
'Bash(git log:*)',
@@ -344,6 +357,9 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'tools' }) {
useEffect(() => {
if (isOpen) {
loadSettings();
// Check CLI authentication status
checkClaudeAuthStatus();
checkCursorAuthStatus();
// Set the active tab when the modal opens
setActiveTab(initialTab);
}
@@ -425,6 +441,81 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'tools' }) {
}
};
// CLI Authentication status checking functions
const checkClaudeAuthStatus = async () => {
try {
const token = localStorage.getItem('auth-token');
const response = await fetch('/api/cli/claude/status', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
setClaudeAuthStatus({
authenticated: data.authenticated,
email: data.email,
loading: false,
error: data.error || null
});
} else {
setClaudeAuthStatus({
authenticated: false,
email: null,
loading: false,
error: 'Failed to check authentication status'
});
}
} catch (error) {
console.error('Error checking Claude auth status:', error);
setClaudeAuthStatus({
authenticated: false,
email: null,
loading: false,
error: error.message
});
}
};
const checkCursorAuthStatus = async () => {
try {
const token = localStorage.getItem('auth-token');
const response = await fetch('/api/cli/cursor/status', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
setCursorAuthStatus({
authenticated: data.authenticated,
email: data.email,
loading: false,
error: data.error || null
});
} else {
setCursorAuthStatus({
authenticated: false,
email: null,
loading: false,
error: 'Failed to check authentication status'
});
}
} catch (error) {
console.error('Error checking Cursor auth status:', error);
setCursorAuthStatus({
authenticated: false,
email: null,
loading: false,
error: error.message
});
}
};
// Login handlers
const handleClaudeLogin = () => {
setLoginProvider('claude');
@@ -440,8 +531,15 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'tools' }) {
const handleLoginComplete = (exitCode) => {
if (exitCode === 0) {
// Login successful - could show a success message here
// Login successful - refresh authentication status
setSaveStatus('success');
// Refresh auth status based on which provider was used
if (loginProvider === 'claude') {
checkClaudeAuthStatus();
} else if (loginProvider === 'cursor') {
checkCursorAuthStatus();
}
}
// Modal will close itself via the LoginModal component
};
@@ -1039,23 +1137,52 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'tools' }) {
</h3>
</div>
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<div className="font-medium text-blue-900 dark:text-blue-100">
Claude CLI Login
</div>
<div className="text-sm text-blue-700 dark:text-blue-300">
Sign in to your Claude account to enable AI features
</div>
<div className="space-y-3">
{/* Authentication Status */}
<div className="flex items-center gap-2">
{claudeAuthStatus.loading ? (
<span className="text-sm text-blue-700 dark:text-blue-300">
Checking authentication...
</span>
) : claudeAuthStatus.authenticated ? (
<div className="flex items-center gap-2">
<Badge variant="success" className="bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300">
Logged in
</Badge>
{claudeAuthStatus.email && (
<span className="text-sm text-blue-700 dark:text-blue-300">
as {claudeAuthStatus.email}
</span>
)}
</div>
) : (
<Badge variant="secondary" className="bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300">
Not authenticated
</Badge>
)}
</div>
{/* Login Button and Description */}
<div className="flex items-center justify-between">
<div>
<div className="font-medium text-blue-900 dark:text-blue-100">
Claude CLI Login
</div>
<div className="text-sm text-blue-700 dark:text-blue-300">
{claudeAuthStatus.authenticated
? 'Re-authenticate or switch accounts'
: 'Sign in to your Claude account to enable AI features'}
</div>
</div>
<Button
onClick={handleClaudeLogin}
className="bg-blue-600 hover:bg-blue-700 text-white"
size="sm"
>
<LogIn className="w-4 h-4 mr-2" />
Login
</Button>
</div>
<Button
onClick={handleClaudeLogin}
className="bg-blue-600 hover:bg-blue-700 text-white"
size="sm"
>
<LogIn className="w-4 h-4 mr-2" />
Login
</Button>
</div>
</div>
</div>
@@ -1799,23 +1926,52 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'tools' }) {
</h3>
</div>
<div className="bg-purple-50 dark:bg-purple-900/20 border border-purple-200 dark:border-purple-800 rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<div className="font-medium text-purple-900 dark:text-purple-100">
Cursor CLI Login
</div>
<div className="text-sm text-purple-700 dark:text-purple-300">
Sign in to your Cursor account to enable AI features
</div>
<div className="space-y-3">
{/* Authentication Status */}
<div className="flex items-center gap-2">
{cursorAuthStatus.loading ? (
<span className="text-sm text-purple-700 dark:text-purple-300">
Checking authentication...
</span>
) : cursorAuthStatus.authenticated ? (
<div className="flex items-center gap-2">
<Badge variant="success" className="bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300">
Logged in
</Badge>
{cursorAuthStatus.email && (
<span className="text-sm text-purple-700 dark:text-purple-300">
as {cursorAuthStatus.email}
</span>
)}
</div>
) : (
<Badge variant="secondary" className="bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300">
Not authenticated
</Badge>
)}
</div>
{/* Login Button and Description */}
<div className="flex items-center justify-between">
<div>
<div className="font-medium text-purple-900 dark:text-purple-100">
Cursor CLI Login
</div>
<div className="text-sm text-purple-700 dark:text-purple-300">
{cursorAuthStatus.authenticated
? 'Re-authenticate or switch accounts'
: 'Sign in to your Cursor account to enable AI features'}
</div>
</div>
<Button
onClick={handleCursorLogin}
className="bg-purple-600 hover:bg-purple-700 text-white"
size="sm"
>
<LogIn className="w-4 h-4 mr-2" />
Login
</Button>
</div>
<Button
onClick={handleCursorLogin}
className="bg-purple-600 hover:bg-purple-700 text-white"
size="sm"
>
<LogIn className="w-4 h-4 mr-2" />
Login
</Button>
</div>
</div>
</div>