162 lines
3.5 KiB
TypeScript
162 lines
3.5 KiB
TypeScript
import type { Database } from '@db/sqlite';
|
|
import { sql } from './queries.ts';
|
|
|
|
export interface LogEntry {
|
|
log_id: string;
|
|
timestamp: string;
|
|
level: string;
|
|
message: string;
|
|
args: string | null;
|
|
source: string | null;
|
|
created_at: number;
|
|
event_type: string | null;
|
|
severity: string | null;
|
|
remote_addr: string | null;
|
|
ccn_pubkey: string | null;
|
|
event_id: string | null;
|
|
risk_score: number | null;
|
|
}
|
|
|
|
export function getRecentLogs(
|
|
db: Database,
|
|
limit = 100,
|
|
level?: string,
|
|
): LogEntry[] {
|
|
if (level) {
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE level = ${level}
|
|
ORDER BY created_at DESC
|
|
LIMIT ${limit}
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
return sql`
|
|
SELECT * FROM logs
|
|
ORDER BY created_at DESC
|
|
LIMIT ${limit}
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
export function getSecurityLogs(
|
|
db: Database,
|
|
limit = 100,
|
|
severity?: string,
|
|
): LogEntry[] {
|
|
if (severity) {
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE event_type IS NOT NULL AND severity = ${severity}
|
|
ORDER BY created_at DESC
|
|
LIMIT ${limit}
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE event_type IS NOT NULL
|
|
ORDER BY created_at DESC
|
|
LIMIT ${limit}
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
export function getLogsByTimeRange(
|
|
db: Database,
|
|
startTime: number,
|
|
endTime: number,
|
|
level?: string,
|
|
): LogEntry[] {
|
|
if (level) {
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE created_at >= ${startTime} AND created_at <= ${endTime} AND level = ${level}
|
|
ORDER BY created_at DESC
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE created_at >= ${startTime} AND created_at <= ${endTime}
|
|
ORDER BY created_at DESC
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
export function getLogsByCCN(
|
|
db: Database,
|
|
ccnPubkey: string,
|
|
limit = 100,
|
|
): LogEntry[] {
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE ccn_pubkey = ${ccnPubkey}
|
|
ORDER BY created_at DESC
|
|
LIMIT ${limit}
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
export function getHighRiskLogs(
|
|
db: Database,
|
|
minRiskScore = 7.0,
|
|
limit = 50,
|
|
): LogEntry[] {
|
|
return sql`
|
|
SELECT * FROM logs
|
|
WHERE risk_score >= ${minRiskScore}
|
|
ORDER BY risk_score DESC, created_at DESC
|
|
LIMIT ${limit}
|
|
`(db) as LogEntry[];
|
|
}
|
|
|
|
export function getLogStats(db: Database): {
|
|
total_logs: number;
|
|
logs_by_level: Record<string, number>;
|
|
security_events: number;
|
|
high_risk_events: number;
|
|
last_24h_logs: number;
|
|
} {
|
|
const totalLogs = sql`SELECT COUNT(*) as count FROM logs`(db)[0].count;
|
|
|
|
const logsByLevel = sql`
|
|
SELECT level, COUNT(*) as count
|
|
FROM logs
|
|
GROUP BY level
|
|
`(db);
|
|
|
|
const securityEvents = sql`
|
|
SELECT COUNT(*) as count
|
|
FROM logs
|
|
WHERE event_type IS NOT NULL
|
|
`(db)[0].count;
|
|
|
|
const highRiskEvents = sql`
|
|
SELECT COUNT(*) as count
|
|
FROM logs
|
|
WHERE risk_score >= 7.0
|
|
`(db)[0].count;
|
|
|
|
const last24hLogs = sql`
|
|
SELECT COUNT(*) as count
|
|
FROM logs
|
|
WHERE created_at >= ${Math.floor(Date.now() / 1000) - 86400}
|
|
`(db)[0].count;
|
|
|
|
const levelStats: Record<string, number> = {};
|
|
for (const row of logsByLevel) {
|
|
levelStats[row.level] = row.count;
|
|
}
|
|
|
|
return {
|
|
total_logs: totalLogs,
|
|
logs_by_level: levelStats,
|
|
security_events: securityEvents,
|
|
high_risk_events: highRiskEvents,
|
|
last_24h_logs: last24hLogs,
|
|
};
|
|
}
|
|
|
|
export function cleanupOldLogs(db: Database, daysToKeep = 30): number {
|
|
const cutoffTime = Math.floor(Date.now() / 1000) - daysToKeep * 86400;
|
|
|
|
const stmt = db.prepare('DELETE FROM logs WHERE created_at < ?');
|
|
return stmt.run(cutoffTime);
|
|
}
|