Authentication Repositories
Repositories provide an abstraction layer for data operations, implementing the Repository pattern from Clean Architecture. They coordinate between data sources and use cases.
AuthRepository (Interface)
Defines the contract for authentication data operations.
Location: lib/feature/auth/core/repositories/auth_repository.dart:6
Methods
Either<Failure, Map<String, dynamic>>
Returns registration response data on success, or a failure on error
Registers a new user in the system. Future < Either < Failure , Map < String , dynamic >>> registerUser (
String username,
String email,
String phone,
String password,
);
Returns authentication token on success, or a failure on error
Authenticates a user and returns an authentication token. Future < Either < Failure , String >> login ( String email, String password);
Returns success or failure
Logs out the current user and clears stored tokens. Future < Either < Failure , void >> logout ();
Returns the authenticated user if a valid session exists, null if not authenticated, or a failure on error
Checks the current authentication status and retrieves the authenticated user. Future < Either < Failure , User ?>> checkAuthStatus ();
Returns the user associated with the token, or a failure on error
Retrieves user information from an authentication token. Future < Either < Failure , User >> getUserFromToken ( String token);
Geographic location of the apiary
Number of beehives in the apiary
Whether treatments are applied
Returns success or failure
Creates a new apiary during the user onboarding process. Future < Either < Failure , void >> createApiary (
String userId,
String apiaryName,
String location,
int beehivesCount,
bool treatments,
String token,
);
AuthRepositoryImpl
Concrete implementation of AuthRepository that coordinates between remote and local data sources.
Location: lib/feature/auth/data/repositories/auth_repository_impl.dart:11
Constructor
remoteDataSource
AuthRemoteDataSource
required
Handles remote API calls
localDataSource
AuthLocalDataSource
required
Handles local storage operations (tokens, user data)
AuthRepositoryImpl ({
required AuthRemoteDataSource remoteDataSource,
required AuthLocalDataSource localDataSource,
});
Implementation Details
Show registerUser Implementation
Calls the remote data source to register a new user. @override
Future < Either < Failure , Map < String , dynamic >>> registerUser (
String username,
String email,
String phone,
String password,
) async {
try {
final result = await remoteDataSource. registerUser (
username,
email,
phone,
password,
);
return Right (result);
} catch (e) {
return Left ( ServerFailure (e. toString ()));
}
}
Error Handling: Catches exceptions and returns ServerFailure
Show login Implementation
Authenticates with remote API and stores the token locally. @override
Future < Either < Failure , String >> login ( String email, String password) async {
try {
final token = await remoteDataSource. login (email, password);
await localDataSource. saveToken (token);
return Right (token);
} catch (e) {
return const Left ( ServerFailure ( 'Error al iniciar sesión' ));
}
}
Flow:
Calls remote API to authenticate
Saves token to local storage on success
Returns token to caller
Error Handling: Returns ServerFailure with localized error message
Show checkAuthStatus Implementation
Checks local token and validates it with the remote API. @override
Future < Either < Failure , User ?>> checkAuthStatus () async {
try {
final token = await localDataSource. getToken ();
if (token == null ) {
return const Right ( null );
}
final user = await remoteDataSource. getUserFromToken (token);
return Right (user);
} catch (e) {
await localDataSource. deleteToken ();
await localDataSource. deleteUser ();
return const Left ( AuthFailure ( 'Session expired. Please log in again.' ));
}
}
Flow:
Retrieves token from local storage
Returns null if no token exists
Validates token with remote API
Returns user if token is valid
Clears local data if token is invalid/expired
Error Handling: Cleans up local storage and returns AuthFailure for expired sessions
Show logout Implementation
Logs out from remote API and clears local storage. @override
Future < Either < Failure , void >> logout () async {
try {
await remoteDataSource. logout ();
await localDataSource. deleteToken ();
await localDataSource. deleteUser ();
return const Right ( null );
} catch (e) {
return const Left ( ServerFailure ( 'Error during logout' ));
}
}
Flow:
Calls remote API to invalidate session
Deletes stored token
Deletes stored user data
Error Handling: Returns ServerFailure if logout fails
Show getUserFromToken Implementation
Retrieves user information from a token via remote API. @override
Future < Either < Failure , User >> getUserFromToken ( String token) async {
try {
final user = await remoteDataSource. getUserFromToken (token);
return Right (user);
} catch (e) {
return const Left ( ServerFailure ( 'Error al obtener usuario del token' ));
}
}
Error Handling: Returns ServerFailure with localized error message
Show createApiary Implementation
Creates a new apiary via remote API during onboarding. @override
Future < Either < Failure , void >> createApiary (
String userId,
String apiaryName,
String location,
int beehivesCount,
bool treatments,
String token,
) async {
try {
await remoteDataSource. createApiary (
userId,
apiaryName,
location,
beehivesCount,
treatments,
token,
);
return const Right ( null );
} catch (e) {
return Left ( ServerFailure (e. toString ()));
}
}
Error Handling: Catches exceptions and returns ServerFailure with error details
Usage Example
// Dependency injection setup
final remoteDataSource = AuthRemoteDataSourceImpl (client : httpClient);
final localDataSource = AuthLocalDataSourceImpl (storage : secureStorage);
final authRepository = AuthRepositoryImpl (
remoteDataSource : remoteDataSource,
localDataSource : localDataSource,
);
// Using the repository
final result = await authRepository. login (
'[email protected] ' ,
'password123' ,
);
result. fold (
(failure) => print ( 'Login failed: ${ failure . message } ' ),
(token) => print ( 'Login successful: $ token ' ),
);
Data Sources
The repository implementation depends on two data sources:
AuthRemoteDataSource
Location: lib/feature/auth/data/datasources/auth_remote_datasource.dart
Handles all remote API calls for authentication operations.
AuthLocalDataSource
Location: lib/feature/auth/data/datasources/auth_local_datasource.dart
Handles local storage operations for:
Authentication tokens
User data caching
Session persistence
Architecture Notes
Separation of Concerns: The repository coordinates between remote API calls and local storage
Error Handling: All methods use the Either type for functional error handling
Token Management: Tokens are automatically stored locally after successful login
Session Cleanup: Failed authentication checks trigger automatic cleanup of local data
Type Safety: Strong typing ensures compile-time safety for all operations