import * as appstate from '../../appstate.js'; import { DeesElement, customElement, html, state, css, cssManager, type TemplateResult, } from '@design.estate/dees-element'; import { type IStatsTile } from '@design.estate/dees-catalog'; declare global { interface HTMLElementTagNameMap { 'ops-view-security-overview': OpsViewSecurityOverview; } } @customElement('ops-view-security-overview') export class OpsViewSecurityOverview extends DeesElement { @state() accessor statsState: appstate.IStatsState = appstate.statsStatePart.getState()!; constructor() { super(); const sub = appstate.statsStatePart .select((s) => s) .subscribe((s) => { this.statsState = s; }); this.rxSubscriptions.push(sub); } public static styles = [ cssManager.defaultStyles, css` :host { display: block; } h2 { margin: 32px 0 16px 0; font-size: 24px; font-weight: 600; color: ${cssManager.bdTheme('#333', '#ccc')}; } dees-statsgrid { margin-bottom: 32px; } `, ]; public render(): TemplateResult { const metrics = this.statsState.securityMetrics; if (!metrics) { return html`

Loading security metrics...

`; } const threatLevel = this.calculateThreatLevel(metrics); const threatScore = this.getThreatScore(metrics); // Derive active sessions from recent successful auth events (last hour) const allEvents: any[] = metrics.recentEvents || []; const oneHourAgo = Date.now() - 3600000; const recentAuthSuccesses = allEvents.filter( (evt: any) => evt.type === 'authentication' && evt.success === true && evt.timestamp >= oneHourAgo ).length; const tiles: IStatsTile[] = [ { id: 'threatLevel', title: 'Threat Level', value: threatScore, type: 'gauge', icon: 'lucide:Shield', gaugeOptions: { min: 0, max: 100, thresholds: [ { value: 0, color: '#ef4444' }, { value: 30, color: '#f59e0b' }, { value: 70, color: '#22c55e' }, ], }, description: `Status: ${threatLevel.toUpperCase()}`, }, { id: 'blockedThreats', title: 'Blocked Threats', value: (metrics.blockedIPs?.length || 0) + metrics.spamDetected, type: 'number', icon: 'lucide:ShieldCheck', color: '#ef4444', description: 'Total threats blocked today', }, { id: 'activeSessions', title: 'Active Sessions', value: recentAuthSuccesses, type: 'number', icon: 'lucide:Users', color: '#22c55e', description: 'Authenticated in last hour', }, { id: 'authFailures', title: 'Auth Failures', value: metrics.authenticationFailures, type: 'number', icon: 'lucide:LockOpen', color: metrics.authenticationFailures > 10 ? '#ef4444' : '#f59e0b', description: 'Failed login attempts today', }, ]; return html` Overview

Recent Security Events

({ 'Time': new Date(item.timestamp).toLocaleTimeString(), 'Event': item.event, 'Severity': item.severity, 'Details': item.details, })} > `; } private calculateThreatLevel(metrics: any): string { const score = this.getThreatScore(metrics); if (score < 30) return 'alert'; if (score < 70) return 'warning'; return 'success'; } private getThreatScore(metrics: any): number { // Simple scoring algorithm let score = 100; const blockedCount = Array.isArray(metrics.blockedIPs) ? metrics.blockedIPs.length : (metrics.blockedIPs || 0); score -= blockedCount * 2; score -= (metrics.authenticationFailures || 0) * 1; score -= (metrics.spamDetected || 0) * 0.5; score -= (metrics.malwareDetected || 0) * 3; score -= (metrics.phishingDetected || 0) * 3; score -= (metrics.suspiciousActivities || 0) * 2; return Math.max(0, Math.min(100, Math.round(score))); } private getSecurityEvents(metrics: any): any[] { const events: any[] = metrics.recentEvents || []; return events.map((evt: any) => ({ timestamp: evt.timestamp, event: evt.message, severity: evt.level === 'critical' ? 'critical' : evt.level === 'error' ? 'high' : evt.level === 'warn' ? 'warning' : 'info', details: evt.ipAddress ? `IP: ${evt.ipAddress}` : evt.domain ? `Domain: ${evt.domain}` : evt.type, })); } }