import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { request as invoke } from '../../utils/request'; import { Search, AlertTriangle } from 'lucide-react'; interface IpAccessLog { id: string; client_ip: string; timestamp: number; method?: string; path?: string; user_agent?: string; status?: number; duration?: number; api_key_hash?: string; blocked: boolean; block_reason?: string; username?: string; } interface IpAccessLogResponse { logs: IpAccessLog[]; total: number; } interface Props { refreshKey?: number; } export const IpAccessLogs: React.FC = ({ refreshKey }) => { const { t } = useTranslation(); const [logs, setLogs] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); const [page, setPage] = useState(1); const [pageSize, setPageSize] = useState(50); const [search, setSearch] = useState(''); const [blockedOnly, setBlockedOnly] = useState(false); const loadLogs = async () => { setLoading(true); try { const res = await invoke('get_ip_access_logs', { page, pageSize: pageSize, search: search || undefined, blockedOnly: blockedOnly, }); setLogs(res.logs); setTotal(res.total); } catch (e) { console.error('Failed to load logs', e); } finally { setLoading(false); } }; useEffect(() => { loadLogs(); }, [page, pageSize, blockedOnly, refreshKey]); // Handle search on enter or blur const handleSearch = () => { setPage(1); loadLogs(); }; return (
{/* Toolbar */}
setSearch(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} onBlur={handleSearch} />
{/* Table */}
{logs.map((log) => ( ))} {!loading && logs.length === 0 && ( )}
{t('security.logs.status')} {t('security.logs.ip_address')} {t('security.logs.username', 'User')} {t('security.logs.method')} {t('security.logs.path')} {t('security.logs.duration')} {t('security.logs.time')} {t('security.logs.reason')}
{log.blocked ? ( {t('security.logs.blocked')} ) : ( = 200 && log.status < 400 ? 'badge-success' : 'badge-warning'}`}> {log.status || '-'} )} {log.client_ip} {log.username || '-'} {log.method || '-'} {log.path || '-'} {log.duration ? `${log.duration}ms` : '-'} {new Date(log.timestamp * 1000).toLocaleString()} {log.block_reason}
{t('security.logs.no_logs')}
{/* Pagination */}
{t('security.logs.total_records', { total })}
); };