mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-24 11:11:13 -05:00
Implement Phase 3C error logging
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
import { logger } from './logger';
|
||||
import { handleNonCriticalError } from './errorHandler';
|
||||
|
||||
/**
|
||||
* Write admin audit details to relational table
|
||||
@@ -27,7 +27,10 @@ export async function writeAdminAuditDetails(
|
||||
.insert(entries);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to write admin audit details', { error, auditLogId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Write admin audit details',
|
||||
metadata: { auditLogId },
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +56,10 @@ export async function writeModerationAuditMetadata(
|
||||
.insert(entries);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to write moderation audit metadata', { error, auditLogId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Write moderation audit metadata',
|
||||
metadata: { auditLogId },
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +90,10 @@ export async function writeItemChangeFields(
|
||||
.insert(entries);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to write item change fields', { error, editHistoryId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Write item change fields',
|
||||
metadata: { editHistoryId },
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +127,10 @@ export async function writeRequestBreadcrumbs(
|
||||
.insert(entries);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to write request breadcrumbs', { error, requestId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Write request breadcrumbs',
|
||||
metadata: { requestId },
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -135,7 +147,10 @@ export async function readAdminAuditDetails(
|
||||
.eq('audit_log_id', auditLogId);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to read admin audit details', { error, auditLogId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Read admin audit details',
|
||||
metadata: { auditLogId },
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -157,7 +172,10 @@ export async function readModerationAuditMetadata(
|
||||
.eq('audit_log_id', auditLogId);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to read moderation audit metadata', { error, auditLogId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Read moderation audit metadata',
|
||||
metadata: { auditLogId },
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -179,7 +197,10 @@ export async function readItemChangeFields(
|
||||
.eq('edit_history_id', editHistoryId);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to read item change fields', { error, editHistoryId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Read item change fields',
|
||||
metadata: { editHistoryId },
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -218,7 +239,10 @@ export async function writeProfileChangeFields(
|
||||
.insert(entries);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to write profile change fields', { error, auditLogId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Write profile change fields',
|
||||
metadata: { auditLogId },
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -252,7 +276,10 @@ export async function writeConflictDetailFields(
|
||||
.insert(entries);
|
||||
|
||||
if (error) {
|
||||
logger.error('Failed to write conflict detail fields', { error, conflictResolutionId });
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Write conflict detail fields',
|
||||
metadata: { conflictResolutionId },
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
} from '@/types/auth';
|
||||
import { setStepUpRequired, setAuthMethod, clearAllAuthFlags } from './sessionFlags';
|
||||
import { logger } from './logger';
|
||||
import { getErrorMessage } from './errorHandler';
|
||||
import { getErrorMessage, handleNonCriticalError } from './errorHandler';
|
||||
|
||||
/**
|
||||
* Extract AAL level from session using Supabase API
|
||||
@@ -37,9 +37,8 @@ export async function getSessionAal(session: Session | null): Promise<AALLevel>
|
||||
});
|
||||
|
||||
if (error) {
|
||||
logger.error('[AuthService] Error getting AAL', {
|
||||
action: 'get_session_aal',
|
||||
error: error.message
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Get session AAL',
|
||||
});
|
||||
return 'aal1';
|
||||
}
|
||||
@@ -48,10 +47,8 @@ export async function getSessionAal(session: Session | null): Promise<AALLevel>
|
||||
logger.log('[AuthService] Returning AAL', { level });
|
||||
return level;
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('[AuthService] Exception getting AAL', {
|
||||
action: 'get_session_aal',
|
||||
error: errorMessage
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Get session AAL exception',
|
||||
});
|
||||
return 'aal1';
|
||||
}
|
||||
@@ -65,9 +62,8 @@ export async function getEnrolledFactors(): Promise<MFAFactor[]> {
|
||||
const { data, error } = await supabase.auth.mfa.listFactors();
|
||||
|
||||
if (error) {
|
||||
logger.error('[AuthService] Error listing factors', {
|
||||
action: 'get_enrolled_factors',
|
||||
error: error.message
|
||||
handleNonCriticalError(error, {
|
||||
action: 'List MFA factors',
|
||||
});
|
||||
return [];
|
||||
}
|
||||
@@ -83,10 +79,8 @@ export async function getEnrolledFactors(): Promise<MFAFactor[]> {
|
||||
updated_at: f.updated_at,
|
||||
}));
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('[AuthService] Exception listing factors', {
|
||||
action: 'get_enrolled_factors',
|
||||
error: errorMessage
|
||||
handleNonCriticalError(error, {
|
||||
action: 'List MFA factors exception',
|
||||
});
|
||||
return [];
|
||||
}
|
||||
@@ -135,21 +129,18 @@ export async function verifyMfaRequired(userId: string): Promise<boolean> {
|
||||
.in('role', ['admin', 'moderator']);
|
||||
|
||||
if (error) {
|
||||
logger.error('[AuthService] Error checking roles', {
|
||||
action: 'verify_mfa_required',
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Verify MFA required',
|
||||
userId,
|
||||
error: error.message
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return (data?.length || 0) > 0;
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('[AuthService] Exception checking roles', {
|
||||
action: 'verify_mfa_required',
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Verify MFA required exception',
|
||||
userId,
|
||||
error: errorMessage
|
||||
});
|
||||
return false;
|
||||
}
|
||||
@@ -207,15 +198,13 @@ export async function handlePostAuthFlow(
|
||||
},
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('[AuthService] Error in post-auth flow', {
|
||||
action: 'handle_post_auth_flow',
|
||||
authMethod,
|
||||
error: errorMessage
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Handle post-auth flow',
|
||||
metadata: { authMethod },
|
||||
});
|
||||
return {
|
||||
success: false,
|
||||
error: errorMessage,
|
||||
error: getErrorMessage(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -234,10 +223,9 @@ export async function verifyMfaUpgrade(session: Session | null): Promise<MFAChal
|
||||
const currentAal = await getSessionAal(session);
|
||||
|
||||
if (currentAal !== 'aal2') {
|
||||
logger.error('[AuthService] MFA verification failed', {
|
||||
action: 'verify_mfa_upgrade',
|
||||
expectedAal: 'aal2',
|
||||
actualAal: currentAal
|
||||
handleNonCriticalError(new Error('MFA verification failed'), {
|
||||
action: 'Verify MFA upgrade',
|
||||
metadata: { expectedAal: 'aal2', actualAal: currentAal },
|
||||
});
|
||||
await logAuthEvent(session.user.id, 'mfa_verification_failed', {
|
||||
expected_aal: 'aal2',
|
||||
@@ -282,20 +270,15 @@ async function logAuthEvent(
|
||||
});
|
||||
|
||||
if (error) {
|
||||
logger.error('[AuthService] Error logging auth event', {
|
||||
action: 'log_auth_event',
|
||||
eventAction: action,
|
||||
userId,
|
||||
error: error.message
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Log auth event',
|
||||
metadata: { eventAction: action, userId },
|
||||
});
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('[AuthService] Exception logging auth event', {
|
||||
action: 'log_auth_event',
|
||||
eventAction: action,
|
||||
userId,
|
||||
error: errorMessage
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Log auth event exception',
|
||||
metadata: { eventAction: action, userId },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ import { supabase } from '@/lib/supabaseClient';
|
||||
import type { Json } from '@/integrations/supabase/types';
|
||||
import { uploadPendingImages } from './imageUploadHelper';
|
||||
import { CompanyFormData, TempCompanyData } from '@/types/company';
|
||||
import { logger } from './logger';
|
||||
import { getErrorMessage } from './errorHandler';
|
||||
import { handleError } from './errorHandler';
|
||||
|
||||
export type { CompanyFormData, TempCompanyData };
|
||||
|
||||
@@ -33,10 +32,9 @@ export async function submitCompanyCreation(
|
||||
uploaded: uploadedImages
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMsg = getErrorMessage(error);
|
||||
logger.error('Failed to upload images for company', {
|
||||
action: `${companyType}_creation`,
|
||||
error: errorMsg
|
||||
handleError(error, {
|
||||
action: 'Upload company images',
|
||||
metadata: { companyType },
|
||||
});
|
||||
throw new Error('Failed to upload images. Please check your connection and try again.');
|
||||
}
|
||||
@@ -120,11 +118,9 @@ export async function submitCompanyUpdate(
|
||||
uploaded: uploadedImages
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMsg = getErrorMessage(error);
|
||||
logger.error('Failed to upload images for company update', {
|
||||
action: `${existingCompany.company_type}_update`,
|
||||
companyId,
|
||||
error: errorMsg
|
||||
handleError(error, {
|
||||
action: 'Upload company images for update',
|
||||
metadata: { companyType: existingCompany.company_type, companyId },
|
||||
});
|
||||
throw new Error('Failed to upload images. Please check your connection and try again.');
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { logger } from '@/lib/logger';
|
||||
import { handleError, handleNonCriticalError } from '@/lib/errorHandler';
|
||||
import { updateSubmissionItem, type SubmissionItemWithDeps, type DependencyConflict } from './submissionItemsService';
|
||||
|
||||
export interface ResolutionResult {
|
||||
@@ -86,15 +85,13 @@ export async function resolveConflicts(
|
||||
updatedSelections,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMsg = getErrorMessage(error);
|
||||
logger.error('Conflict resolution error', {
|
||||
action: 'resolve_conflicts',
|
||||
conflictCount: conflicts.length,
|
||||
error: errorMsg
|
||||
handleError(error, {
|
||||
action: 'Resolve conflicts',
|
||||
metadata: { conflictCount: conflicts.length },
|
||||
});
|
||||
return {
|
||||
success: false,
|
||||
error: errorMsg,
|
||||
error: error instanceof Error ? error.message : 'Unknown error',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -236,11 +233,9 @@ export async function findMatchingEntities(
|
||||
|
||||
return [];
|
||||
} catch (error: unknown) {
|
||||
const errorMsg = getErrorMessage(error);
|
||||
logger.error('Error finding matching entities', {
|
||||
action: 'find_matching_entities',
|
||||
itemType,
|
||||
error: errorMsg
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Find matching entities',
|
||||
metadata: { itemType },
|
||||
});
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
import { invokeWithTracking } from '@/lib/edgeFunctionTracking';
|
||||
import { logger } from '@/lib/logger';
|
||||
import { getErrorMessage } from '@/lib/errorHandler';
|
||||
import { handleNonCriticalError } from '@/lib/errorHandler';
|
||||
|
||||
interface EmailValidationResult {
|
||||
valid: boolean;
|
||||
@@ -22,9 +21,8 @@ export async function validateEmailNotDisposable(email: string): Promise<EmailVa
|
||||
);
|
||||
|
||||
if (error) {
|
||||
logger.error('Email validation error from backend', {
|
||||
action: 'validate_email_backend',
|
||||
error: error.message
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Validate email backend',
|
||||
});
|
||||
return {
|
||||
valid: false,
|
||||
@@ -34,10 +32,8 @@ export async function validateEmailNotDisposable(email: string): Promise<EmailVa
|
||||
|
||||
return data as EmailValidationResult;
|
||||
} catch (error: unknown) {
|
||||
const errorMsg = getErrorMessage(error);
|
||||
logger.error('Email validation error', {
|
||||
action: 'validate_email_disposable',
|
||||
error: errorMsg
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Validate email disposable',
|
||||
});
|
||||
return {
|
||||
valid: false,
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { ProcessedImage } from './supabaseHelpers';
|
||||
import { extractChangedFields } from './submissionChangeDetection';
|
||||
import type { CompanyDatabaseRecord, TimelineEventDatabaseRecord } from '@/types/company-data';
|
||||
import { logger } from './logger';
|
||||
import { getErrorMessage } from './errorHandler';
|
||||
import { handleError } from './errorHandler';
|
||||
import type { TimelineEventFormData, EntityType } from '@/types/timeline';
|
||||
|
||||
// ============================================
|
||||
@@ -345,13 +345,11 @@ async function submitCompositeCreation(
|
||||
});
|
||||
|
||||
if (error) {
|
||||
logger.error('Composite submission failed', {
|
||||
action: 'composite_submission',
|
||||
primaryType: uploadedPrimary.type,
|
||||
dependencyCount: dependencies.length,
|
||||
error: getErrorMessage(error)
|
||||
handleError(error, {
|
||||
action: 'Composite submission',
|
||||
metadata: { primaryType: uploadedPrimary.type, dependencyCount: dependencies.length },
|
||||
});
|
||||
throw new Error(`Failed to create composite submission: ${getErrorMessage(error)}`);
|
||||
throw new Error(`Failed to create composite submission: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
|
||||
return { submitted: true, submissionId: result };
|
||||
@@ -440,12 +438,10 @@ export async function submitParkCreation(
|
||||
uploaded: uploadedImages
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Park image upload failed', {
|
||||
action: 'park_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload park images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,12 +747,10 @@ export async function submitRideCreation(
|
||||
uploaded: uploadedImages
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Ride image upload failed', {
|
||||
action: 'ride_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload ride images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,12 +966,10 @@ export async function submitRideModelCreation(
|
||||
uploaded: uploadedImages
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Ride model image upload failed', {
|
||||
action: 'ride_model_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload ride model images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1110,12 +1102,10 @@ export async function submitManufacturerCreation(
|
||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Company image upload failed', {
|
||||
action: 'manufacturer_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload manufacturer images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1218,12 +1208,10 @@ export async function submitDesignerCreation(
|
||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Company image upload failed', {
|
||||
action: 'designer_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload designer images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,12 +1314,10 @@ export async function submitOperatorCreation(
|
||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Company image upload failed', {
|
||||
action: 'operator_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload operator images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1434,12 +1420,10 @@ export async function submitPropertyOwnerCreation(
|
||||
const uploadedImages = await uploadPendingImages(data.images.uploaded);
|
||||
processedImages = { ...data.images, uploaded: uploadedImages };
|
||||
} catch (error: unknown) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Company image upload failed', {
|
||||
action: 'property_owner_creation',
|
||||
error: errorMessage
|
||||
handleError(error, {
|
||||
action: 'Upload property owner images',
|
||||
});
|
||||
throw new Error(`Failed to upload images: ${errorMessage}`);
|
||||
throw new Error(`Failed to upload images: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1602,11 +1586,9 @@ export async function submitTimelineEvent(
|
||||
});
|
||||
|
||||
if (error || !submissionId) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
logger.error('Timeline event submission failed', {
|
||||
action: 'create_timeline_event',
|
||||
handleError(error || new Error('No submission ID returned'), {
|
||||
action: 'Submit timeline event',
|
||||
userId,
|
||||
error: errorMessage
|
||||
});
|
||||
throw new Error('Failed to submit timeline event for review');
|
||||
}
|
||||
@@ -1679,11 +1661,9 @@ export async function submitTimelineEventUpdate(
|
||||
);
|
||||
|
||||
if (rpcError || !result) {
|
||||
const errorMessage = getErrorMessage(rpcError);
|
||||
logger.error('Timeline event update failed', {
|
||||
action: 'update_timeline_event',
|
||||
eventId,
|
||||
error: errorMessage
|
||||
handleError(rpcError || new Error('No result returned'), {
|
||||
action: 'Update timeline event',
|
||||
metadata: { eventId },
|
||||
});
|
||||
throw new Error('Failed to submit timeline event update');
|
||||
}
|
||||
@@ -1707,11 +1687,9 @@ export async function deleteTimelineEvent(
|
||||
.single();
|
||||
|
||||
if (fetchError) {
|
||||
const errorMessage = getErrorMessage(fetchError);
|
||||
logger.error('Timeline event fetch failed', {
|
||||
action: 'delete_timeline_event',
|
||||
eventId,
|
||||
error: errorMessage
|
||||
handleError(fetchError, {
|
||||
action: 'Delete timeline event',
|
||||
metadata: { eventId },
|
||||
});
|
||||
throw new Error('Timeline event not found');
|
||||
}
|
||||
@@ -1736,11 +1714,9 @@ export async function deleteTimelineEvent(
|
||||
.eq('id', eventId);
|
||||
|
||||
if (deleteError) {
|
||||
const errorMessage = getErrorMessage(deleteError);
|
||||
logger.error('Timeline event deletion failed', {
|
||||
action: 'delete_timeline_event',
|
||||
eventId,
|
||||
error: errorMessage
|
||||
handleError(deleteError, {
|
||||
action: 'Delete timeline event',
|
||||
metadata: { eventId },
|
||||
});
|
||||
throw new Error('Failed to delete timeline event');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user