import React, { useState, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import ReactJsonView from 'react-json-view';
import { format } from 'date-fns';
import {
X,
Copy,
ExternalLink,
Shield,
User,
Clock,
MapPin,
AlertTriangle,
CheckCircle,
XCircle,
Eye,
EyeOff,
Download,
Link as LinkIcon,
Code,
FileText,
Activity,
Tag
} from 'lucide-react';
import { AuditLogEntry } from '@/types/audit';
import { toast } from 'react-toastify';
interface LogDetailModalProps {
log: AuditLogEntry | null;
isOpen: boolean;
onClose: () => void;
onViewCorrelated?: (requestId: string) => void;
onViewSession?: (sessionId: string) => void;
}
type TabType = 'overview' | 'context' | 'metadata' | 'compliance' | 'raw';
const SeverityBadge: React.FC<{ severity: AuditLogEntry['severity'] }> = ({ severity }) => {
const config = {
low: { icon: CheckCircle, className: 'severity-low' },
medium: { icon: AlertTriangle, className: 'severity-medium' },
high: { icon: AlertTriangle, className: 'severity-high' },
critical: { icon: XCircle, className: 'severity-critical' }
};
const { icon: Icon, className } = config[severity];
return (
{severity.charAt(0).toUpperCase() + severity.slice(1)}
);
};
const StatusBadge: React.FC<{ success: boolean; reason?: string }> = ({ success, reason }) => {
return (
{success ? (
) : (
)}
{success ? 'Success' : 'Failed'}
{reason && (
{reason}
)}
);
};
const ComplianceBadges: React.FC<{ compliance: AuditLogEntry['compliance'] }> = ({ compliance }) => {
const frameworks = [];
if (compliance.soc2Relevant) frameworks.push({ name: 'SOC2', relevant: true });
if (compliance.hipaaRelevant) frameworks.push({ name: 'HIPAA', relevant: true });
if (compliance.pciRelevant) frameworks.push({ name: 'PCI DSS', relevant: true });
if (compliance.gdprRelevant) frameworks.push({ name: 'GDPR', relevant: true });
return (
{frameworks.map(({ name }) => (
{name}
))}
{frameworks.length === 0 && (
No compliance frameworks
)}
);
};
const CopyButton: React.FC<{ value: string; label: string }> = ({ value, label }) => {
const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText(value);
toast.success(`${label} copied to clipboard`);
} catch (error) {
toast.error(`Failed to copy ${label}`);
}
}, [value, label]);
return (
);
};
export const LogDetailModal: React.FC = ({
log,
isOpen,
onClose,
onViewCorrelated,
onViewSession
}) => {
const [activeTab, setActiveTab] = useState('overview');
const [showSensitiveData, setShowSensitiveData] = useState(false);
if (!log) return null;
const handleExportJson = () => {
const dataStr = JSON.stringify(log, null, 2);
const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
const exportFileDefaultName = `audit-log-${log.id}.json`;
const linkElement = document.createElement('a');
linkElement.setAttribute('href', dataUri);
linkElement.setAttribute('download', exportFileDefaultName);
linkElement.click();
};
const tabs = [
{ id: 'overview', label: 'Overview', icon: Eye },
{ id: 'context', label: 'Context', icon: Activity },
{ id: 'metadata', label: 'Metadata', icon: Tag },
{ id: 'compliance', label: 'Compliance', icon: Shield },
{ id: 'raw', label: 'Raw JSON', icon: Code }
] as const;
return (
{isOpen && (
<>
{/* Backdrop */}
{/* Modal */}
{/* Header */}
Audit Log Details
{format(log.timestamp, 'PPpp')}
{log.user.username}
{/* Tabs */}
{/* Content */}
{activeTab === 'overview' && (
{/* Action and Status */}
Action
Type
{log.action.type.replace(/_/g, ' ').toUpperCase()}
Resource
{log.action.resource}
{log.action.resourceId && (
Resource ID
{log.action.resourceId}
)}
Description
{log.action.description}
Result
Status
{log.result.decision && (
Decision
{log.result.decision}
)}
Severity
{(log.result.errorCode || log.result.errorMessage) && (
{log.result.errorCode && (
Error Code
{log.result.errorCode}
)}
{log.result.errorMessage && (
Error Message
{log.result.errorMessage}
)}
)}
{/* User Information */}
User Information
Username
{log.user.username}
Email
{log.user.email}
Roles
{log.user.roles.map((role) => (
{role}
))}
{/* Quick Actions */}
{onViewCorrelated && (
)}
{onViewSession && (
)}
)}
{activeTab === 'context' && (
Request Context
Session & Request
Session ID
{log.context.sessionId}
Request ID
{log.context.requestId}
MFA Enabled
{log.context.mfaEnabled ? 'Yes' : 'No'}
Network & Location
IP Address
{log.context.ipAddress}
{log.context.location && (
<>
Country
{log.context.location.country}
City
{log.context.location.city}
{log.context.location.coordinates && (
Coordinates
{log.context.location.coordinates[0]}, {log.context.location.coordinates[1]}
)}
>
)}
User Agent
{showSensitiveData ? log.context.userAgent : '***HIDDEN***'}
)}
{activeTab === 'metadata' && (
Metadata
{/* Tags */}
Tags
{log.tags.length > 0 ? (
{log.tags.map((tag) => (
{tag}
))}
) : (
No tags
)}
{/* Retention Policy */}
Retention Policy
Retention Period
{log.retention.retentionPeriod} days
{log.retention.archiveDate && (
Archive Date
{format(log.retention.archiveDate, 'PP')}
)}
{log.retention.deletionDate && (
Deletion Date
{format(log.retention.deletionDate, 'PP')}
)}
{/* Custom Metadata */}
{Object.keys(log.metadata).length > 0 && (
)}
)}
{activeTab === 'compliance' && (
Compliance Information
Relevant Frameworks
{/* Compliance Details */}
{log.compliance.soc2Relevant && (
SOC2 Type II
This log entry is relevant for SOC2 Type II compliance monitoring.
)}
{log.compliance.hipaaRelevant && (
HIPAA
This log entry contains PHI-related activity for HIPAA compliance.
)}
{log.compliance.pciRelevant && (
PCI DSS
This log entry is relevant for PCI DSS compliance requirements.
)}
{log.compliance.gdprRelevant && (
GDPR
This log entry involves personal data processing under GDPR.
)}
)}
{activeTab === 'raw' && (
)}
>
)}
);
};