import { prisma } from '../../database/prisma.js'; import type { SecuritySearchTemplate, SearchHistoryEntry, SecurityActivityEvent, } from './securityTypes.js'; export async function getSecurityTemplates(): Promise { const rows = await prisma.securitySearchTemplate.findMany({ orderBy: { createdAt: 'desc' }, }); return rows.map(row => ({ id: row.id, name: row.name, description: row.description, query: row.query, severity: row.severity as SecuritySearchTemplate['severity'], timeframe: row.timeframe, sources: (row.sources as string[]) ?? [], createdAt: row.createdAt.toISOString(), })); } export async function recordSearchHistory(entry: Omit & { ranAt?: string }): Promise { const created = await prisma.securitySearchHistory.create({ data: { id: entry.id, query: entry.query, severity: entry.severity, timeframe: entry.timeframe, sources: entry.sources, results: entry.results, latencyMs: entry.latencyMs, createdAt: entry.ranAt ? new Date(entry.ranAt) : undefined, }, }); return { ...entry, ranAt: created.createdAt.toISOString(), }; } export async function getSearchHistory(limit = 6): Promise { const rows = await prisma.securitySearchHistory.findMany({ orderBy: { createdAt: 'desc' }, take: limit, }); return rows.map(row => ({ id: row.id, query: row.query, severity: row.severity, timeframe: row.timeframe, sources: (row.sources as string[]) ?? [], results: row.results, latencyMs: row.latencyMs, ranAt: row.createdAt.toISOString(), })); } export async function persistActivityEvent(event: SecurityActivityEvent): Promise { await prisma.securityActivityEvent.upsert({ where: { id: event.id }, update: { title: event.title, description: event.description, category: event.category, severity: event.severity, source: event.source, rule: event.rule ?? null, channel: event.channel, payload: event.payload as any, createdAt: event.createdAt ? new Date(event.createdAt) : undefined, acknowledged: event.acknowledged ?? false, }, create: { id: event.id, title: event.title, description: event.description, category: event.category, severity: event.severity, source: event.source, rule: event.rule ?? null, channel: event.channel, payload: event.payload as any, createdAt: event.createdAt ? new Date(event.createdAt) : undefined, acknowledged: event.acknowledged ?? false, }, }); } interface ActivityFilter { severity?: string; category?: string; limit?: number; } export async function listActivityEvents(filter: ActivityFilter = {}): Promise { const where: any = {}; if (filter.severity && filter.severity !== 'all') { where.severity = filter.severity; } if (filter.category && filter.category !== 'all') { where.category = filter.category; } const rows = await prisma.securityActivityEvent.findMany({ where, orderBy: { createdAt: 'desc' }, take: filter.limit ?? 25, }); return rows.map(row => ({ id: row.id, title: row.title, description: row.description, category: row.category as SecurityActivityEvent['category'], severity: row.severity as SecurityActivityEvent['severity'], source: row.source, rule: row.rule ?? undefined, channel: row.channel as SecurityActivityEvent['channel'], payload: row.payload as Record | undefined, createdAt: row.createdAt.toISOString(), acknowledged: row.acknowledged, })); } export async function setActivityAcknowledged(id: string, acknowledged: boolean): Promise { try { const updated = await prisma.securityActivityEvent.update({ where: { id }, data: { acknowledged }, }); return { id: updated.id, title: updated.title, description: updated.description, category: updated.category as SecurityActivityEvent['category'], severity: updated.severity as SecurityActivityEvent['severity'], source: updated.source, rule: updated.rule ?? undefined, channel: updated.channel as SecurityActivityEvent['channel'], payload: updated.payload as Record | undefined, createdAt: updated.createdAt.toISOString(), acknowledged: updated.acknowledged, }; } catch { return null; } } export async function getWidgetPermissions(widgetId: string): Promise { return prisma.widgetPermission.findMany({ where: { widgetId }, }); } export async function checkWidgetAccess(widgetId: string, resourceType: string, requiredLevel: 'read' | 'write'): Promise { const row = await prisma.widgetPermission.findUnique({ where: { widgetId_resourceType: { widgetId, resourceType } }, }); const levels = { none: 0, read: 1, write: 2 }; if (row && row.override) { return levels[row.accessLevel as keyof typeof levels] >= levels[requiredLevel]; } const defaultRow = await prisma.widgetPermission.findUnique({ where: { widgetId_resourceType: { widgetId: 'SYSTEM_DEFAULT', resourceType } }, }); const defaultLevel = defaultRow ? defaultRow.accessLevel : 'read'; return levels[defaultLevel as keyof typeof levels] >= levels[requiredLevel]; } export async function setWidgetPermission(widgetId: string, resourceType: string, accessLevel: 'none' | 'read' | 'write', override: boolean = false): Promise { await prisma.widgetPermission.upsert({ where: { widgetId_resourceType: { widgetId, resourceType } }, update: { accessLevel, override }, create: { widgetId, resourceType, accessLevel, override }, }); } export async function setPlatformDefault(resourceType: string, accessLevel: 'none' | 'read' | 'write'): Promise { await prisma.widgetPermission.upsert({ where: { widgetId_resourceType: { widgetId: 'SYSTEM_DEFAULT', resourceType } }, update: { accessLevel, override: false }, create: { widgetId: 'SYSTEM_DEFAULT', resourceType, accessLevel, override: false }, }); }