149 lines
6.8 KiB
TypeScript
149 lines
6.8 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Ban, Mail, Globe, AlertTriangle } from "lucide-react";
|
|
import { securityService } from "@/services";
|
|
import type { SuspiciousIP, SuspiciousEmail } from "@/types/security.types";
|
|
|
|
export default function SuspiciousActivityPage() {
|
|
const { data: suspicious, isLoading } = useQuery({
|
|
queryKey: ["admin", "security", "suspicious"],
|
|
queryFn: () => securityService.getSuspiciousActivity(),
|
|
});
|
|
|
|
return (
|
|
<div className="space-y-8 max-w-7xl mx-auto bg-white p-4 min-h-screen">
|
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
|
<div>
|
|
<h1 className="text-3xl font-bold text-gray-900 tracking-tight">
|
|
Anomalous Activity
|
|
</h1>
|
|
<p className="text-gray-500 mt-1">
|
|
High-risk identifiers flagged for potential system abuse.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
<Card className="border shadow-none rounded-none overflow-hidden">
|
|
<CardHeader className="border-b pb-4 bg-gray-50/30 flex flex-row items-center justify-between">
|
|
<div className="flex items-center gap-2">
|
|
<Globe className="w-4 h-4 text-gray-400" />
|
|
<CardTitle className="text-xs font-bold uppercase tracking-widest text-gray-400">
|
|
Suspicious Network Ingress
|
|
</CardTitle>
|
|
</div>
|
|
<span className="px-2 py-0.5 text-[9px] font-bold uppercase bg-rose-50 text-rose-600 border border-rose-100">
|
|
Shield Active
|
|
</span>
|
|
</CardHeader>
|
|
<CardContent className="p-0">
|
|
{isLoading ? (
|
|
<div className="p-20 text-center text-gray-400 animate-pulse font-medium uppercase tracking-widest text-[10px]">
|
|
Interrogating global threats...
|
|
</div>
|
|
) : (suspicious?.suspiciousIPs?.length ?? 0) > 0 ? (
|
|
<div className="divide-y">
|
|
{suspicious?.suspiciousIPs?.map(
|
|
(ip: SuspiciousIP, index: number) => (
|
|
<div
|
|
key={index}
|
|
className="flex items-center justify-between p-6 hover:bg-gray-50 transition-colors group"
|
|
>
|
|
<div>
|
|
<p className="text-sm font-bold font-mono text-gray-900 tracking-tighter">
|
|
{ip.ipAddress}
|
|
</p>
|
|
<p className="text-[10px] font-bold text-gray-400 uppercase tracking-widest mt-0.5">
|
|
{ip.attempts} Flagged Interactions
|
|
</p>
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-8 rounded-none border border-transparent hover:border-gray-900 hover:bg-gray-900 hover:text-white transition-all font-bold uppercase tracking-widest text-[9px]"
|
|
>
|
|
<Ban className="w-3 h-3 mr-2" /> Block IP
|
|
</Button>
|
|
</div>
|
|
),
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="p-20 text-center text-gray-400 italic font-medium uppercase tracking-widest text-[10px]">
|
|
No high-risk network sources.
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card className="border shadow-none rounded-none overflow-hidden">
|
|
<CardHeader className="border-b pb-4 bg-gray-50/30 flex flex-row items-center justify-between">
|
|
<div className="flex items-center gap-2">
|
|
<Mail className="w-4 h-4 text-gray-400" />
|
|
<CardTitle className="text-xs font-bold uppercase tracking-widest text-gray-400">
|
|
Flagged Credentials
|
|
</CardTitle>
|
|
</div>
|
|
<span className="px-2 py-0.5 text-[9px] font-bold uppercase bg-emerald-50 text-emerald-600 border border-emerald-100">
|
|
Monitoring
|
|
</span>
|
|
</CardHeader>
|
|
<CardContent className="p-0">
|
|
{isLoading ? (
|
|
<div className="p-20 text-center text-gray-400 animate-pulse font-medium uppercase tracking-widest text-[10px]">
|
|
Screening identity registry...
|
|
</div>
|
|
) : (suspicious?.suspiciousEmails?.length ?? 0) > 0 ? (
|
|
<div className="divide-y">
|
|
{suspicious?.suspiciousEmails?.map(
|
|
(email: SuspiciousEmail, index: number) => (
|
|
<div
|
|
key={index}
|
|
className="flex items-center justify-between p-6 hover:bg-gray-50 transition-colors group"
|
|
>
|
|
<div>
|
|
<p className="text-sm font-bold text-gray-900 tracking-tighter">
|
|
{email.email}
|
|
</p>
|
|
<p className="text-[10px] font-bold text-gray-400 uppercase tracking-widest mt-0.5">
|
|
{email.attempts} Security Triggers
|
|
</p>
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-8 rounded-none border border-transparent hover:border-gray-900 hover:bg-gray-900 hover:text-white transition-all font-bold uppercase tracking-widest text-[9px]"
|
|
>
|
|
<Ban className="w-3 h-3 mr-2" /> Block Domain
|
|
</Button>
|
|
</div>
|
|
),
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="p-20 text-center text-gray-400 italic font-medium uppercase tracking-widest text-[10px]">
|
|
No suspicious identity triggers.
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<div className="p-6 bg-amber-50 border border-amber-100 rounded-none flex items-start gap-4">
|
|
<AlertTriangle className="w-5 h-5 text-amber-500 flex-shrink-0 mt-0.5" />
|
|
<div className="space-y-1">
|
|
<p className="text-[10px] font-bold uppercase tracking-widest text-amber-900">
|
|
Protocol Awareness
|
|
</p>
|
|
<p className="text-xs text-amber-700 leading-relaxed font-medium">
|
|
Flagged items above are generated based on heuristic analysis of
|
|
failed signatures, geofence violations, and credential stuffing
|
|
patterns. Actions taken here apply globally to the ingress proxy.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|