diff --git a/backend/src/features/audit-log/data/audit-log.repository.ts b/backend/src/features/audit-log/data/audit-log.repository.ts index 94774f6..622e5b7 100644 --- a/backend/src/features/audit-log/data/audit-log.repository.ts +++ b/backend/src/features/audit-log/data/audit-log.repository.ts @@ -39,37 +39,37 @@ export class AuditLogRepository { let paramIndex = 1; if (filters.search) { - conditions.push(`action ILIKE $${paramIndex}`); + conditions.push(`al.action ILIKE $${paramIndex}`); params.push(`%${this.escapeLikePattern(filters.search)}%`); paramIndex++; } if (filters.category) { - conditions.push(`category = $${paramIndex}`); + conditions.push(`al.category = $${paramIndex}`); params.push(filters.category); paramIndex++; } if (filters.severity) { - conditions.push(`severity = $${paramIndex}`); + conditions.push(`al.severity = $${paramIndex}`); params.push(filters.severity); paramIndex++; } if (filters.userId) { - conditions.push(`user_id = $${paramIndex}`); + conditions.push(`al.user_id = $${paramIndex}`); params.push(filters.userId); paramIndex++; } if (filters.startDate) { - conditions.push(`created_at >= $${paramIndex}`); + conditions.push(`al.created_at >= $${paramIndex}`); params.push(filters.startDate); paramIndex++; } if (filters.endDate) { - conditions.push(`created_at <= $${paramIndex}`); + conditions.push(`al.created_at <= $${paramIndex}`); params.push(filters.endDate); paramIndex++; } @@ -86,7 +86,8 @@ export class AuditLogRepository { const query = ` INSERT INTO audit_logs (category, severity, user_id, action, resource_type, resource_id, details) VALUES ($1, $2, $3, $4, $5, $6, $7) - RETURNING id, category, severity, user_id, action, resource_type, resource_id, details, created_at + RETURNING id, category, severity, user_id, action, resource_type, resource_id, details, created_at, + NULL::text as user_email `; try { @@ -117,14 +118,17 @@ export class AuditLogRepository { const { whereClause, params, nextParamIndex } = this.buildWhereClause(filters); // Count query - const countQuery = `SELECT COUNT(*) as total FROM audit_logs ${whereClause}`; + const countQuery = `SELECT COUNT(*) as total FROM audit_logs al ${whereClause}`; - // Data query with pagination + // Data query with pagination - LEFT JOIN to get user email const dataQuery = ` - SELECT id, category, severity, user_id, action, resource_type, resource_id, details, created_at - FROM audit_logs + SELECT al.id, al.category, al.severity, al.user_id, al.action, + al.resource_type, al.resource_id, al.details, al.created_at, + up.email as user_email + FROM audit_logs al + LEFT JOIN user_profiles up ON al.user_id = up.auth0_sub ${whereClause} - ORDER BY created_at DESC + ORDER BY al.created_at DESC LIMIT $${nextParamIndex} OFFSET $${nextParamIndex + 1} `; @@ -156,16 +160,19 @@ export class AuditLogRepository { const { whereClause, params } = this.buildWhereClause(filters); // First, count total matching records - const countQuery = `SELECT COUNT(*) as total FROM audit_logs ${whereClause}`; + const countQuery = `SELECT COUNT(*) as total FROM audit_logs al ${whereClause}`; const countResult = await this.pool.query(countQuery, params); const totalCount = parseInt(countResult.rows[0].total, 10); const truncated = totalCount > MAX_EXPORT_RECORDS; const query = ` - SELECT id, category, severity, user_id, action, resource_type, resource_id, details, created_at - FROM audit_logs + SELECT al.id, al.category, al.severity, al.user_id, al.action, + al.resource_type, al.resource_id, al.details, al.created_at, + up.email as user_email + FROM audit_logs al + LEFT JOIN user_profiles up ON al.user_id = up.auth0_sub ${whereClause} - ORDER BY created_at DESC + ORDER BY al.created_at DESC LIMIT ${MAX_EXPORT_RECORDS} `; @@ -222,6 +229,7 @@ export class AuditLogRepository { category: row.category as AuditLogEntry['category'], severity: row.severity as AuditLogEntry['severity'], userId: row.user_id as string | null, + userEmail: (row.user_email as string | null) || null, action: row.action as string, resourceType: row.resource_type as string | null, resourceId: row.resource_id as string | null, diff --git a/backend/src/features/audit-log/domain/audit-log.types.ts b/backend/src/features/audit-log/domain/audit-log.types.ts index 0c17de6..d1c98fb 100644 --- a/backend/src/features/audit-log/domain/audit-log.types.ts +++ b/backend/src/features/audit-log/domain/audit-log.types.ts @@ -21,6 +21,7 @@ export interface AuditLogEntry { category: AuditLogCategory; severity: AuditLogSeverity; userId: string | null; + userEmail: string | null; action: string; resourceType: string | null; resourceId: string | null; diff --git a/frontend/src/features/admin/mobile/AdminLogsMobileScreen.tsx b/frontend/src/features/admin/mobile/AdminLogsMobileScreen.tsx index 02e8cec..3089f61 100644 --- a/frontend/src/features/admin/mobile/AdminLogsMobileScreen.tsx +++ b/frontend/src/features/admin/mobile/AdminLogsMobileScreen.tsx @@ -268,11 +268,15 @@ const AdminLogsMobileScreen: React.FC = () => { {/* Metadata */}