feat(audit): implement audit logging for search requests and results
All checks were successful
Publish FaceAI Container / publish (push) Successful in 13m22s
All checks were successful
Publish FaceAI Container / publish (push) Successful in 13m22s
- Added configuration options for audit database path and retention days in backend and processor. - Integrated audit logging in server and worker processes to track search requests, completions, and failures. - Created utility functions for reading and parsing audit logs in end-to-end tests. - Updated Docker Compose files to include audit database configuration. - Added new tests to verify audit log entries for successful and no-results searches.
This commit is contained in:
parent
a026fec62b
commit
32db61c381
14 changed files with 1067 additions and 16 deletions
|
|
@ -3,6 +3,7 @@ import fs from 'node:fs/promises';
|
|||
import path from 'node:path';
|
||||
import { Worker } from 'bullmq';
|
||||
import { config } from './config.js';
|
||||
import { createAuditStore } from '../../backend/src/audit-store.js';
|
||||
import {
|
||||
createRedisConnection,
|
||||
getSearchRecord,
|
||||
|
|
@ -16,6 +17,7 @@ import {
|
|||
import { parseMatcherCsv, resolvePklPath, runFaceMatcher } from './worker-utils.js';
|
||||
|
||||
const connection = createRedisConnection(config.redisUrl);
|
||||
const auditStore = createAuditStore({ dbPath: config.auditDbPath, retentionDays: config.auditRetentionDays });
|
||||
|
||||
async function ensureMatcherBinaryAvailable() {
|
||||
try {
|
||||
|
|
@ -93,9 +95,23 @@ async function completeSearch(search, searchId, searchLogPath, matchCount, match
|
|||
completionCode
|
||||
});
|
||||
|
||||
await markSearchCompleted(connection, searchId, result.id, matchCount, config.searchTtlSeconds, {
|
||||
const completedSearch = await markSearchCompleted(connection, searchId, result.id, matchCount, config.searchTtlSeconds, {
|
||||
completionCode
|
||||
});
|
||||
auditStore.markSearchCompleted({
|
||||
searchId,
|
||||
user: { id: search.userId },
|
||||
race: {
|
||||
id: search.raceId,
|
||||
name: search.raceName,
|
||||
storage: search.raceStorage
|
||||
},
|
||||
resultId: result.id,
|
||||
matchCount,
|
||||
matches,
|
||||
completionCode,
|
||||
completedAt: completedSearch?.completedAt || Date.now()
|
||||
});
|
||||
await releaseActiveSearchLock(connection, search.userId, searchId);
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +194,22 @@ async function processJob(job) {
|
|||
message: error.message,
|
||||
stack: error.stack || null
|
||||
});
|
||||
await markSearchFailed(connection, searchId, 'PROCESSOR_ERROR', error.message, config.searchTtlSeconds);
|
||||
const failedSearch = await markSearchFailed(connection, searchId, 'PROCESSOR_ERROR', error.message, config.searchTtlSeconds);
|
||||
auditStore.markSearchFailed({
|
||||
searchId,
|
||||
user: { id: search.userId },
|
||||
race: {
|
||||
id: search.raceId,
|
||||
name: search.raceName,
|
||||
storage: search.raceStorage
|
||||
},
|
||||
errorCode: 'PROCESSOR_ERROR',
|
||||
errorMessage: error.message,
|
||||
completedAt: failedSearch?.completedAt || Date.now(),
|
||||
payload: {
|
||||
stack: error.stack || null
|
||||
}
|
||||
});
|
||||
await releaseActiveSearchLock(connection, search.userId, searchId);
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue