/** * Terminal Authentication Dialog * Displays auth form with password/key selection for SSH connection */ import { BadgeCheck, ChevronDown, Eye, EyeOff, Key, Lock, Unplug } from 'lucide-react'; import React from 'react'; import { useI18n } from '../../application/i18n/I18nProvider'; import { cn } from '../../lib/utils'; import { SSHKey } from '../../types'; import { Button } from '../ui/button'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import { Dropdown, DropdownContent, DropdownTrigger } from '../ui/dropdown'; import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'; export type TerminalAuthMethod = 'password' | 'key' | 'certificate'; export interface TerminalAuthDialogProps { authMethod: TerminalAuthMethod; setAuthMethod: (method: TerminalAuthMethod) => void; authUsername: string; setAuthUsername: (username: string) => void; authPassword: string; setAuthPassword: (password: string) => void; authKeyId: string | null; setAuthKeyId: (keyId: string | null) => void; authPassphrase: string; setAuthPassphrase: (passphrase: string) => void; showAuthPassphrase: boolean; setShowAuthPassphrase: (show: boolean) => void; showAuthPassword: boolean; setShowAuthPassword: (show: boolean) => void; authRetryMessage: string | null; keys: SSHKey[]; onSubmit: () => void; onSubmitWithoutSave?: () => void; onCancel: () => void; isValid: boolean; } export const TerminalAuthDialog: React.FC = ({ authMethod, setAuthMethod, authUsername, setAuthUsername, authPassword, setAuthPassword, authKeyId, setAuthKeyId, authPassphrase, setAuthPassphrase, showAuthPassphrase, setShowAuthPassphrase, showAuthPassword, setShowAuthPassword, authRetryMessage, keys, onSubmit, onSubmitWithoutSave, onCancel, isValid, }) => { const { t } = useI18n(); const handleContinue = onSubmitWithoutSave ?? onSubmit; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && isValid) { handleContinue(); } }; // Show all keys (both regular keys and certificates) in the single key picker. const selectableKeys = React.useMemo( () => keys.filter((k) => k.category === 'key' || Boolean(k.certificate?.trim())), [keys], ); const [keyDropdownOpen, setKeyDropdownOpen] = React.useState(false); const [submitOptionsOpen, setSubmitOptionsOpen] = React.useState(false); const selectedKey = authKeyId ? keys.find((k) => k.id === authKeyId) : null; return ( <> {/* Auth method tabs */}
{/* Auth retry error message */} {authRetryMessage && (
{authRetryMessage}
)}
setAuthUsername(e.target.value)} placeholder={t("terminal.auth.username.placeholder")} />
{authMethod === 'password' ? (
setAuthPassword(e.target.value)} placeholder={t("terminal.auth.password.placeholder")} className={cn("pr-10", authRetryMessage && "border-destructive/50")} autoFocus={!!authRetryMessage} onKeyDown={handleKeyDown} />
) : ( <>
{selectableKeys.length === 0 ? (
{t("terminal.auth.noKeysHint")}
) : (
{selectableKeys.map((key) => ( ))}
)}
setAuthPassphrase(e.target.value)} placeholder={t("terminal.auth.passphrase.placeholder")} className="pr-10" disabled={!selectedKey} onKeyDown={handleKeyDown} />
)}
); }; export default TerminalAuthDialog;