suite des maj
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import DataTable, { Column } from './ui/DataTable';
|
||||
|
||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@ -75,6 +76,94 @@ function ErrorMessage({ message }: { message: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Detections DataTable ─────────────────────────────────────────────────────
|
||||
|
||||
function TcpDetectionsTable({
|
||||
items,
|
||||
navigate,
|
||||
}: {
|
||||
items: TcpSpoofingItem[];
|
||||
navigate: (path: string) => void;
|
||||
}) {
|
||||
const columns = useMemo((): Column<TcpSpoofingItem>[] => [
|
||||
{
|
||||
key: 'ip',
|
||||
label: 'IP',
|
||||
render: (v: string) => <span className="font-mono text-xs text-text-primary">{v}</span>,
|
||||
},
|
||||
{
|
||||
key: 'ja4',
|
||||
label: 'JA4',
|
||||
render: (v: string) => (
|
||||
<span className="font-mono text-xs text-text-secondary">
|
||||
{v ? `${v.slice(0, 14)}…` : '—'}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'tcp_ttl',
|
||||
label: 'TTL observé',
|
||||
align: 'right',
|
||||
render: (v: number) => (
|
||||
<span className={`font-mono font-semibold ${ttlColor(v)}`}>{v}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'tcp_window_size',
|
||||
label: 'Fenêtre TCP',
|
||||
align: 'right',
|
||||
render: (v: number) => (
|
||||
<span className="text-text-secondary text-xs">{formatNumber(v)}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'suspected_os',
|
||||
label: 'OS suspecté',
|
||||
render: (v: string) => <span className="text-text-primary text-xs">{v || '—'}</span>,
|
||||
},
|
||||
{
|
||||
key: 'declared_os',
|
||||
label: 'OS déclaré',
|
||||
render: (v: string) => <span className="text-text-secondary text-xs">{v || '—'}</span>,
|
||||
},
|
||||
{
|
||||
key: 'spoof_flag',
|
||||
label: 'Spoof',
|
||||
sortable: false,
|
||||
render: (v: boolean) =>
|
||||
v ? (
|
||||
<span className="bg-threat-critical/20 text-threat-critical text-xs px-2 py-0.5 rounded-full">
|
||||
🚨 Spoof
|
||||
</span>
|
||||
) : null,
|
||||
},
|
||||
{
|
||||
key: '_actions',
|
||||
label: '',
|
||||
sortable: false,
|
||||
render: (_: unknown, row: TcpSpoofingItem) => (
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); navigate(`/investigation/${row.ip}`); }}
|
||||
className="text-xs bg-accent-primary/10 text-accent-primary px-3 py-1 rounded hover:bg-accent-primary/20 transition-colors"
|
||||
>
|
||||
Investiguer
|
||||
</button>
|
||||
),
|
||||
},
|
||||
], [navigate]);
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
data={items}
|
||||
columns={columns}
|
||||
rowKey="ip"
|
||||
defaultSortKey="tcp_ttl"
|
||||
emptyMessage="Aucune détection"
|
||||
compact
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Main Component ───────────────────────────────────────────────────────────
|
||||
|
||||
export function TcpSpoofingView() {
|
||||
@ -261,53 +350,7 @@ export function TcpSpoofingView() {
|
||||
) : itemsError ? (
|
||||
<div className="p-4"><ErrorMessage message={itemsError} /></div>
|
||||
) : (
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b border-border text-text-secondary text-left">
|
||||
<th className="px-4 py-3">IP</th>
|
||||
<th className="px-4 py-3">JA4</th>
|
||||
<th className="px-4 py-3">TTL observé</th>
|
||||
<th className="px-4 py-3">Fenêtre TCP</th>
|
||||
<th className="px-4 py-3">OS suspecté</th>
|
||||
<th className="px-4 py-3">OS déclaré</th>
|
||||
<th className="px-4 py-3">Spoof</th>
|
||||
<th className="px-4 py-3"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredItems.map((item) => (
|
||||
<tr key={item.ip} className="border-b border-border hover:bg-background-card transition-colors">
|
||||
<td className="px-4 py-3 font-mono text-xs text-text-primary">{item.ip}</td>
|
||||
<td className="px-4 py-3 font-mono text-xs text-text-secondary">
|
||||
{item.ja4 ? `${item.ja4.slice(0, 14)}…` : '—'}
|
||||
</td>
|
||||
<td className={`px-4 py-3 font-mono font-semibold ${ttlColor(item.tcp_ttl)}`}>
|
||||
{item.tcp_ttl}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-text-secondary text-xs">
|
||||
{formatNumber(item.tcp_window_size)}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-text-primary text-xs">{item.suspected_os || '—'}</td>
|
||||
<td className="px-4 py-3 text-text-secondary text-xs">{item.declared_os || '—'}</td>
|
||||
<td className="px-4 py-3">
|
||||
{item.spoof_flag && (
|
||||
<span className="bg-threat-critical/20 text-threat-critical text-xs px-2 py-0.5 rounded-full">
|
||||
🚨 Spoof
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<button
|
||||
onClick={() => navigate(`/investigation/${item.ip}`)}
|
||||
className="text-xs bg-accent-primary/10 text-accent-primary px-3 py-1 rounded hover:bg-accent-primary/20 transition-colors"
|
||||
>
|
||||
Investiguer
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<TcpDetectionsTable items={filteredItems} navigate={navigate} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user