Rustelo/info/auth_error_handling.md

289 lines
9.2 KiB
Markdown
Raw Normal View History

# Authentication Error Handling with Internationalization
This document describes the enhanced authentication error handling system that provides localized error messages based on the current language setting.
## Overview
The authentication context has been updated to handle error messages in multiple languages, providing a better user experience for international users. The system includes:
1. **Comprehensive Error Mapping**: Server errors are mapped to appropriate translation keys
2. **Internationalized Error Messages**: All error messages are displayed in the user's current language
3. **Consistent Error Handling**: Standardized error handling across all authentication operations
4. **Reusable Components**: Pre-built components for displaying errors in different formats
## Features
### 1. Automatic Error Translation
The system automatically translates server error responses into the user's current language:
```rust
// Before (hardcoded English)
s.error = Some("Login failed".to_string());
// After (internationalized)
s.error = Some(error_handler.handle_request_failure("login"));
```
### 2. Smart Error Mapping
Server responses are intelligently mapped to appropriate translation keys:
- JSON API responses are parsed and mapped
- Common error patterns are recognized
- Fallback to generic error messages when specific mapping isn't available
### 3. Comprehensive Error Coverage
The system handles all types of authentication errors:
- **Invalid Credentials**: Wrong username/password
- **Token Errors**: Expired or invalid tokens
- **Account Issues**: Suspended or unverified accounts
- **Network Errors**: Connection problems
- **Server Errors**: Internal server errors
- **Validation Errors**: Input validation failures
## Available Error Messages
### English (en.ftl)
```
invalid-credentials = Invalid email or password
user-not-found = User not found
email-already-exists = An account with this email already exists
username-already-exists = This username is already taken
invalid-token = Invalid authentication token
token-expired = Your authentication token has expired
insufficient-permissions = You don't have permission to perform this action
account-not-verified = Please verify your email before signing in
account-suspended = Your account has been suspended
rate-limit-exceeded = Too many attempts. Please try again later
oauth-error = OAuth authentication error
database-error = A database error occurred. Please try again
internal-error = An internal error occurred. Please try again
validation-error = Please check your input and try again
network-error = Network error. Please check your connection
login-failed = Login failed
registration-failed = Registration failed
session-expired = Your session has expired. Please sign in again
profile-update-failed = Failed to update profile
password-change-failed = Failed to change password
server-error = Server error occurred. Please try again later
request-failed = Request failed. Please try again
unknown-error = An unknown error occurred
```
### Spanish (es.ftl)
```
invalid-credentials = Correo electrónico o contraseña inválidos
user-not-found = Usuario no encontrado
email-already-exists = Ya existe una cuenta con este correo electrónico
username-already-exists = Este nombre de usuario ya está en uso
invalid-token = Token de autenticación inválido
token-expired = Tu token de autenticación ha expirado
insufficient-permissions = No tienes permisos para realizar esta acción
account-not-verified = Por favor verifica tu correo electrónico antes de iniciar sesión
account-suspended = Tu cuenta ha sido suspendida
rate-limit-exceeded = Demasiados intentos. Por favor intenta de nuevo más tarde
oauth-error = Error de autenticación OAuth
database-error = Ocurrió un error en la base de datos. Por favor intenta de nuevo
internal-error = Ocurrió un error interno. Por favor intenta de nuevo
validation-error = Por favor revisa tu información e intenta de nuevo
network-error = Error de red. Por favor verifica tu conexión
login-failed = Error al iniciar sesión
registration-failed = Error en el registro
session-expired = Tu sesión ha expirado. Por favor inicia sesión de nuevo
profile-update-failed = Error al actualizar el perfil
password-change-failed = Error al cambiar la contraseña
server-error = Error del servidor. Por favor intenta más tarde
request-failed = La solicitud falló. Por favor intenta de nuevo
unknown-error = Ocurrió un error desconocido
```
## Usage
### 1. Basic Error Handling
The authentication context automatically handles errors with localization:
```rust
use crate::auth::use_auth;
#[component]
pub fn LoginComponent() -> impl IntoView {
let auth = use_auth();
view! {
<div>
// Error will be displayed in the current language
<Show when=move || auth.error().is_some()>
<div class="error">
{move || auth.error().unwrap_or_default()}
</div>
</Show>
</div>
}
}
```
### 2. Using Error Display Components
Pre-built components are available for common error display patterns:
```rust
use crate::auth::{AuthErrorDisplay, AuthErrorToast, InlineAuthError};
#[component]
pub fn MyComponent() -> impl IntoView {
let auth = use_auth();
view! {
<div>
// Alert-style error display
<AuthErrorDisplay
error=move || auth.error()
on_dismiss=Callback::new(move |_| {
auth.actions.clear_error();
})
/>
// Toast notification
<Show when=move || auth.error().is_some()>
<AuthErrorToast
error=move || auth.error().unwrap_or_default()
duration=5000
/>
</Show>
// Inline error display
<Show when=move || auth.error().is_some()>
<InlineAuthError
error=move || auth.error().unwrap_or_default()
/>
</Show>
</div>
}
}
```
### 3. Custom Error Handling
You can use the error handling utilities directly:
```rust
use crate::auth::errors::{AuthErrorHandler, AuthErrorHandling};
use crate::i18n::use_i18n;
#[component]
pub fn CustomErrorHandling() -> impl IntoView {
let i18n = use_i18n();
let error_handler = AuthErrorHandler::new(i18n.clone());
// Handle a specific error
let error_message = error_handler.handle_request_failure("login");
// Or use the trait extension
let network_error = i18n.handle_network_error();
view! {
<div>
<p>{error_message}</p>
<p>{network_error}</p>
</div>
}
}
```
## Error Display Components
### AuthErrorDisplay
A full-featured error display component with dismiss functionality:
- Shows error with icon and styling
- Optional dismiss button
- Customizable CSS classes
- Callback when dismissed
### AuthErrorToast
A toast notification for non-blocking error display:
- Auto-dismisses after specified duration
- Positioned fixed in top-right corner
- Manual dismiss option
- Smooth animations
### InlineAuthError
A compact error display for inline use:
- Minimal styling
- Icon with text
- Suitable for form validation errors
## Implementation Details
### Error Mapping Logic
The `AuthErrorHandler` processes server errors in the following order:
1. **JSON Parsing**: Attempts to parse response as JSON and extract error messages
2. **Pattern Matching**: Matches error text against known patterns
3. **Fallback**: Uses generic error message if no specific match found
### Session Management
The system automatically handles session expiration:
- Detects expired tokens
- Clears user session
- Shows appropriate localized message
- Redirects to login when necessary
### Network Error Handling
Network errors are consistently handled across all operations:
- Connection timeouts
- Network unavailability
- Server unreachable
- DNS resolution failures
## Best Practices
1. **Always Clear Errors**: Use `auth.actions.clear_error()` when appropriate
2. **Provide User Feedback**: Show loading states during operations
3. **Handle Edge Cases**: Plan for unexpected error scenarios
4. **Test Multiple Languages**: Verify translations work correctly
5. **Use Appropriate Display**: Choose the right error display component for your use case
## Adding New Error Messages
To add new error messages:
1. Add the translation key to both `en.ftl` and `es.ftl`
2. Update the error mapping logic in `AuthErrorHandler`
3. Handle the new error type in your components
Example:
```rust
// In errors.rs
msg if msg.contains("two-factor required") => "two-factor-required".to_string(),
```
```
# In en.ftl
two-factor-required = Two-factor authentication is required
# In es.ftl
two-factor-required = Se requiere autenticación de dos factores
```
## Migration from Previous Version
If you're upgrading from a previous version:
1. Replace hardcoded error messages with translation keys
2. Update error handling in components to use new utilities
3. Test with different language settings
4. Update any custom error handling logic
The new system is backward compatible, but you'll need to update your components to take advantage of the internationalization features.