TF-196 Implement RemoteExceptionThrower when get session

This commit is contained in:
dab246
2022-06-22 11:26:43 +07:00
committed by Dat H. Pham
parent fd9b7cbb0a
commit 4cff46623c
12 changed files with 117 additions and 27 deletions
@@ -5,9 +5,20 @@ import 'package:dio/dio.dart';
class RemoteExceptionThrower { class RemoteExceptionThrower {
void throwRemoteException(dynamic exception, {Function(DioError)? handler}) { void throwRemoteException(dynamic exception, {Function(DioError)? handler}) {
if (exception is DioError) { if (exception is DioError) {
handler != null ? handler(exception) : throw UnknownError(exception.message); switch (exception.type) {
case DioErrorType.connectTimeout:
throw ConnectError();
default:
if (handler != null) {
throw handler(exception);
} else {
throw UnknownError(
code: exception.response?.statusCode,
message: exception.message);
}
}
} else { } else {
throw UnknownError(exception.toString()); throw UnknownError(message: exception.toString());
} }
} }
} }
@@ -2,14 +2,23 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
abstract class RemoteException extends Equatable implements Exception { abstract class RemoteException extends Equatable implements Exception {
static final connectError = 'Connect error';
final String? message; final String? message;
final int? code;
RemoteException(this.message); RemoteException({this.code, this.message});
} }
class UnknownError extends RemoteException { class UnknownError extends RemoteException {
UnknownError(String? message) : super(message); UnknownError({int? code, String? message}) : super(code: code, message: message);
@override
List<Object> get props => [];
}
class ConnectError extends RemoteException {
ConnectError() : super(message: RemoteException.connectError);
@override @override
List<Object> get props => []; List<Object> get props => [];
@@ -1,17 +1,26 @@
import 'package:equatable/equatable.dart';
abstract class AuthenticationException extends Equatable { import 'package:core/domain/exceptions/remote_exception.dart';
abstract class AuthenticationException extends RemoteException {
static const wrongCredential = 'Credential is wrong'; static const wrongCredential = 'Credential is wrong';
static const badGateway = 'Bad gateway';
static const invalidBaseUrl = 'Invalid base URL'; static const invalidBaseUrl = 'Invalid base URL';
const AuthenticationException(String message); AuthenticationException(String message) : super(message: message);
} }
class BadCredentials extends AuthenticationException { class BadCredentials extends AuthenticationException {
const BadCredentials() : super(AuthenticationException.wrongCredential); BadCredentials() : super(AuthenticationException.wrongCredential);
@override @override
List<Object> get props => []; List<Object?> get props => [message];
}
class BadGateway extends AuthenticationException {
BadGateway() : super(AuthenticationException.badGateway);
@override
List<Object?> get props => [message];
} }
class NotFoundAuthenticatedAccountException implements Exception { class NotFoundAuthenticatedAccountException implements Exception {
@@ -23,10 +32,10 @@ class NotFoundStoredTokenException implements Exception {
} }
class InvalidBaseUrl extends AuthenticationException { class InvalidBaseUrl extends AuthenticationException {
const InvalidBaseUrl() : super(AuthenticationException.invalidBaseUrl); InvalidBaseUrl() : super(AuthenticationException.invalidBaseUrl);
@override @override
List<Object?> get props => []; List<Object?> get props => [message];
} }
class NotFoundAccessTokenException implements Exception { class NotFoundAccessTokenException implements Exception {
@@ -20,7 +20,7 @@ class GetCredentialInteractor {
if (isCredentialValid(baseUrl)) { if (isCredentialValid(baseUrl)) {
return Right(GetCredentialViewState(baseUrl, userName, password)); return Right(GetCredentialViewState(baseUrl, userName, password));
} else { } else {
return Left(GetCredentialFailure(const BadCredentials())); return Left(GetCredentialFailure(BadCredentials()));
} }
} catch (exception) { } catch (exception) {
return Left(GetCredentialFailure(exception)); return Left(GetCredentialFailure(exception));
@@ -35,7 +35,7 @@ class GetStoredTokenOidcInteractor {
if (_isCredentialValid(baseUrl)) { if (_isCredentialValid(baseUrl)) {
yield Right(GetStoredTokenOidcSuccess(baseUrl, tokenOidc, oidcConfiguration)); yield Right(GetStoredTokenOidcSuccess(baseUrl, tokenOidc, oidcConfiguration));
} else { } else {
yield Left(GetStoredTokenOidcFailure(const InvalidBaseUrl())); yield Left(GetStoredTokenOidcFailure(InvalidBaseUrl()));
} }
} catch (e) { } catch (e) {
log('GetStoredTokenOidcInteractor::execute(): $e'); log('GetStoredTokenOidcInteractor::execute(): $e');
@@ -1,19 +1,34 @@
import 'package:core/data/network/remote_exception_thrower.dart';
import 'package:core/domain/exceptions/remote_exception.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dio/dio.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
import 'package:tmail_ui_user/features/session/data/datasource/session_datasource.dart'; import 'package:tmail_ui_user/features/session/data/datasource/session_datasource.dart';
import 'package:tmail_ui_user/features/session/data/network/session_api.dart'; import 'package:tmail_ui_user/features/session/data/network/session_api.dart';
class SessionDataSourceImpl extends SessionDataSource { class SessionDataSourceImpl extends SessionDataSource {
final SessionAPI sessionAPI; final SessionAPI _sessionAPI;
final RemoteExceptionThrower _remoteExceptionThrower;
SessionDataSourceImpl(this.sessionAPI); SessionDataSourceImpl(this._sessionAPI, this._remoteExceptionThrower);
@override @override
Future<Session> getSession() { Future<Session> getSession() {
return Future.sync(() async { return Future.sync(() async {
return await sessionAPI.getSession(); return await _sessionAPI.getSession();
}).catchError((error) { }).catchError((error) {
throw error; _remoteExceptionThrower.throwRemoteException(error, handler: (DioError error) {
if (error.response?.statusCode == 502) {
throw BadGateway();
} else {
log('SessionDataSourceImpl::getSession(): statusMessage: ${error.response?.statusMessage}');
throw UnknownError(
code: error.response?.statusCode,
message: error.response?.statusMessage);
}
});
}); });
} }
} }
@@ -1,10 +1,15 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/utils/app_toast.dart';
import 'package:core/domain/exceptions/remote_exception.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart';
import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_authority_oidc_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
import 'package:tmail_ui_user/features/session/domain/state/get_session_state.dart'; import 'package:tmail_ui_user/features/session/domain/state/get_session_state.dart';
import 'package:tmail_ui_user/features/session/domain/usecases/get_session_interactor.dart'; import 'package:tmail_ui_user/features/session/domain/usecases/get_session_interactor.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -14,6 +19,7 @@ class SessionController extends GetxController {
final CachingManager _cachingManager; final CachingManager _cachingManager;
final DeleteAuthorityOidcInteractor _deleteAuthorityOidcInteractor; final DeleteAuthorityOidcInteractor _deleteAuthorityOidcInteractor;
final AuthorizationInterceptors _authorizationInterceptors; final AuthorizationInterceptors _authorizationInterceptors;
final AppToast _appToast;
SessionController( SessionController(
this._getSessionInteractor, this._getSessionInteractor,
@@ -21,7 +27,7 @@ class SessionController extends GetxController {
this._cachingManager, this._cachingManager,
this._deleteAuthorityOidcInteractor, this._deleteAuthorityOidcInteractor,
this._authorizationInterceptors, this._authorizationInterceptors,
); this._appToast);
@override @override
void onReady() { void onReady() {
@@ -32,8 +38,32 @@ class SessionController extends GetxController {
void _getSession() async { void _getSession() async {
await _getSessionInteractor.execute() await _getSessionInteractor.execute()
.then((response) => response.fold( .then((response) => response.fold(
(failure) => _goToLogin(), (failure) {
(success) => success is GetSessionSuccess ? _goToMailboxDashBoard(success) : _goToLogin())); _handleSessionFailure(failure);
_goToLogin();
},
(success) => success is GetSessionSuccess
? _goToMailboxDashBoard(success)
: _goToLogin()));
}
void _handleSessionFailure(Failure failure) {
if (failure is GetSessionFailure) {
final sessionException = failure.exception;
if (_checkUrlError(sessionException) && currentContext != null) {
_appToast.showErrorToast(AppLocalizations.of(currentContext!).wrongUrlMessage);
} else if (sessionException is UnknownError && currentContext != null) {
if (sessionException.message != null) {
_appToast.showErrorToast('[${sessionException.code}] ${sessionException.message}');
} else {
_appToast.showErrorToast(AppLocalizations.of(currentContext!).unknown_error_login_message);
}
}
}
}
bool _checkUrlError(dynamic sessionException) {
return sessionException is ConnectError || sessionException is BadGateway;
} }
void _goToLogin() async { void _goToLogin() async {
@@ -1,3 +1,4 @@
import 'package:core/presentation/utils/app_toast.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart'; import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart';
@@ -25,6 +26,7 @@ class SessionPageBindings extends BaseBindings {
Get.find<CachingManager>(), Get.find<CachingManager>(),
Get.find<DeleteAuthorityOidcInteractor>(), Get.find<DeleteAuthorityOidcInteractor>(),
Get.find<AuthorizationInterceptors>(), Get.find<AuthorizationInterceptors>(),
Get.find<AppToast>(),
)); ));
} }
+7 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2022-06-13T12:33:59.446625", "@@last_modified": "2022-06-22T11:25:25.867848",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -1417,5 +1417,11 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"wrongUrlMessage": "Server URL is not valid, please try again",
"@wrongUrlMessage": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -26,6 +26,7 @@ class NetworkBindings extends Bindings {
_bindingDio(); _bindingDio();
_bindingApi(); _bindingApi();
_bindingConnection(); _bindingConnection();
_bindingException();
} }
void _bindingBaseOption() { void _bindingBaseOption() {
@@ -78,4 +79,8 @@ class NetworkBindings extends Bindings {
void _bindingConnection() { void _bindingConnection() {
Get.put(Connectivity()); Get.put(Connectivity());
} }
void _bindingException() {
Get.put(RemoteExceptionThrower());
}
} }
@@ -1,3 +1,4 @@
import 'package:core/core.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart'; import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
@@ -11,11 +12,6 @@ import 'package:tmail_ui_user/features/session/domain/usecases/get_session_inter
class SessionBindings extends BaseBindings { class SessionBindings extends BaseBindings {
@override
void dependencies() {
super.dependencies();
}
@override @override
void bindingsController() { void bindingsController() {
} }
@@ -27,7 +23,9 @@ class SessionBindings extends BaseBindings {
@override @override
void bindingsDataSourceImpl() { void bindingsDataSourceImpl() {
Get.put(SessionDataSourceImpl(Get.find<SessionAPI>())); Get.put(SessionDataSourceImpl(
Get.find<SessionAPI>(),
Get.find<RemoteExceptionThrower>()));
} }
@override @override
@@ -1448,4 +1448,9 @@ class AppLocalizations {
name: 'noPreviewAvailable', name: 'noPreviewAvailable',
); );
} }
String get wrongUrlMessage {
return Intl.message('Server URL is not valid, please try again',
name: 'wrongUrlMessage');
}
} }