Files
thrilltrack-explorer/src-old/lib/aalErrorDetection.ts

126 lines
3.1 KiB
TypeScript

/**
* AAL2 Error Detection Utilities
*
* Detects when operations fail due to AAL2/MFA requirements
* and provides user-friendly error messages
*/
import { PostgrestError } from '@supabase/supabase-js';
/**
* Check if an error is due to AAL2/RLS policy failure
*/
export function isAAL2PolicyError(error: unknown): boolean {
if (!error) return false;
// Handle Supabase PostgrestError
if (isPostgrestError(error)) {
const code = error.code;
const message = error.message?.toLowerCase() || '';
const details = error.details?.toLowerCase() || '';
// Check for RLS policy violations
if (code === 'PGRST301' || code === '42501') {
return true;
}
// Check for permission denied messages
if (
message.includes('permission denied') ||
message.includes('row-level security') ||
message.includes('policy') ||
details.includes('policy')
) {
return true;
}
}
// Handle generic errors with 403 status
if (hasStatusCode(error) && error.status === 403) {
return true;
}
// Handle error messages
if (error instanceof Error) {
const message = error.message.toLowerCase();
return (
message.includes('row-level security') ||
message.includes('permission denied') ||
message.includes('policy') ||
message.includes('403')
);
}
return false;
}
/**
* Get user-friendly error message for AAL2 errors
*/
export function getAAL2ErrorMessage(error: unknown): string {
// Default message
const defaultMessage = 'This action requires additional security verification';
if (!error) return defaultMessage;
// Check if error mentions specific operations
if (error instanceof Error) {
const message = error.message.toLowerCase();
if (message.includes('delete') || message.includes('remove')) {
return 'Deleting this data requires additional security verification';
}
if (message.includes('update') || message.includes('modify')) {
return 'Modifying this data requires additional security verification';
}
if (message.includes('insert') || message.includes('create')) {
return 'Creating this data requires additional security verification';
}
}
return defaultMessage;
}
/**
* Type guard for PostgrestError
*/
function isPostgrestError(error: unknown): error is PostgrestError {
return (
typeof error === 'object' &&
error !== null &&
'code' in error &&
'message' in error
);
}
/**
* Type guard for errors with status code
*/
function hasStatusCode(error: unknown): error is { status: number } {
return (
typeof error === 'object' &&
error !== null &&
'status' in error &&
typeof (error as any).status === 'number'
);
}
/**
* Create a user-cancellation error
*/
export class MFACancelledError extends Error {
constructor() {
super('MFA verification was cancelled by user');
this.name = 'MFACancelledError';
}
}
/**
* Check if error is a user cancellation
*/
export function isMFACancelledError(error: unknown): boolean {
return error instanceof MFACancelledError;
}