mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 23:51:11 -05:00
Refactor: Implement full error logging
This commit is contained in:
@@ -5,7 +5,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { handleError, handleSuccess, handleInfo, AppError, getErrorMessage } from '@/lib/errorHandler';
|
import { handleError, handleSuccess, handleInfo, handleNonCriticalError, AppError, getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { useRequireMFA } from '@/hooks/useRequireMFA';
|
import { useRequireMFA } from '@/hooks/useRequireMFA';
|
||||||
@@ -51,10 +51,10 @@ export function TOTPSetup() {
|
|||||||
}));
|
}));
|
||||||
setFactors(totpFactors);
|
setFactors(totpFactors);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to fetch TOTP factors', {
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Fetch TOTP factors',
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
action: 'fetch_totp_factors',
|
metadata: { context: 'initial_load' }
|
||||||
error: getErrorMessage(error)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -76,11 +76,6 @@ export function TOTPSetup() {
|
|||||||
setFactorId(data.id);
|
setFactorId(data.id);
|
||||||
setEnrolling(true);
|
setEnrolling(true);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to start TOTP enrollment', {
|
|
||||||
userId: user?.id,
|
|
||||||
action: 'totp_enroll_start',
|
|
||||||
error: getErrorMessage(error)
|
|
||||||
});
|
|
||||||
handleError(
|
handleError(
|
||||||
new AppError(
|
new AppError(
|
||||||
getErrorMessage(error) || 'Failed to start TOTP enrollment',
|
getErrorMessage(error) || 'Failed to start TOTP enrollment',
|
||||||
@@ -148,13 +143,6 @@ export function TOTPSetup() {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('TOTP verification failed', {
|
|
||||||
userId: user?.id,
|
|
||||||
action: 'totp_verify',
|
|
||||||
error: getErrorMessage(error),
|
|
||||||
factorId
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(
|
handleError(
|
||||||
new AppError(
|
new AppError(
|
||||||
getErrorMessage(error) || 'Invalid verification code. Please try again.',
|
getErrorMessage(error) || 'Invalid verification code. Please try again.',
|
||||||
|
|||||||
@@ -148,13 +148,7 @@ export function ContactForm() {
|
|||||||
setCaptchaToken('');
|
setCaptchaToken('');
|
||||||
setCaptchaKey((prev) => prev + 1);
|
setCaptchaKey((prev) => prev + 1);
|
||||||
|
|
||||||
logger.info('Contact form submitted successfully', {
|
|
||||||
submissionId: result?.submissionId,
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Failed to submit contact form', {
|
|
||||||
error: error instanceof Error ? error.message : String(error),
|
|
||||||
});
|
|
||||||
handleError(error, {
|
handleError(error, {
|
||||||
action: 'submit_contact_form',
|
action: 'submit_contact_form',
|
||||||
metadata: { category: data.category },
|
metadata: { category: data.category },
|
||||||
|
|||||||
@@ -12,8 +12,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { handleError, handleSuccess, getErrorMessage } from '@/lib/errorHandler';
|
import { handleError, handleSuccess, handleNonCriticalError, getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
|
|
||||||
interface UserProfile {
|
interface UserProfile {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -131,7 +130,13 @@ export function ProfileManager() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (logError) logger.error('Failed to log admin action', { error: getErrorMessage(logError) });
|
if (logError) {
|
||||||
|
handleNonCriticalError(logError, {
|
||||||
|
action: 'Log admin action (ban/unban)',
|
||||||
|
userId: user?.id,
|
||||||
|
metadata: { targetUserId, ban, banReason }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
handleSuccess(
|
handleSuccess(
|
||||||
'Success',
|
'Success',
|
||||||
@@ -211,7 +216,13 @@ export function ProfileManager() {
|
|||||||
_details: { role: newRole, previous_roles: currentRoles }
|
_details: { role: newRole, previous_roles: currentRoles }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (logError) logger.error('Failed to log admin action', { error: getErrorMessage(logError) });
|
if (logError) {
|
||||||
|
handleNonCriticalError(logError, {
|
||||||
|
action: 'Log admin action (role change)',
|
||||||
|
userId: user?.id,
|
||||||
|
metadata: { targetUserId, newRole, previousRoles: currentRoles }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
handleSuccess('Success', 'User role updated successfully.');
|
handleSuccess('Success', 'User role updated successfully.');
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { useAdminSettings } from '@/hooks/useAdminSettings';
|
|||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { useIsMobile } from '@/hooks/use-mobile';
|
import { useIsMobile } from '@/hooks/use-mobile';
|
||||||
import { smartMergeArray } from '@/lib/smartStateUpdate';
|
import { smartMergeArray } from '@/lib/smartStateUpdate';
|
||||||
import { handleError, handleSuccess } from '@/lib/errorHandler';
|
import { handleError, handleSuccess, handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
|
|
||||||
// Type-safe reported content interfaces
|
// Type-safe reported content interfaces
|
||||||
interface ReportedReview {
|
interface ReportedReview {
|
||||||
@@ -383,7 +383,11 @@ export const ReportsQueue = forwardRef<ReportsQueueRef>((props, ref) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (auditError) {
|
} catch (auditError) {
|
||||||
logger.error('Failed to log report action audit', { error: auditError });
|
handleNonCriticalError(auditError, {
|
||||||
|
action: 'Log report action audit',
|
||||||
|
userId: user?.id,
|
||||||
|
metadata: { reportId, action }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,12 +32,6 @@ export function BlockedUsers() {
|
|||||||
.order('created_at', { ascending: false });
|
.order('created_at', { ascending: false });
|
||||||
|
|
||||||
if (blocksError) {
|
if (blocksError) {
|
||||||
logger.error('Failed to fetch user blocks', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'fetch_blocked_users',
|
|
||||||
error: blocksError.message,
|
|
||||||
errorCode: blocksError.code
|
|
||||||
});
|
|
||||||
throw blocksError;
|
throw blocksError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,12 +48,6 @@ export function BlockedUsers() {
|
|||||||
.in('user_id', blockedIds);
|
.in('user_id', blockedIds);
|
||||||
|
|
||||||
if (profilesError) {
|
if (profilesError) {
|
||||||
logger.error('Failed to fetch blocked user profiles', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'fetch_blocked_user_profiles',
|
|
||||||
error: profilesError.message,
|
|
||||||
errorCode: profilesError.code
|
|
||||||
});
|
|
||||||
throw profilesError;
|
throw profilesError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,18 +61,7 @@ export function BlockedUsers() {
|
|||||||
|
|
||||||
setBlockedUsers(blockedUsersWithProfiles as UserBlock[]);
|
setBlockedUsers(blockedUsersWithProfiles as UserBlock[]);
|
||||||
|
|
||||||
logger.info('Blocked users fetched successfully', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'fetch_blocked_users',
|
|
||||||
count: blockedUsersWithProfiles.length
|
|
||||||
});
|
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error fetching blocked users', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'fetch_blocked_users',
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(error, {
|
handleError(error, {
|
||||||
action: 'Load blocked users',
|
action: 'Load blocked users',
|
||||||
userId: user.id
|
userId: user.id
|
||||||
@@ -104,13 +81,6 @@ export function BlockedUsers() {
|
|||||||
.eq('id', blockId);
|
.eq('id', blockId);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to unblock user', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'unblock_user',
|
|
||||||
targetUserId: blockedUserId,
|
|
||||||
error: error.message,
|
|
||||||
errorCode: error.code
|
|
||||||
});
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,21 +98,8 @@ export function BlockedUsers() {
|
|||||||
|
|
||||||
setBlockedUsers(prev => prev.filter(block => block.id !== blockId));
|
setBlockedUsers(prev => prev.filter(block => block.id !== blockId));
|
||||||
|
|
||||||
logger.info('User unblocked successfully', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'unblock_user',
|
|
||||||
targetUserId: blockedUserId
|
|
||||||
});
|
|
||||||
|
|
||||||
handleSuccess('User unblocked', `You have unblocked @${username}`);
|
handleSuccess('User unblocked', `You have unblocked @${username}`);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error unblocking user', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'unblock_user',
|
|
||||||
targetUserId: blockedUserId,
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(error, {
|
handleError(error, {
|
||||||
action: 'Unblock user',
|
action: 'Unblock user',
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import { toast } from '@/hooks/use-toast';
|
|||||||
import { PhotoUpload } from '@/components/upload/PhotoUpload';
|
import { PhotoUpload } from '@/components/upload/PhotoUpload';
|
||||||
import { StarRating } from './StarRating';
|
import { StarRating } from './StarRating';
|
||||||
import { toDateOnly, parseDateOnly } from '@/lib/dateUtils';
|
import { toDateOnly, parseDateOnly } from '@/lib/dateUtils';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
const reviewSchema = z.object({
|
const reviewSchema = z.object({
|
||||||
rating: z.number().min(0.5).max(5).multipleOf(0.5),
|
rating: z.number().min(0.5).max(5).multipleOf(0.5),
|
||||||
title: z.string().optional(),
|
title: z.string().optional(),
|
||||||
@@ -109,7 +108,11 @@ export function ReviewForm({
|
|||||||
.insert(photoRecords);
|
.insert(photoRecords);
|
||||||
|
|
||||||
if (photosError) {
|
if (photosError) {
|
||||||
logger.error('Failed to insert review photos', { error: getErrorMessage(photosError) });
|
handleNonCriticalError(photosError, {
|
||||||
|
action: 'Insert review photos',
|
||||||
|
userId: user?.id,
|
||||||
|
metadata: { reviewId: review.id, photoCount: photos.length }
|
||||||
|
});
|
||||||
// Don't throw - review is already created
|
// Don't throw - review is already created
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import { Star, ThumbsUp, Calendar, MapPin } from 'lucide-react';
|
|||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { ReportButton } from '@/components/moderation/ReportButton';
|
import { ReportButton } from '@/components/moderation/ReportButton';
|
||||||
import { StarRating } from './StarRating';
|
import { StarRating } from './StarRating';
|
||||||
import { getErrorMessage } from '@/lib/errorHandler';
|
import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
|
|
||||||
interface ReviewWithProfile {
|
interface ReviewWithProfile {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -65,7 +64,10 @@ export function ReviewsList({ entityType, entityId, entityName }: ReviewsListPro
|
|||||||
const { data } = await query;
|
const { data } = await query;
|
||||||
setReviews((data || []) as ReviewWithProfile[]);
|
setReviews((data || []) as ReviewWithProfile[]);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to fetch reviews', { error: getErrorMessage(error), entityType, entityId });
|
handleNonCriticalError(error, {
|
||||||
|
action: 'Fetch reviews',
|
||||||
|
metadata: { entityType, entityId }
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { useProfile } from '@/hooks/useProfile';
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { handleError, handleSuccess, AppError } from '@/lib/errorHandler';
|
import { handleError, handleSuccess, handleNonCriticalError, AppError } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
import { Download, Activity, BarChart3, AlertCircle, Clock } from 'lucide-react';
|
import { Download, Activity, BarChart3, AlertCircle, Clock } from 'lucide-react';
|
||||||
import type {
|
import type {
|
||||||
UserStatistics,
|
UserStatistics,
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ import { useAuth } from '@/hooks/useAuth';
|
|||||||
import { useProfile } from '@/hooks/useProfile';
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { handleError, handleSuccess, AppError } from '@/lib/errorHandler';
|
import { handleError, handleSuccess, handleNonCriticalError, AppError } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
|
||||||
import { MapPin, Calendar, Accessibility, Ruler } from 'lucide-react';
|
import { MapPin, Calendar, Accessibility, Ruler } from 'lucide-react';
|
||||||
import type { LocationFormData, AccessibilityOptions, ParkOption } from '@/types/location';
|
import type { LocationFormData, AccessibilityOptions, ParkOption } from '@/types/location';
|
||||||
import {
|
import {
|
||||||
@@ -75,12 +74,6 @@ export function LocationTab() {
|
|||||||
.order('name');
|
.order('name');
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('Failed to fetch parks list', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'fetch_parks',
|
|
||||||
error: error.message,
|
|
||||||
errorCode: error.code
|
|
||||||
});
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,12 +191,6 @@ export function LocationTab() {
|
|||||||
.eq('user_id', user.id);
|
.eq('user_id', user.id);
|
||||||
|
|
||||||
if (profileError) {
|
if (profileError) {
|
||||||
logger.error('Failed to update profile', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'update_profile_location',
|
|
||||||
error: profileError.message,
|
|
||||||
errorCode: profileError.code
|
|
||||||
});
|
|
||||||
throw profileError;
|
throw profileError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,12 +203,6 @@ export function LocationTab() {
|
|||||||
.eq('user_id', user.id);
|
.eq('user_id', user.id);
|
||||||
|
|
||||||
if (accessibilityError) {
|
if (accessibilityError) {
|
||||||
logger.error('Failed to update accessibility preferences', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'update_accessibility_preferences',
|
|
||||||
error: accessibilityError.message,
|
|
||||||
errorCode: accessibilityError.code
|
|
||||||
});
|
|
||||||
throw accessibilityError;
|
throw accessibilityError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,22 +227,11 @@ export function LocationTab() {
|
|||||||
|
|
||||||
await refreshProfile();
|
await refreshProfile();
|
||||||
|
|
||||||
logger.info('Location and info settings updated', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'update_location_info'
|
|
||||||
});
|
|
||||||
|
|
||||||
handleSuccess(
|
handleSuccess(
|
||||||
'Settings saved',
|
'Settings saved',
|
||||||
'Your location, personal information, accessibility, and unit preferences have been updated.'
|
'Your location, personal information, accessibility, and unit preferences have been updated.'
|
||||||
);
|
);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error saving location settings', {
|
|
||||||
userId: user.id,
|
|
||||||
action: 'save_location_settings',
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error instanceof z.ZodError) {
|
if (error instanceof z.ZodError) {
|
||||||
handleError(
|
handleError(
|
||||||
new AppError(
|
new AppError(
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
|||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { handleError, handleSuccess, handleInfo } from "@/lib/errorHandler";
|
import { handleError, handleSuccess, handleInfo, handleNonCriticalError } from "@/lib/errorHandler";
|
||||||
import { logger } from "@/lib/logger";
|
|
||||||
import { notificationService } from "@/lib/notificationService";
|
import { notificationService } from "@/lib/notificationService";
|
||||||
import type {
|
import type {
|
||||||
NotificationPreferences,
|
NotificationPreferences,
|
||||||
@@ -53,18 +52,7 @@ export function NotificationsTab() {
|
|||||||
setWorkflowPreferences(preferences.workflowPreferences);
|
setWorkflowPreferences(preferences.workflowPreferences);
|
||||||
setFrequencySettings(preferences.frequencySettings);
|
setFrequencySettings(preferences.frequencySettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('Notification preferences loaded', {
|
|
||||||
action: 'load_notification_preferences',
|
|
||||||
userId: user.id
|
|
||||||
});
|
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to load notification preferences', {
|
|
||||||
action: 'load_notification_preferences',
|
|
||||||
userId: user.id,
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(error, {
|
handleError(error, {
|
||||||
action: 'Load notification preferences',
|
action: 'Load notification preferences',
|
||||||
userId: user.id
|
userId: user.id
|
||||||
@@ -92,20 +80,8 @@ export function NotificationsTab() {
|
|||||||
if (Object.keys(initialPrefs).length > 0) {
|
if (Object.keys(initialPrefs).length > 0) {
|
||||||
setWorkflowPreferences((prev) => ({ ...prev, ...initialPrefs }));
|
setWorkflowPreferences((prev) => ({ ...prev, ...initialPrefs }));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('Notification templates loaded', {
|
|
||||||
action: 'load_notification_templates',
|
|
||||||
userId: user.id,
|
|
||||||
count: templateData.length
|
|
||||||
});
|
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to load notification templates', {
|
handleNonCriticalError(error, {
|
||||||
action: 'load_notification_templates',
|
|
||||||
userId: user.id,
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(error, {
|
|
||||||
action: 'Load notification templates',
|
action: 'Load notification templates',
|
||||||
userId: user.id
|
userId: user.id
|
||||||
});
|
});
|
||||||
@@ -185,12 +161,6 @@ export function NotificationsTab() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Error requesting push permission', {
|
|
||||||
action: 'request_push_permission',
|
|
||||||
userId: user?.id,
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(error, {
|
handleError(error, {
|
||||||
action: 'Enable push notifications',
|
action: 'Enable push notifications',
|
||||||
userId: user?.id
|
userId: user?.id
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { handleError, handleSuccess, AppError, getErrorMessage } from '@/lib/errorHandler';
|
import { handleError, handleSuccess, handleNonCriticalError, AppError, getErrorMessage } from '@/lib/errorHandler';
|
||||||
import { logger } from '@/lib/logger';
|
import { logger } from '@/lib/logger';
|
||||||
import { supabase } from '@/lib/supabaseClient';
|
import { supabase } from '@/lib/supabaseClient';
|
||||||
import { Loader2, Shield, CheckCircle2 } from 'lucide-react';
|
import { Loader2, Shield, CheckCircle2 } from 'lucide-react';
|
||||||
@@ -82,9 +82,10 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
|
|||||||
const hasVerifiedTotp = data?.totp?.some(factor => factor.status === 'verified') || false;
|
const hasVerifiedTotp = data?.totp?.some(factor => factor.status === 'verified') || false;
|
||||||
setHasMFA(hasVerifiedTotp);
|
setHasMFA(hasVerifiedTotp);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('Failed to check MFA status', {
|
handleNonCriticalError(error, {
|
||||||
action: 'check_mfa_status',
|
action: 'Check MFA status',
|
||||||
error: error instanceof Error ? error.message : String(error)
|
userId,
|
||||||
|
metadata: { context: 'password_change_dialog' }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -142,13 +143,6 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
|
|||||||
setCaptchaToken('');
|
setCaptchaToken('');
|
||||||
setCaptchaKey(prev => prev + 1);
|
setCaptchaKey(prev => prev + 1);
|
||||||
|
|
||||||
logger.error('Password authentication failed', {
|
|
||||||
userId,
|
|
||||||
action: 'password_change_auth',
|
|
||||||
error: signInError.message,
|
|
||||||
errorCode: signInError.code
|
|
||||||
});
|
|
||||||
|
|
||||||
throw signInError;
|
throw signInError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,18 +163,6 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
|
|||||||
await updatePasswordWithNonce(data.newPassword, generatedNonce);
|
await updatePasswordWithNonce(data.newPassword, generatedNonce);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorDetails = isErrorWithCode(error) ? {
|
|
||||||
errorCode: error.code,
|
|
||||||
errorStatus: error.status
|
|
||||||
} : {};
|
|
||||||
|
|
||||||
logger.error('Password change failed', {
|
|
||||||
userId,
|
|
||||||
action: 'password_change',
|
|
||||||
error: getErrorMessage(error),
|
|
||||||
...errorDetails
|
|
||||||
});
|
|
||||||
|
|
||||||
const errorMessage = getErrorMessage(error);
|
const errorMessage = getErrorMessage(error);
|
||||||
const errorStatus = isErrorWithCode(error) ? error.status : undefined;
|
const errorStatus = isErrorWithCode(error) ? error.status : undefined;
|
||||||
|
|
||||||
@@ -238,12 +220,6 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (challengeError) {
|
if (challengeError) {
|
||||||
logger.error('MFA challenge creation failed', {
|
|
||||||
userId,
|
|
||||||
action: 'password_change_mfa_challenge',
|
|
||||||
error: challengeError.message,
|
|
||||||
errorCode: challengeError.code
|
|
||||||
});
|
|
||||||
throw challengeError;
|
throw challengeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,24 +231,12 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (verifyError) {
|
if (verifyError) {
|
||||||
logger.error('MFA verification failed', {
|
|
||||||
userId,
|
|
||||||
action: 'password_change_mfa',
|
|
||||||
error: verifyError.message,
|
|
||||||
errorCode: verifyError.code
|
|
||||||
});
|
|
||||||
throw verifyError;
|
throw verifyError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOTP verified, now update password
|
// TOTP verified, now update password
|
||||||
await updatePasswordWithNonce(newPassword, nonce);
|
await updatePasswordWithNonce(newPassword, nonce);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error('MFA verification failed', {
|
|
||||||
userId,
|
|
||||||
action: 'password_change_mfa',
|
|
||||||
error: getErrorMessage(error)
|
|
||||||
});
|
|
||||||
|
|
||||||
handleError(
|
handleError(
|
||||||
new AppError(
|
new AppError(
|
||||||
getErrorMessage(error) || 'Invalid authentication code',
|
getErrorMessage(error) || 'Invalid authentication code',
|
||||||
@@ -325,10 +289,10 @@ export function PasswordUpdateDialog({ open, onOpenChange, onSuccess }: Password
|
|||||||
user.id
|
user.id
|
||||||
);
|
);
|
||||||
} catch (notifError) {
|
} catch (notifError) {
|
||||||
logger.error('Failed to send password change notification', {
|
handleNonCriticalError(notifError, {
|
||||||
|
action: 'Send password change notification',
|
||||||
userId: user!.id,
|
userId: user!.id,
|
||||||
action: 'password_change_notification',
|
metadata: { context: 'post_password_change' }
|
||||||
error: getErrorMessage(notifError)
|
|
||||||
});
|
});
|
||||||
// Don't fail the password update if notification fails
|
// Don't fail the password update if notification fails
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user