148 lines
4.3 KiB
Dart
148 lines
4.3 KiB
Dart
import '../../../../core/constants/api_endpoints.dart';
|
|
import '../../../../core/errors/exceptions.dart';
|
|
import '../../../../core/network/api_client.dart';
|
|
import '../../../../core/network/api_response.dart';
|
|
import '../models/login_request_model.dart';
|
|
import '../models/user_model.dart';
|
|
|
|
/// Abstract interface for authentication remote data source
|
|
///
|
|
/// Defines the contract for authentication-related API operations
|
|
abstract class AuthRemoteDataSource {
|
|
/// Login with username and password
|
|
///
|
|
/// Throws [ServerException] if the login fails
|
|
/// Returns [UserModel] on successful login
|
|
Future<UserModel> login(LoginRequestModel request);
|
|
|
|
/// Logout current user
|
|
///
|
|
/// Throws [ServerException] if logout fails
|
|
Future<void> logout();
|
|
|
|
/// Refresh access token using refresh token
|
|
///
|
|
/// Throws [ServerException] if refresh fails
|
|
/// Returns new [UserModel] with updated tokens
|
|
Future<UserModel> refreshToken(String refreshToken);
|
|
}
|
|
|
|
/// Implementation of AuthRemoteDataSource using ApiClient
|
|
///
|
|
/// Handles all authentication-related API calls
|
|
class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
|
final ApiClient apiClient;
|
|
|
|
AuthRemoteDataSourceImpl(this.apiClient);
|
|
|
|
@override
|
|
Future<UserModel> login(LoginRequestModel request) async {
|
|
try {
|
|
// Make POST request to login endpoint
|
|
final response = await apiClient.post(
|
|
ApiEndpoints.login,
|
|
data: request.toJson(),
|
|
);
|
|
|
|
// Parse API response with ApiResponse wrapper
|
|
final apiResponse = ApiResponse.fromJson(
|
|
response.data as Map<String, dynamic>,
|
|
(json) => UserModel.fromJson(
|
|
json as Map<String, dynamic>,
|
|
username: request.username, // Pass username since API doesn't return it
|
|
),
|
|
);
|
|
|
|
// Check if login was successful
|
|
if (apiResponse.isSuccess && apiResponse.value != null) {
|
|
return apiResponse.value!;
|
|
} else {
|
|
// Extract error message from API response
|
|
final errorMessage = apiResponse.errors.isNotEmpty
|
|
? apiResponse.errors.first
|
|
: 'Login failed';
|
|
|
|
throw ServerException(
|
|
errorMessage,
|
|
code: apiResponse.errorCodes.isNotEmpty
|
|
? apiResponse.errorCodes.first
|
|
: null,
|
|
);
|
|
}
|
|
} on ServerException {
|
|
rethrow;
|
|
} catch (e) {
|
|
throw ServerException('Failed to login: ${e.toString()}');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> logout() async {
|
|
try {
|
|
// Make POST request to logout endpoint
|
|
final response = await apiClient.post(ApiEndpoints.logout);
|
|
|
|
// Parse API response
|
|
final apiResponse = ApiResponse.fromJson(
|
|
response.data as Map<String, dynamic>,
|
|
null,
|
|
);
|
|
|
|
// Check if logout was successful
|
|
if (!apiResponse.isSuccess) {
|
|
final errorMessage = apiResponse.errors.isNotEmpty
|
|
? apiResponse.errors.first
|
|
: 'Logout failed';
|
|
|
|
throw ServerException(
|
|
errorMessage,
|
|
code: apiResponse.errorCodes.isNotEmpty
|
|
? apiResponse.errorCodes.first
|
|
: null,
|
|
);
|
|
}
|
|
} on ServerException {
|
|
rethrow;
|
|
} catch (e) {
|
|
throw ServerException('Failed to logout: ${e.toString()}');
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<UserModel> refreshToken(String refreshToken) async {
|
|
try {
|
|
// Make POST request to refresh token endpoint
|
|
final response = await apiClient.post(
|
|
ApiEndpoints.refreshToken,
|
|
data: {'refreshToken': refreshToken},
|
|
);
|
|
|
|
// Parse API response
|
|
final apiResponse = ApiResponse.fromJson(
|
|
response.data as Map<String, dynamic>,
|
|
(json) => UserModel.fromJson(json as Map<String, dynamic>),
|
|
);
|
|
|
|
// Check if refresh was successful
|
|
if (apiResponse.isSuccess && apiResponse.value != null) {
|
|
return apiResponse.value!;
|
|
} else {
|
|
final errorMessage = apiResponse.errors.isNotEmpty
|
|
? apiResponse.errors.first
|
|
: 'Token refresh failed';
|
|
|
|
throw ServerException(
|
|
errorMessage,
|
|
code: apiResponse.errorCodes.isNotEmpty
|
|
? apiResponse.errorCodes.first
|
|
: null,
|
|
);
|
|
}
|
|
} on ServerException {
|
|
rethrow;
|
|
} catch (e) {
|
|
throw ServerException('Failed to refresh token: ${e.toString()}');
|
|
}
|
|
}
|
|
}
|