This commit is contained in:
2025-10-28 00:09:46 +07:00
parent 9ebe7c2919
commit de49f564b1
110 changed files with 15392 additions and 3996 deletions

380
lib/features/auth/README.md Normal file
View File

@@ -0,0 +1,380 @@
# Authentication Feature
Complete authentication implementation following clean architecture principles for the warehouse management app.
## Architecture Overview
```
auth/
├── data/ # Data layer
│ ├── datasources/ # API and local data sources
│ │ └── auth_remote_datasource.dart
│ ├── models/ # Data transfer objects
│ │ ├── login_request_model.dart
│ │ └── user_model.dart
│ ├── repositories/ # Repository implementations
│ │ └── auth_repository_impl.dart
│ └── data.dart # Barrel export
├── domain/ # Domain layer (business logic)
│ ├── entities/ # Business entities
│ │ └── user_entity.dart
│ ├── repositories/ # Repository interfaces
│ │ └── auth_repository.dart
│ ├── usecases/ # Use cases
│ │ └── login_usecase.dart
│ └── domain.dart # Barrel export
├── presentation/ # Presentation layer (UI)
│ ├── pages/ # Screen widgets
│ │ └── login_page.dart
│ ├── providers/ # State management
│ │ └── auth_provider.dart
│ ├── widgets/ # Reusable widgets
│ │ └── login_form.dart
│ └── presentation.dart # Barrel export
├── di/ # Dependency injection
│ └── auth_dependency_injection.dart
├── auth.dart # Main barrel export
└── README.md # This file
```
## Features
### Implemented
- ✅ User login with username/password
- ✅ Token storage in secure storage
- ✅ Authentication state management
- ✅ Form validation
- ✅ Error handling with user-friendly messages
- ✅ Loading states
- ✅ Auto-navigation after successful login
- ✅ Check authentication status on app start
- ✅ Logout functionality
- ✅ Token refresh (prepared for future use)
### Pending
- ⏳ Integration with actual API endpoints
- ⏳ Biometric authentication
- ⏳ Remember me functionality
- ⏳ Password recovery
## Data Flow
### Login Flow
```
1. User enters credentials in LoginPage
2. LoginForm validates input
3. AuthNotifier.login() is called
4. LoginUseCase validates and processes request
5. AuthRepository calls AuthRemoteDataSource
6. API response is converted to UserModel
7. Tokens saved to SecureStorage
8. AuthState updated to authenticated
9. Navigation to warehouses page
```
### Logout Flow
```
1. User triggers logout
2. AuthNotifier.logout() is called
3. LogoutUseCase calls AuthRepository
4. API logout call (optional, can fail)
5. SecureStorage cleared
6. AuthState reset to initial
7. Navigation to login page
```
## Usage
### Basic Import
```dart
import 'package:minhthu/features/auth/auth.dart';
```
### Using in UI
```dart
// In a ConsumerWidget or ConsumerStatefulWidget
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// Watch auth state
final authState = ref.watch(authProvider);
// Check authentication
if (authState.isAuthenticated) {
return AuthenticatedView(user: authState.user!);
}
// Handle loading
if (authState.isLoading) {
return LoadingIndicator();
}
// Show error
if (authState.error != null) {
return ErrorView(message: authState.error!);
}
return LoginView();
}
}
```
### Perform Login
```dart
// In your widget
void handleLogin(String username, String password) {
ref.read(authProvider.notifier).login(username, password);
}
```
### Perform Logout
```dart
void handleLogout() {
ref.read(authProvider.notifier).logout();
}
```
### Check Auth Status
```dart
void checkIfAuthenticated() async {
await ref.read(authProvider.notifier).checkAuthStatus();
}
```
### Listen to Auth Changes
```dart
ref.listen(authProvider, (previous, next) {
if (next.isAuthenticated) {
// Navigate to home
context.go('/home');
} else if (next.error != null) {
// Show error snackbar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(next.error!)),
);
}
});
```
## API Integration
### Expected API Response Format
```json
{
"Value": {
"userId": "string",
"username": "string",
"accessToken": "string",
"refreshToken": "string"
},
"IsSuccess": true,
"IsFailure": false,
"Errors": [],
"ErrorCodes": []
}
```
### Login Request
```json
POST /api/v1/auth/login
{
"username": "string",
"password": "string"
}
```
### Logout Request
```json
POST /api/v1/auth/logout
Authorization: Bearer {accessToken}
```
### Refresh Token Request
```json
POST /api/v1/auth/refresh
{
"refreshToken": "string"
}
```
## State Management
### AuthState
```dart
class AuthState {
final UserEntity? user; // Current user or null
final bool isAuthenticated; // Authentication status
final bool isLoading; // Loading indicator
final String? error; // Error message
}
```
### State Transitions
```
Initial State → Loading → Authenticated (success)
→ Error (failure)
```
## Testing
### Unit Tests (TODO)
```dart
// Test use cases
test('login with valid credentials returns user', () async {
// Arrange
final useCase = LoginUseCase(mockRepository);
final request = LoginRequestModel(
username: 'testuser',
password: 'password123',
);
// Act
final result = await useCase(request);
// Assert
expect(result.isRight(), true);
});
// Test repository
test('repository saves tokens on successful login', () async {
// Test implementation
});
```
### Widget Tests (TODO)
```dart
testWidgets('login page shows form fields', (tester) async {
await tester.pumpWidget(
ProviderScope(
child: MaterialApp(home: LoginPage()),
),
);
expect(find.byType(TextField), findsNWidgets(2));
expect(find.text('Username'), findsOneWidget);
expect(find.text('Password'), findsOneWidget);
});
```
## Error Handling
### Validation Errors
- Empty username/password
- Username too short (< 3 characters)
- Password too short (< 6 characters)
### Network Errors
- Connection timeout
- No internet connection
- Server unreachable
### Authentication Errors
- Invalid credentials
- Account locked
- Token expired
### Display Errors
All errors are displayed in a user-friendly format in the UI with appropriate styling.
## Security Considerations
### Implemented
- Tokens stored in secure storage (encrypted)
- Password field obscured
- Auth token added to API headers automatically
- Token cleared on logout
- No sensitive data logged
### Best Practices
- Never log passwords or tokens
- Use HTTPS for all API calls
- Implement token refresh before expiration
- Clear sensitive data on logout
- Validate all user input
## Dependencies
### Core Dependencies
- `flutter_riverpod` - State management
- `dartz` - Functional programming (Either type)
- `flutter_secure_storage` - Secure token storage
- `dio` - HTTP client (via ApiClient)
- `equatable` - Value equality
- `go_router` - Navigation
### Internal Dependencies
- `core/network/api_client.dart` - HTTP client wrapper
- `core/storage/secure_storage.dart` - Secure storage wrapper
- `core/errors/failures.dart` - Error types
- `core/errors/exceptions.dart` - Exception types
- `core/widgets/custom_button.dart` - Button widget
- `core/widgets/loading_indicator.dart` - Loading widget
## Troubleshooting
### Common Issues
**Issue: Login always fails**
- Check API endpoint configuration in `api_endpoints.dart`
- Verify API is running and accessible
- Check network connectivity
- Verify request/response format matches API
**Issue: Tokens not persisted**
- Verify secure storage is initialized
- Check device storage permissions
- Clear app data and try again
**Issue: Navigation doesn't work after login**
- Verify router configuration includes `/warehouses` route
- Check if listener in LoginPage is properly set up
- Ensure ProviderScope wraps the app
**Issue: State not updating in UI**
- Ensure using ConsumerWidget or ConsumerStatefulWidget
- Verify provider is being watched, not just read
- Check if state is properly copied in copyWith
## Future Enhancements
### Planned Features
1. **Biometric Authentication**
- Face ID / Touch ID support
- Fallback to password
2. **Token Auto-Refresh**
- Background token refresh
- Seamless reauthentication
3. **Multi-factor Authentication**
- OTP support
- SMS verification
4. **Remember Me**
- Optional persistent login
- Secure device storage
5. **Password Reset**
- Email-based reset flow
- Security questions
## Contributing
When modifying this feature:
1. Follow clean architecture principles
2. Maintain separation of concerns (data/domain/presentation)
3. Add tests for new functionality
4. Update this README with changes
5. Follow existing code style and patterns
## Related Files
- App Router: `lib/core/routing/app_router.dart`
- API Endpoints: `lib/core/constants/api_endpoints.dart`
- App Theme: `lib/core/theme/app_theme.dart`
- Main App: `lib/main.dart`