TF-1899 Sync and optimize handle error in base controller

(cherry picked from commit 1901d66c9100ca455c91ee8c95341de2a283eb67)
This commit is contained in:
dab246
2023-06-07 00:07:30 +07:00
committed by Dat Vu
parent dda45438ef
commit 00d8499879
12 changed files with 89 additions and 122 deletions
+55 -43
View File
@@ -93,35 +93,34 @@ abstract class BaseController extends GetxController
viewState.value = newState;
viewState.value.fold(
(failure) {
if (_handleCommonException(failure)) {
handleFinallyCommonException();
return;
if (failure is FeatureFailure) {
final exception = _performFilterExceptionInError(failure.exception);
if (exception != null) {
handleExceptionAction(exception);
} else {
handleFailureViewState(failure);
}
} else {
handleFailureViewState(failure);
}
handleFailureViewState(failure);
},
handleSuccessViewState);
}
bool _handleCommonException(Failure failure) {
if (failure is FeatureFailure) {
return _handleCommonError(failure.exception);
}
return false;
}
void onError(Object error, StackTrace stackTrace) {
logError('BaseController::onError():error: $error | stackTrace: $stackTrace');
if (_handleCommonError(error)) {
handleFinallyCommonException();
return;
final exception = _performFilterExceptionInError(error);
if (exception != null) {
handleExceptionAction(exception);
} else {
handleErrorViewState(error, stackTrace);
}
handleErrorViewState(error, stackTrace);
}
void onDone() {}
bool _handleCommonError(dynamic error) {
logError('BaseController::_handleCommonError(): $error');
Exception? _performFilterExceptionInError(dynamic error) {
logError('BaseController::_performFilterExceptionInError(): $error');
if (error is NoNetworkError || error is ConnectError || error is InternalServerError) {
if (currentOverlayContext != null && currentContext != null) {
_appToast.showToastMessage(
@@ -135,46 +134,55 @@ abstract class BaseController extends GetxController
infinityToast: true,
);
}
return true;
return error;
} else if (error is BadCredentialsException) {
if (currentOverlayContext != null && currentContext != null) {
_appToast.showToastErrorMessage(
currentOverlayContext!,
AppLocalizations.of(currentContext!).badCredentials);
}
checkAuthenticationTypeWhenLogout();
return true;
performInvokeLogoutAction();
return error;
}
return false;
return null;
}
void handleErrorViewState(Object error, StackTrace stackTrace) {}
void handleFinallyCommonException() {
void handleExceptionAction(Exception exception) {
log('BaseController::handleExceptionAction():exception: $exception');
clearState();
}
void handleFailureViewState(Failure failure) {
logError('BaseController::handleFailureViewState(): $failure');
if (failure is LogoutOidcFailure) {
_getSubscriptionLocalAction();
if (_isFcmEnabled) {
_getSubscriptionLocalAction();
} else {
_logoutOIDCAction();
}
} else if (failure is GetFCMSubscriptionLocalFailure) {
checkAuthenticationTypeWhenLogout();
performInvokeLogoutAction();
} else if (failure is DestroySubscriptionFailure) {
checkAuthenticationTypeWhenLogout();
performInvokeLogoutAction();
}
}
void handleSuccessViewState(Success success) {
log('BaseController::handleSuccessViewState(): $success');
if (success is LogoutOidcSuccess) {
_getSubscriptionLocalAction();
if (_isFcmEnabled) {
_getSubscriptionLocalAction();
} else {
_logoutOIDCAction();
}
} else if (success is GetFCMSubscriptionLocalSuccess) {
final subscriptionId = success.fcmSubscription.subscriptionId;
_destroySubscriptionAction(subscriptionId);
} else if (success is DestroySubscriptionSuccess) {
checkAuthenticationTypeWhenLogout();
performInvokeLogoutAction();
}
}
@@ -249,6 +257,10 @@ abstract class BaseController extends GetxController
}
}
AuthenticationType get authenticationType => authorizationInterceptors.authenticationType;
bool get isAuthenticatedWithOidc => authenticationType == AuthenticationType.oidc;
bool _isFcmActivated(Session session, AccountId accountId) =>
[FirebaseCapability.fcmIdentifier].isSupported(session, accountId) && AppConfig.fcmAvailable;
@@ -258,17 +270,18 @@ abstract class BaseController extends GetxController
void logout(Session? session, AccountId? accountId) {
if (session == null || accountId == null) {
logError('BaseController::logout(): Session is $session OR AccountId is $accountId');
performInvokeLogoutAction();
return;
}
_isFcmEnabled = _isFcmActivated(session, accountId);
final authenticationType = authorizationInterceptors.authenticationType;
if (authenticationType == AuthenticationType.oidc) {
if (isAuthenticatedWithOidc) {
consumeState(logoutOidcInteractor.execute());
} else {
if (_isFcmEnabled) {
_getSubscriptionLocalAction();
} else {
logoutAction();
_logoutAction();
}
}
}
@@ -278,33 +291,31 @@ abstract class BaseController extends GetxController
_destroySubscriptionInteractor = Get.find<DestroySubscriptionInteractor>();
consumeState(_destroySubscriptionInteractor!.execute(subscriptionId));
} catch(e) {
logError('ReloadableController::destroySubscriptionAction(): exception: $e');
logoutAction();
logError('BaseController::destroySubscriptionAction(): exception: $e');
performInvokeLogoutAction();
}
}
Future<void> _getSubscriptionLocalAction() {
void _getSubscriptionLocalAction() {
try {
_getSubscriptionLocalInteractor = Get.find<GetFCMSubscriptionLocalInteractor>();
consumeState(_getSubscriptionLocalInteractor!.execute());
} catch (e) {
logError(
'ReloadableController::getSubscriptionLocalAction(): exception: $e');
logoutAction();
logError('BaseController::getSubscriptionLocalAction(): exception: $e');
performInvokeLogoutAction();
}
return Future.value();
}
void checkAuthenticationTypeWhenLogout() {
final authenticationType = authorizationInterceptors.authenticationType;
if (authenticationType == AuthenticationType.oidc) {
void performInvokeLogoutAction() {
if (isAuthenticatedWithOidc) {
_logoutOIDCAction();
} else {
logoutAction();
_logoutAction();
}
}
void logoutAction() async {
void _logoutAction() async {
log('BaseController::_logoutAction():');
await Future.wait([
deleteCredentialInteractor.execute(),
cachingManager.clearAll(),
@@ -321,7 +332,7 @@ abstract class BaseController extends GetxController
}
void _logoutOIDCAction() async {
log('ReloadableController::_logoutOIDCAction():');
log('BaseController::_logoutOIDCAction():');
await Future.wait([
deleteAuthorityOidcInteractor.execute(),
cachingManager.clearAll(),
@@ -334,5 +345,6 @@ abstract class BaseController extends GetxController
_fcmReceiver.deleteFcmToken();
}
await cachingManager.closeHive();
goToLogin(arguments: LoginArguments(LoginFormType.ssoForm));
}
}
@@ -1,5 +1,4 @@
import 'package:core/data/network/config/dynamic_url_interceptors.dart';
import 'package:core/presentation/extensions/uri_extension.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
@@ -8,7 +7,6 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/user_name.dart';
import 'package:model/account/authentication_type.dart';
import 'package:model/extensions/session_extension.dart';
import 'package:model/oidc/token_oidc.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
@@ -20,6 +18,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/update_authenticati
import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart';
import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/vacation/vacation_interactors_bindings.dart';
import 'package:tmail_ui_user/features/session/domain/extensions/session_extensions.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/main/error/capability_validator.dart';
@@ -94,35 +93,22 @@ abstract class ReloadableController extends BaseController {
consumeState(_getSessionInteractor.execute());
}
void _handleGetSessionFailure() async {
await Future.wait([
deleteCredentialInteractor.execute(),
deleteAuthorityOidcInteractor.execute(),
cachingManager.clearAll(),
languageCacheManager.removeLanguage(),
]);
final authenticationType = authorizationInterceptors.authenticationType;
if (authenticationType == AuthenticationType.oidc) {
goToLogin(arguments: LoginArguments(LoginFormType.ssoForm));
} else {
goToLogin(arguments: LoginArguments(LoginFormType.credentialForm));
}
void _handleGetSessionFailure() {
performInvokeLogoutAction();
}
void _handleGetSessionSuccess(GetSessionSuccess success) {
final session = success.session;
final personalAccount = session.personalAccount;
final jmapUrl = _dynamicUrlInterceptors.jmapUrl;
final apiUrl = jmapUrl != null
? session.apiUrl.toQualifiedUrl(baseUrl: Uri.parse(jmapUrl)).toString()
: session.apiUrl.toString();
final apiUrl = session.getQualifiedApiUrl(baseUrl: _dynamicUrlInterceptors.jmapUrl);
log('ReloadableController::_handleGetSessionSuccess():apiUrl: $apiUrl');
if (apiUrl.isNotEmpty) {
_dynamicUrlInterceptors.changeBaseUrl(apiUrl);
updateAuthenticationAccount(session, personalAccount.accountId, session.username);
handleReloaded(session);
} else {
_handleGetSessionFailure();
logError('ReloadableController::_handleGetSessionSuccess(): apiUrl is NULL');
performInvokeLogoutAction();
}
}
@@ -154,10 +140,7 @@ abstract class ReloadableController extends BaseController {
}
void updateAuthenticationAccount(Session session, AccountId accountId, UserName userName) {
final jmapUrl = _dynamicUrlInterceptors.jmapUrl;
final apiUrl = jmapUrl != null
? session.apiUrl.toQualifiedUrl(baseUrl: Uri.parse(jmapUrl)).toString()
: session.apiUrl.toString();
final apiUrl = session.getQualifiedApiUrl(baseUrl: _dynamicUrlInterceptors.jmapUrl);;
log('ReloadableController::updateAuthenticationAccount():apiUrl: $apiUrl');
if (apiUrl.isNotEmpty) {
consumeState(_updateAuthenticationAccountInteractor.execute(accountId, apiUrl, userName));