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

View File

@@ -0,0 +1,134 @@
import 'package:dartz/dartz.dart';
import '../../../../core/errors/exceptions.dart';
import '../../../../core/errors/failures.dart';
import '../../../../core/storage/secure_storage.dart';
import '../../domain/entities/user_entity.dart';
import '../../domain/repositories/auth_repository.dart';
import '../datasources/auth_remote_datasource.dart';
import '../models/login_request_model.dart';
/// Implementation of AuthRepository
///
/// Coordinates between remote data source and local storage
/// Handles error conversion from exceptions to failures
class AuthRepositoryImpl implements AuthRepository {
final AuthRemoteDataSource remoteDataSource;
final SecureStorage secureStorage;
AuthRepositoryImpl({
required this.remoteDataSource,
required this.secureStorage,
});
@override
Future<Either<Failure, UserEntity>> login(LoginRequestModel request) async {
try {
// Call remote data source to login
final userModel = await remoteDataSource.login(request);
// Save tokens to secure storage
await secureStorage.saveAccessToken(userModel.accessToken);
await secureStorage.saveUserId(userModel.userId);
await secureStorage.saveUsername(userModel.username);
if (userModel.refreshToken != null) {
await secureStorage.saveRefreshToken(userModel.refreshToken!);
}
// Return user entity
return Right(userModel.toEntity());
} on ServerException catch (e) {
return Left(AuthenticationFailure(e.message));
} on NetworkException catch (e) {
return Left(NetworkFailure(e.message));
} catch (e) {
return Left(UnknownFailure('Login failed: ${e.toString()}'));
}
}
@override
Future<Either<Failure, void>> logout() async {
try {
// Call remote data source to logout (optional - can fail silently)
try {
await remoteDataSource.logout();
} catch (e) {
// Ignore remote logout errors, still clear local data
}
// Clear all local authentication data
await secureStorage.clearAll();
return const Right(null);
} catch (e) {
return Left(UnknownFailure('Logout failed: ${e.toString()}'));
}
}
@override
Future<Either<Failure, UserEntity>> refreshToken(String refreshToken) async {
try {
// Call remote data source to refresh token
final userModel = await remoteDataSource.refreshToken(refreshToken);
// Update tokens in secure storage
await secureStorage.saveAccessToken(userModel.accessToken);
if (userModel.refreshToken != null) {
await secureStorage.saveRefreshToken(userModel.refreshToken!);
}
return Right(userModel.toEntity());
} on ServerException catch (e) {
return Left(AuthenticationFailure(e.message));
} on NetworkException catch (e) {
return Left(NetworkFailure(e.message));
} catch (e) {
return Left(UnknownFailure('Token refresh failed: ${e.toString()}'));
}
}
@override
Future<bool> isAuthenticated() async {
try {
return await secureStorage.isAuthenticated();
} catch (e) {
return false;
}
}
@override
Future<Either<Failure, UserEntity>> getCurrentUser() async {
try {
final userId = await secureStorage.getUserId();
final username = await secureStorage.getUsername();
final accessToken = await secureStorage.getAccessToken();
final refreshToken = await secureStorage.getRefreshToken();
if (userId == null || username == null || accessToken == null) {
return const Left(AuthenticationFailure('No user data found'));
}
final user = UserEntity(
userId: userId,
username: username,
accessToken: accessToken,
refreshToken: refreshToken,
);
return Right(user);
} catch (e) {
return Left(CacheFailure('Failed to get user data: ${e.toString()}'));
}
}
@override
Future<Either<Failure, void>> clearAuthData() async {
try {
await secureStorage.clearAll();
return const Right(null);
} catch (e) {
return Left(CacheFailure('Failed to clear auth data: ${e.toString()}'));
}
}
}