SECURITY: Fix authentication and file manager display issues

- Add JWT authentication middleware to file manager and metrics APIs
- Fix WebSocket authentication timing race conditions
- Resolve file manager grid view display issue by eliminating request ID complexity
- Fix FileViewer translation function undefined error
- Simplify SSH authentication flow and remove duplicate connection attempts
- Ensure consistent user authentication across all services

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ZacharyZcR
2025-09-22 21:52:25 +08:00
parent b8a94017c9
commit aea00225d2
6 changed files with 159 additions and 79 deletions

View File

@@ -73,7 +73,6 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
const [files, setFiles] = useState<FileItem[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [sshSessionId, setSshSessionId] = useState<string | null>(null);
const [currentRequestId, setCurrentRequestId] = useState<number>(0);
const [isReconnecting, setIsReconnecting] = useState<boolean>(false);
const [searchQuery, setSearchQuery] = useState("");
const [lastRefreshTime, setLastRefreshTime] = useState<number>(0);
@@ -231,56 +230,39 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
}
}
async function loadDirectory(path: string) {
const loadDirectory = useCallback(async (path: string) => {
if (!sshSessionId) {
console.error("Cannot load directory: no SSH session ID");
return;
}
// Generate unique request ID to prevent race conditions
const requestId = Date.now();
setCurrentRequestId(requestId);
setIsLoading(true);
try {
console.log(`[${requestId}] Loading directory:`, path);
console.log("Loading directory:", path);
const response = await listSSHFiles(sshSessionId, path);
// Only process response if this is still the latest request
if (requestId !== currentRequestId) {
console.log(`[${requestId}] Request outdated, ignoring response`);
return;
}
console.log(`[${requestId}] Directory response received:`, response);
console.log("Directory response received:", response);
const files = Array.isArray(response) ? response : response?.files || [];
console.log("Directory loaded successfully:", files.length, "items");
setFiles(files);
clearSelection();
console.log(`[${requestId}] Directory loaded successfully:`, files.length, "items");
} catch (error: any) {
// Only handle error if this is still the latest request
if (requestId !== currentRequestId) {
console.log(`[${requestId}] Request outdated, ignoring error`);
return;
}
console.error(`[${requestId}] Failed to load directory:`, error);
console.error("Failed to load directory:", error);
toast.error(
t("fileManager.failedToLoadDirectory") + ": " + (error.message || error)
);
} finally {
// Only clear loading if this is still the latest request
if (requestId === currentRequestId) {
setIsLoading(false);
}
setIsLoading(false);
}
}
}, [sshSessionId, clearSelection, t]);
// Debounced refresh function - prevent excessive clicking
function handleRefreshDirectory() {
const handleRefreshDirectory = useCallback(() => {
const now = Date.now();
const DEBOUNCE_MS = 500; // 500ms debounce
@@ -291,7 +273,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
setLastRefreshTime(now);
loadDirectory(currentPath);
}
}, [currentPath, lastRefreshTime, loadDirectory]);
function handleFilesDropped(fileList: FileList) {
if (!sshSessionId) {
@@ -1465,6 +1447,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerModernProps) {
file.name.toLowerCase().includes(searchQuery.toLowerCase()),
);
if (!currentHost) {
return (
<div className="h-full flex items-center justify-center">