mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 14:31:12 -05:00
126 lines
3.1 KiB
TypeScript
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;
|
|
}
|