from __future__ import annotations from typing import List, Literal, Optional from typing_extensions import TypedDict ErrorCode = Literal[ "unexpected_failure", "validation_failed", "bad_json", "email_exists", "phone_exists", "bad_jwt", "not_admin", "no_authorization", "user_not_found", "session_not_found", "flow_state_not_found", "flow_state_expired", "signup_disabled", "user_banned", "provider_email_needs_verification", "invite_not_found", "bad_oauth_state", "bad_oauth_callback", "oauth_provider_not_supported", "unexpected_audience", "single_identity_not_deletable", "email_conflict_identity_not_deletable", "identity_already_exists", "email_provider_disabled", "phone_provider_disabled", "too_many_enrolled_mfa_factors", "mfa_factor_name_conflict", "mfa_factor_not_found", "mfa_ip_address_mismatch", "mfa_challenge_expired", "mfa_verification_failed", "mfa_verification_rejected", "insufficient_aal", "captcha_failed", "saml_provider_disabled", "manual_linking_disabled", "sms_send_failed", "email_not_confirmed", "phone_not_confirmed", "reauth_nonce_missing", "saml_relay_state_not_found", "saml_relay_state_expired", "saml_idp_not_found", "saml_assertion_no_user_id", "saml_assertion_no_email", "user_already_exists", "sso_provider_not_found", "saml_metadata_fetch_failed", "saml_idp_already_exists", "sso_domain_already_exists", "saml_entity_id_mismatch", "conflict", "provider_disabled", "user_sso_managed", "reauthentication_needed", "same_password", "reauthentication_not_valid", "otp_expired", "otp_disabled", "identity_not_found", "weak_password", "over_request_rate_limit", "over_email_send_rate_limit", "over_sms_send_rate_limit", "bad_code_verifier", "anonymous_provider_disabled", "hook_timeout", "hook_timeout_after_retry", "hook_payload_over_size_limit", "hook_payload_invalid_content_type", "request_timeout", "mfa_phone_enroll_not_enabled", "mfa_phone_verify_not_enabled", "mfa_totp_enroll_not_enabled", "mfa_totp_verify_not_enabled", "mfa_webauthn_enroll_not_enabled", "mfa_webauthn_verify_not_enabled", "mfa_verified_factor_exists", "invalid_credentials", "email_address_not_authorized", "email_address_invalid", ] class AuthError(Exception): def __init__(self, message: str, code: ErrorCode) -> None: Exception.__init__(self, message) self.message = message self.name = "AuthError" self.code = code class AuthApiErrorDict(TypedDict): name: str message: str status: int code: ErrorCode class AuthApiError(AuthError): def __init__(self, message: str, status: int, code: ErrorCode) -> None: AuthError.__init__(self, message, code) self.name = "AuthApiError" self.status = status self.code = code def to_dict(self) -> AuthApiErrorDict: return { "name": self.name, "message": self.message, "status": self.status, "code": self.code, } class AuthUnknownError(AuthError): def __init__(self, message: str, original_error: Exception) -> None: AuthError.__init__(self, message, None) self.name = "AuthUnknownError" self.original_error = original_error class CustomAuthError(AuthError): def __init__(self, message: str, name: str, status: int, code: ErrorCode) -> None: AuthError.__init__(self, message, code) self.name = name self.status = status def to_dict(self) -> AuthApiErrorDict: return { "name": self.name, "message": self.message, "status": self.status, } class AuthSessionMissingError(CustomAuthError): def __init__(self) -> None: CustomAuthError.__init__( self, "Auth session missing!", "AuthSessionMissingError", 400, None, ) class AuthInvalidCredentialsError(CustomAuthError): def __init__(self, message: str) -> None: CustomAuthError.__init__( self, message, "AuthInvalidCredentialsError", 400, None, ) class AuthImplicitGrantRedirectErrorDetails(TypedDict): error: str code: str class AuthImplicitGrantRedirectErrorDict(AuthApiErrorDict): details: Optional[AuthImplicitGrantRedirectErrorDetails] class AuthImplicitGrantRedirectError(CustomAuthError): def __init__( self, message: str, details: Optional[AuthImplicitGrantRedirectErrorDetails] = None, ) -> None: CustomAuthError.__init__( self, message, "AuthImplicitGrantRedirectError", 500, None, ) self.details = details def to_dict(self) -> AuthImplicitGrantRedirectErrorDict: return { "name": self.name, "message": self.message, "status": self.status, "details": self.details, } class AuthRetryableError(CustomAuthError): def __init__(self, message: str, status: int) -> None: CustomAuthError.__init__( self, message, "AuthRetryableError", status, None, ) class AuthWeakPasswordError(CustomAuthError): def __init__(self, message: str, status: int, reasons: List[str]) -> None: CustomAuthError.__init__( self, message, "AuthWeakPasswordError", status, "weak_password", ) self.reasons = reasons def to_dict(self) -> AuthApiErrorDict: return { "name": self.name, "message": self.message, "status": self.status, "reasons": self.reasons, }