feat: Implement comprehensive audit logging

This commit is contained in:
gpt-engineer-app[bot]
2025-10-27 17:14:24 +00:00
parent 79277c744a
commit 2de13c12e4
4 changed files with 158 additions and 0 deletions

View File

@@ -333,16 +333,40 @@ export const ReportsQueue = forwardRef<ReportsQueueRef>((props, ref) => {
const handleReportAction = async (reportId: string, action: 'reviewed' | 'dismissed') => {
setActionLoading(reportId);
try {
// Fetch report details for audit log
const report = reports.find(r => r.id === reportId);
const { error } = await supabase
.from('reports')
.update({
status: action,
reviewed_by: user?.id,
reviewed_at: new Date().toISOString(),
})
.eq('id', reportId);
if (error) throw error;
// Log audit trail for report resolution
if (user && report) {
try {
await supabase.rpc('log_admin_action', {
_admin_user_id: user.id,
_target_user_id: report.reported_by,
_action: action === 'reviewed' ? 'report_resolved' : 'report_dismissed',
_details: {
report_id: reportId,
reported_entity_type: report.reported_entity_type,
reported_entity_id: report.reported_entity_id,
report_reason: report.reason,
action: action
}
});
} catch (auditError) {
console.error('Failed to log report action audit:', auditError);
}
}
handleSuccess(`Report ${action}`, `The report has been marked as ${action}`);
// Remove report from queue

View File

@@ -235,6 +235,25 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
if (error) throw error;
// Log audit trail for review moderation
if (table === 'reviews' && user) {
try {
await supabase.rpc('log_admin_action', {
_admin_user_id: user.id,
_target_user_id: item.user_id,
_action: `review_${action}`,
_details: {
review_id: item.id,
entity_type: item.entity_type,
entity_id: item.entity_id,
moderator_notes: moderatorNotes
}
});
} catch (auditError) {
logger.error('Failed to log review moderation audit', { error: auditError });
}
}
toast({
title: `Content ${action}`,
description: `The ${item.type} has been ${action}`,
@@ -266,10 +285,35 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
onActionStart(item.id);
try {
// Fetch submission details for audit log
const { data: submission } = await supabase
.from('content_submissions')
.select('user_id, submission_type, status')
.eq('id', item.id)
.single();
const { error } = await supabase.from('content_submissions').delete().eq('id', item.id);
if (error) throw error;
// Log audit trail for deletion
if (user && submission) {
try {
await supabase.rpc('log_admin_action', {
_admin_user_id: user.id,
_target_user_id: submission.user_id,
_action: 'submission_deleted',
_details: {
submission_id: item.id,
submission_type: submission.submission_type,
status_when_deleted: submission.status
}
});
} catch (auditError) {
logger.error('Failed to log submission deletion audit', { error: auditError });
}
}
toast({
title: 'Submission deleted',
description: 'The submission has been permanently deleted',
@@ -302,6 +346,23 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
const { resetRejectedItemsToPending } = await import('@/lib/submissionItemsService');
await resetRejectedItemsToPending(item.id);
// Log audit trail for reset
if (user) {
try {
await supabase.rpc('log_admin_action', {
_admin_user_id: user.id,
_target_user_id: item.user_id,
_action: 'submission_reset',
_details: {
submission_id: item.id,
submission_type: item.submission_type
}
});
} catch (auditError) {
logger.error('Failed to log submission reset audit', { error: auditError });
}
}
toast({
title: 'Reset Complete',
description: 'Submission and all items have been reset to pending status',
@@ -355,6 +416,25 @@ export function useModerationActions(config: ModerationActionsConfig): Moderatio
if (error) throw error;
// Log audit trail for retry
if (user) {
try {
await supabase.rpc('log_admin_action', {
_admin_user_id: user.id,
_target_user_id: item.user_id,
_action: 'submission_retried',
_details: {
submission_id: item.id,
submission_type: item.submission_type,
items_retried: failedItems.length,
request_id: requestId
}
});
} catch (auditError) {
logger.error('Failed to log submission retry audit', { error: auditError });
}
}
toast({
title: 'Items Retried',
description: `Successfully retried ${failedItems.length} failed item(s)${requestId ? ` (Request: ${requestId.substring(0, 8)})` : ''}`,

View File

@@ -1155,6 +1155,13 @@ export async function escalateSubmission(
throw new Error('User authentication required to escalate submission');
}
// Fetch submission details for audit log
const { data: submission } = await supabase
.from('content_submissions')
.select('user_id, submission_type')
.eq('id', submissionId)
.single();
const { error } = await supabase
.from('content_submissions')
.update({
@@ -1166,4 +1173,22 @@ export async function escalateSubmission(
.eq('id', submissionId);
if (error) throw error;
// Log audit trail for escalation
if (submission) {
try {
await supabase.rpc('log_admin_action', {
_admin_user_id: userId,
_target_user_id: submission.user_id,
_action: 'submission_escalated',
_details: {
submission_id: submissionId,
submission_type: submission.submission_type,
escalation_reason: reason
}
});
} catch (auditError) {
logger.error('Failed to log escalation audit', { error: auditError });
}
}
}

View File

@@ -602,6 +602,35 @@ serve(async (req) => {
console.error('[APPROVAL] Failed to update submission status:', { error: updateError.message });
}
// Log audit trail for submission action
try {
const approvedCount = approvalResults.filter(r => r.success).length;
const rejectedCount = approvalResults.filter(r => !r.success).length;
await supabaseClient.rpc('log_admin_action', {
_admin_user_id: authenticatedUserId,
_target_user_id: submission.user_id,
_action: finalStatus === 'approved'
? 'submission_approved'
: finalStatus === 'partially_approved'
? 'submission_partially_approved'
: 'submission_rejected',
_details: {
submission_id: submissionId,
submission_type: submission.submission_type,
items_approved: approvedCount,
items_rejected: rejectedCount,
total_items: approvalResults.length,
final_status: finalStatus,
has_dependency_failure: hasDependencyFailure,
reviewer_notes: reviewerNotes
}
});
} catch (auditError) {
// Log but don't fail the operation
console.error('[AUDIT] Failed to log admin action:', auditError);
}
const duration = endRequest(tracking);
return new Response(