UX improvements.
This commit is contained in:
@@ -82,8 +82,12 @@ function titleCaseScenario(s: string): string {
|
||||
).join(' ');
|
||||
}
|
||||
|
||||
function friendlyReason(reason: string): string {
|
||||
if (!reason) return 'Community blocklist';
|
||||
function friendlyScenario(scenario: string, origin?: string): string {
|
||||
if (!scenario) {
|
||||
if (origin === 'capi') return 'Community blocklist';
|
||||
if (origin === 'manual' || origin === 'cscli') return 'Manual';
|
||||
return origin || 'Unknown';
|
||||
}
|
||||
const map: Record<string, string> = {
|
||||
'crowdsecurity/http-scan-classb': 'HTTP Scanner',
|
||||
'crowdsecurity/ssh-slow-bruteforce': 'SSH Brute Force (slow)',
|
||||
@@ -96,8 +100,8 @@ function friendlyReason(reason: string): string {
|
||||
'crowdsecurity/http-bad-user-agent': 'Bad User Agent',
|
||||
'crowdsecurity/iptables-scan-multi_ports': 'Port Scanner',
|
||||
};
|
||||
if (map[reason]) return map[reason];
|
||||
const short = reason.includes('/') ? reason.split('/').slice(1).join(' ') : reason;
|
||||
if (map[scenario]) return map[scenario];
|
||||
const short = scenario.includes('/') ? scenario.split('/').slice(1).join(' ') : scenario;
|
||||
return titleCaseScenario(short);
|
||||
}
|
||||
|
||||
@@ -294,10 +298,10 @@ export function CrowdSecComponent() {
|
||||
/>
|
||||
{scenarioHubUrl(reason) ? (
|
||||
<a href={scenarioHubUrl(reason)!} target="_blank" rel="noopener noreferrer" className="text-muted-foreground hover:text-foreground hover:underline">
|
||||
{friendlyReason(reason)}
|
||||
{friendlyScenario(reason)}
|
||||
</a>
|
||||
) : (
|
||||
<span className="text-muted-foreground">{friendlyReason(reason)}</span>
|
||||
<span className="text-muted-foreground">{friendlyScenario(reason)}</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="font-mono text-xs tabular-nums">{count.toLocaleString()}</span>
|
||||
@@ -411,10 +415,10 @@ export function CrowdSecComponent() {
|
||||
</div>
|
||||
{scenarioHubUrl(alert.scenario) ? (
|
||||
<a href={scenarioHubUrl(alert.scenario)!} target="_blank" rel="noopener noreferrer" className="text-xs text-muted-foreground whitespace-nowrap hover:text-foreground hover:underline">
|
||||
{friendlyReason(alert.scenario)}
|
||||
{friendlyScenario(alert.scenario)}
|
||||
</a>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground whitespace-nowrap">{friendlyReason(alert.scenario)}</span>
|
||||
<span className="text-xs text-muted-foreground whitespace-nowrap">{friendlyScenario(alert.scenario)}</span>
|
||||
)}
|
||||
<span className="text-xs font-mono text-muted-foreground whitespace-nowrap">{alert.machineId?.replace(/^wc-/, '') ?? '—'}</span>
|
||||
<span className="text-xs text-muted-foreground whitespace-nowrap">{formatRelativeTime(alert.createdAt)}</span>
|
||||
@@ -528,7 +532,7 @@ export function CrowdSecComponent() {
|
||||
}
|
||||
<span className="font-mono truncate">{d.value}</span>
|
||||
<Badge variant="outline" className="text-xs h-4 shrink-0">{d.type}</Badge>
|
||||
<span className="text-muted-foreground truncate">{friendlyReason(d.reason)}</span>
|
||||
<span className="text-muted-foreground truncate">{friendlyScenario(d.scenario, d.origin)}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
{d.duration && (
|
||||
|
||||
Reference in New Issue
Block a user