Kraft102's picture
Update backend source
34367da verified
import { prisma } from '../../database/prisma.js';
import type {
SecuritySearchTemplate,
SearchHistoryEntry,
SecurityActivityEvent,
} from './securityTypes.js';
export async function getSecurityTemplates(): Promise<SecuritySearchTemplate[]> {
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<SearchHistoryEntry, 'ranAt'> & { ranAt?: string }): Promise<SearchHistoryEntry> {
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<SearchHistoryEntry[]> {
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<void> {
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<SecurityActivityEvent[]> {
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<string, unknown> | undefined,
createdAt: row.createdAt.toISOString(),
acknowledged: row.acknowledged,
}));
}
export async function setActivityAcknowledged(id: string, acknowledged: boolean): Promise<SecurityActivityEvent | null> {
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<string, unknown> | undefined,
createdAt: updated.createdAt.toISOString(),
acknowledged: updated.acknowledged,
};
} catch {
return null;
}
}
export async function getWidgetPermissions(widgetId: string): Promise<any[]> {
return prisma.widgetPermission.findMany({
where: { widgetId },
});
}
export async function checkWidgetAccess(widgetId: string, resourceType: string, requiredLevel: 'read' | 'write'): Promise<boolean> {
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<void> {
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<void> {
await prisma.widgetPermission.upsert({
where: { widgetId_resourceType: { widgetId: 'SYSTEM_DEFAULT', resourceType } },
update: { accessLevel, override: false },
create: { widgetId: 'SYSTEM_DEFAULT', resourceType, accessLevel, override: false },
});
}