From 9a2f0aa35630b73c845b411661c96f6dc0d5c070 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 2 Jul 2025 15:54:29 +0700 Subject: [PATCH] Handle web finger to get token in HomeController Signed-off-by: dab246 --- .../reloadable/reloadable_controller.dart | 20 ++++++ .../caching/config/hive_cache_client.dart | 2 +- .../utils/session_storage_manager.dart | 16 +++-- ...email_session_storage_datasource_impl.dart | 4 +- ...dle_web_finger_to_get_token_extension.dart | 69 +++++++++++++++++++ .../home/presentation/home_bindings.dart | 9 ++- .../home/presentation/home_controller.dart | 45 +++++++++++- .../authentication_oidc_datasource.dart | 2 + .../authentication_oidc_datasource_impl.dart | 31 +++++++-- .../authentication_client_base.dart | 2 - .../authentication_client_mobile.dart | 5 -- .../authentication_client_web.dart | 13 ---- .../authentication_oidc_repository_impl.dart | 5 ++ .../exceptions/authentication_exception.dart | 2 - .../authentication_oidc_repository.dart | 2 + .../domain/state/get_token_oidc_state.dart | 9 ++- .../remove_auth_destination_url_state.dart | 11 +++ ...thenticate_oidc_on_browser_interactor.dart | 2 +- .../usecases/get_token_oidc_interactor.dart | 10 ++- ...emove_auth_destination_url_interactor.dart | 21 ++++++ .../login/presentation/login_bindings.dart | 22 +----- .../login/presentation/login_controller.dart | 67 ++++++------------ .../credential/credential_bindings.dart | 32 +++++++++ model/lib/oidc/request/oidc_request.dart | 7 ++ .../presentation/home_controller_test.dart | 23 ++++++- .../presentation/login_controller_test.dart | 5 ++ 26 files changed, 323 insertions(+), 113 deletions(-) create mode 100644 lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart create mode 100644 lib/features/login/domain/state/remove_auth_destination_url_state.dart create mode 100644 lib/features/login/domain/usecases/remove_auth_destination_url_interactor.dart diff --git a/lib/features/base/reloadable/reloadable_controller.dart b/lib/features/base/reloadable/reloadable_controller.dart index 655d272cd..ec2d0d840 100644 --- a/lib/features/base/reloadable/reloadable_controller.dart +++ b/lib/features/base/reloadable/reloadable_controller.dart @@ -158,4 +158,24 @@ abstract class ReloadableController extends BaseController { failure is GetStoredTokenOidcFailure || failure is GetAuthenticatedAccountFailure; } + + void synchronizeTokenAndGetSession({ + required Uri baseUri, + required TokenOIDC tokenOIDC, + required OIDCConfiguration oidcConfiguration, + }) { + final baseUrl = baseUri.toString(); + dynamicUrlInterceptors.setJmapUrl(baseUrl); + dynamicUrlInterceptors.changeBaseUrl(baseUrl); + authorizationInterceptors.setTokenAndAuthorityOidc( + newToken: tokenOIDC, + newConfig: oidcConfiguration, + ); + authorizationIsolateInterceptors.setTokenAndAuthorityOidc( + newToken: tokenOIDC, + newConfig: oidcConfiguration, + ); + + getSessionAction(); + } } \ No newline at end of file diff --git a/lib/features/caching/config/hive_cache_client.dart b/lib/features/caching/config/hive_cache_client.dart index 34fc93f39..35aaa40ac 100644 --- a/lib/features/caching/config/hive_cache_client.dart +++ b/lib/features/caching/config/hive_cache_client.dart @@ -53,7 +53,7 @@ abstract class HiveCacheClient { T newObject, { bool isolated = true, }) { - log('$runtimeType::insertItem:encryption: $encryption - key = $key - isolated'); + log('$runtimeType::insertItem:encryption: $encryption - key = $key - isolated = $isolated'); return Future.sync(() async { if (isolated) { final boxItem = await openIsolatedBox(); diff --git a/lib/features/caching/utils/session_storage_manager.dart b/lib/features/caching/utils/session_storage_manager.dart index 1afac4db2..1725b260a 100644 --- a/lib/features/caching/utils/session_storage_manager.dart +++ b/lib/features/caching/utils/session_storage_manager.dart @@ -5,12 +5,14 @@ import 'package:universal_html/html.dart' as html; class SessionStorageManager { - void save(String key, String value) { - html.window.sessionStorage.addAll({key: value}); + final html.Storage sessionStorage = html.window.sessionStorage; + + Future save(String key, String value) async { + return sessionStorage.addAll({key: value}); } - String get(String key) { - final entry = html.window.sessionStorage + Future get(String key) async { + final entry = sessionStorage .entries .firstWhereOrNull((entry) => entry.key == key); @@ -21,7 +23,9 @@ class SessionStorageManager { } } - void remove(String key) { - html.window.sessionStorage.remove(key); + Future remove(String key) async { + if (sessionStorage.containsKey(key)) { + sessionStorage.remove(key); + } } } \ No newline at end of file diff --git a/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart b/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart index 5c3b0a0fd..1855dee33 100644 --- a/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart +++ b/lib/features/email/data/datasource_impl/email_session_storage_datasource_impl.dart @@ -218,7 +218,7 @@ class EmailSessionStorageDatasourceImpl extends EmailDataSource { @override Future storePreviewEMLContentToSessionStorage(EMLPreviewer emlPreviewer) { return Future.sync(() async { - return _sessionStorageManager.save( + return await _sessionStorageManager.save( emlPreviewer.id, jsonEncode(emlPreviewer.toJson()), ); @@ -233,7 +233,7 @@ class EmailSessionStorageDatasourceImpl extends EmailDataSource { @override Future getPreviewEMLContentInMemory(String keyStored) { return Future.sync(() async { - final data = _sessionStorageManager.get(keyStored); + final data = await _sessionStorageManager.get(keyStored); return EMLPreviewer.fromJson(jsonDecode(data)); }).catchError(_exceptionThrower.throwException); } diff --git a/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart b/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart new file mode 100644 index 000000000..a51b1a9d2 --- /dev/null +++ b/lib/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart @@ -0,0 +1,69 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/utils/platform_info.dart'; +import 'package:dartz/dartz.dart'; +import 'package:model/oidc/oidc_configuration.dart'; +import 'package:model/oidc/request/oidc_request.dart'; +import 'package:model/oidc/response/oidc_response.dart'; +import 'package:tmail_ui_user/features/home/presentation/home_controller.dart'; +import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; +import 'package:tmail_ui_user/features/login/domain/model/base_url_oidc_response.dart'; +import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart'; +import 'package:tmail_ui_user/features/login/domain/state/get_token_oidc_state.dart'; +import 'package:tmail_ui_user/main/utils/app_config.dart'; + +extension HandleWebFingerToGetTokenExtension on HomeController { + bool isNotSignInOnWeb(Failure failure) => + PlatformInfo.isWeb && isNotSignedIn(failure); + + void checkOIDCIsAvailable() { + final baseUri = Uri.tryParse(AppConfig.baseUrl); + + if (baseUri == null) { + goToLogin(); + } else { + consumeState( + checkOIDCIsAvailableInteractor.execute(OIDCRequest.fromUri(baseUri)), + ); + } + } + + void getOIDCConfiguration(OIDCResponse oidcResponse) { + consumeState(getOIDCConfigurationInteractor.execute(oidcResponse)); + } + + void handleOIDCConfigurationSuccess(OIDCConfiguration oidcConfig) { + performUserAuthenticationOnWeb(oidcConfig); + } + + void performUserAuthenticationOnWeb(OIDCConfiguration oidcConfig) { + _removeAuthDestinationUrl(); + + consumeState(authenticateOidcOnBrowserInteractor.execute(oidcConfig)); + } + + void _removeAuthDestinationUrl() { + consumeState(removeAuthDestinationUrlInteractor.execute()); + } + + void handleCheckOIDCIsAvailableFailure() { + final baseUri = Uri.tryParse(AppConfig.baseUrl); + + if (baseUri == null) { + consumeState( + Stream.value(Left(GetOIDCConfigurationFailure(CanNotFoundBaseUrl()))), + ); + } else { + tryGetOIDCConfigurationFromBaseUri(baseUri); + } + } + + void tryGetOIDCConfigurationFromBaseUri(Uri baseUri) { + getOIDCConfiguration(BaseUrlOidcResponse(baseUri)); + } + + bool isGetTokenOIDCFailure(Failure? failure) { + return failure is GetOIDCConfigurationFailure || + failure is GetOIDCConfigurationFromBaseUrlFailure || + failure is GetTokenOIDCFailure; + } +} diff --git a/lib/features/home/presentation/home_bindings.dart b/lib/features/home/presentation/home_bindings.dart index 62ed90c0c..d853ba414 100644 --- a/lib/features/home/presentation/home_bindings.dart +++ b/lib/features/home/presentation/home_bindings.dart @@ -5,8 +5,10 @@ import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_lo import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_login_username_interactor.dart'; import 'package:tmail_ui_user/features/cleanup/presentation/cleanup_bindings.dart'; import 'package:tmail_ui_user/features/home/presentation/home_controller.dart'; -import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/check_oidc_is_available_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; class HomeBindings extends BaseBindings { @@ -18,6 +20,10 @@ class HomeBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), + Get.find(), + Get.find(), + Get.find(), )); } @@ -30,7 +36,6 @@ class HomeBindings extends BaseBindings { @override void bindingsInteractor() { CleanupBindings().dependencies(); - Get.lazyPut(() => CheckOIDCIsAvailableInteractor(Get.find())); } @override diff --git a/lib/features/home/presentation/home_controller.dart b/lib/features/home/presentation/home_controller.dart index fa0f6bfc4..6774d7146 100644 --- a/lib/features/home/presentation/home_controller.dart +++ b/lib/features/home/presentation/home_controller.dart @@ -20,9 +20,16 @@ import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_lo import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_login_username_interactor.dart'; import 'package:tmail_ui_user/features/home/domain/state/auto_sign_in_via_deep_link_state.dart'; import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart'; +import 'package:tmail_ui_user/features/home/presentation/extensions/handle_web_finger_to_get_token_extension.dart'; import 'package:tmail_ui_user/features/login/domain/exceptions/logout_exception.dart'; +import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_credential_state.dart'; +import 'package:tmail_ui_user/features/login/domain/state/get_oidc_configuration_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_stored_token_oidc_state.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/check_oidc_is_available_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/features/login/presentation/model/login_navigate_arguments.dart'; import 'package:tmail_ui_user/features/login/presentation/model/login_navigate_type.dart'; import 'package:tmail_ui_user/main/deep_links/open_app_deep_link_data.dart'; @@ -39,6 +46,10 @@ class HomeController extends ReloadableController { final EmailReceiveManager _emailReceiveManager; final CleanupRecentLoginUrlCacheInteractor _cleanupRecentLoginUrlCacheInteractor; final CleanupRecentLoginUsernameCacheInteractor _cleanupRecentLoginUsernameCacheInteractor; + final CheckOIDCIsAvailableInteractor checkOIDCIsAvailableInteractor; + final GetOIDCConfigurationInteractor getOIDCConfigurationInteractor; + final AuthenticateOidcOnBrowserInteractor authenticateOidcOnBrowserInteractor; + final RemoveAuthDestinationUrlInteractor removeAuthDestinationUrlInteractor; IOSNotificationManager? _iosNotificationManager; DeepLinksManager? _deepLinksManager; @@ -48,6 +59,10 @@ class HomeController extends ReloadableController { this._emailReceiveManager, this._cleanupRecentLoginUrlCacheInteractor, this._cleanupRecentLoginUsernameCacheInteractor, + this.checkOIDCIsAvailableInteractor, + this.getOIDCConfigurationInteractor, + this.authenticateOidcOnBrowserInteractor, + this.removeAuthDestinationUrlInteractor, ); @override @@ -95,7 +110,7 @@ class HomeController extends ReloadableController { if (arguments is LoginNavigateArguments) { _handleLoginNavigateArguments(arguments); } else { - _cleanupCache(); + await _cleanupCache(); } } @@ -283,6 +298,12 @@ class HomeController extends ReloadableController { }, onFailureCallback: goToLogin, ); + } else if (isNotSignInOnWeb(failure)) { + checkOIDCIsAvailable(); + } else if (failure is CheckOIDCIsAvailableFailure) { + handleCheckOIDCIsAvailableFailure(); + } else if (isGetTokenOIDCFailure(failure)) { + goToLogin(); } else { super.handleFailureViewState(failure); } @@ -313,8 +334,30 @@ class HomeController extends ReloadableController { }, onFailureCallback: () => _continueUsingTheApp(success), ); + } else if (success is CheckOIDCIsAvailableSuccess) { + getOIDCConfiguration(success.oidcResponse); + } else if (success is GetOIDCConfigurationSuccess) { + handleOIDCConfigurationSuccess(success.oidcConfiguration); } else { super.handleSuccessViewState(success); } } + + @override + void handleUrgentExceptionOnWeb({Failure? failure, Exception? exception}) { + if (failure is CheckOIDCIsAvailableFailure) { + handleCheckOIDCIsAvailableFailure(); + } else if (isGetTokenOIDCFailure(failure)) { + goToLogin(); + } else { + super.handleUrgentExceptionOnWeb(failure: failure, exception: exception); + } + } + + @override + void handleErrorViewState(Object error, StackTrace stackTrace) { + if (PlatformInfo.isWeb) { + goToLogin(); + } + } } \ No newline at end of file diff --git a/lib/features/login/data/datasource/authentication_oidc_datasource.dart b/lib/features/login/data/datasource/authentication_oidc_datasource.dart index 9642c12bf..5cfc0cf59 100644 --- a/lib/features/login/data/datasource/authentication_oidc_datasource.dart +++ b/lib/features/login/data/datasource/authentication_oidc_datasource.dart @@ -38,4 +38,6 @@ abstract class AuthenticationOIDCDataSource { List scopes); Future getAuthenticationInfo(); + + Future removeAuthDestinationUrl(); } \ No newline at end of file diff --git a/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart b/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart index 1c9e135fc..c644c1624 100644 --- a/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart +++ b/lib/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart @@ -1,9 +1,17 @@ -import 'package:model/model.dart'; +import 'package:model/oidc/oidc_configuration.dart'; +import 'package:model/oidc/request/oidc_request.dart'; +import 'package:model/oidc/response/oidc_discovery_response.dart'; +import 'package:model/oidc/response/oidc_response.dart'; +import 'package:model/oidc/token_id.dart'; +import 'package:model/oidc/token_oidc.dart'; +import 'package:tmail_ui_user/features/caching/utils/session_storage_manager.dart'; import 'package:tmail_ui_user/features/login/data/datasource/authentication_oidc_datasource.dart'; import 'package:tmail_ui_user/features/login/data/local/oidc_configuration_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/local/token_oidc_cache_manager.dart'; import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart'; +import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.dart'; import 'package:tmail_ui_user/features/login/data/network/oidc_http_client.dart'; +import 'package:tmail_ui_user/features/login/domain/model/login_constants.dart'; import 'package:tmail_ui_user/main/exceptions/exception_thrower.dart'; class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { @@ -12,6 +20,7 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { final AuthenticationClientBase _authenticationClient; final TokenOidcCacheManager _tokenOidcCacheManager; final OidcConfigurationCacheManager _oidcConfigurationCacheManager; + final SessionStorageManager _sessionStorageManager; final ExceptionThrower _exceptionThrower; final ExceptionThrower _cacheExceptionThrower; @@ -20,6 +29,7 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { this._authenticationClient, this._tokenOidcCacheManager, this._oidcConfigurationCacheManager, + this._sessionStorageManager, this._exceptionThrower, this._cacheExceptionThrower ); @@ -109,7 +119,7 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { Future deleteOidcConfiguration() { return Future.sync(() async { return await _oidcConfigurationCacheManager.deleteOidcConfiguration(); - }).catchError(_exceptionThrower.throwException); + }).catchError(_cacheExceptionThrower.throwException); } @override @@ -131,14 +141,25 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource { @override Future getAuthenticationInfo() { return Future.sync(() async { - return await _authenticationClient.getAuthenticationInfo(); - }).catchError(_exceptionThrower.throwException); + return await _sessionStorageManager.get( + OIDCConstant.authResponseKey, + ); + }).catchError(_cacheExceptionThrower.throwException); } @override Future deleteTokenOIDC() { return Future.sync(() async { return await _tokenOidcCacheManager.deleteTokenOidc(); - }).catchError(_exceptionThrower.throwException); + }).catchError(_cacheExceptionThrower.throwException); + } + + @override + Future removeAuthDestinationUrl() { + return Future.sync(() async { + return await _sessionStorageManager.remove( + LoginConstants.AUTH_DESTINATION_KEY, + ); + }).catchError(_cacheExceptionThrower.throwException); } } \ No newline at end of file diff --git a/lib/features/login/data/network/authentication_client/authentication_client_base.dart b/lib/features/login/data/network/authentication_client/authentication_client_base.dart index e3f9c70d4..4fbd79eeb 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_base.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_base.dart @@ -13,8 +13,6 @@ abstract class AuthenticationClientBase { String discoveryUrl, List scopes); - Future getAuthenticationInfo(); - Future getTokenOIDC( String clientId, String redirectUrl, diff --git a/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart b/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart index eeb1c4451..4eecf70cf 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_mobile.dart @@ -95,11 +95,6 @@ class AuthenticationClientMobile implements AuthenticationClientBase { return Future.value(null); } - @override - Future getAuthenticationInfo() { - return Future.value(''); - } - @override Future signInTwakeWorkplace(OIDCConfiguration oidcConfiguration) async { final uri = await FlutterWebAuth2.authenticate( diff --git a/lib/features/login/data/network/authentication_client/authentication_client_web.dart b/lib/features/login/data/network/authentication_client/authentication_client_web.dart index 1e3146a00..0f58a9e93 100644 --- a/lib/features/login/data/network/authentication_client/authentication_client_web.dart +++ b/lib/features/login/data/network/authentication_client/authentication_client_web.dart @@ -9,11 +9,9 @@ import 'package:model/oidc/token_oidc.dart'; import 'package:tmail_ui_user/features/login/data/extensions/authentication_token_extension.dart'; import 'package:tmail_ui_user/features/login/data/extensions/token_response_extension.dart'; import 'package:tmail_ui_user/features/login/data/network/authentication_client/authentication_client_base.dart'; -import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.dart'; import 'package:tmail_ui_user/features/login/data/utils/library_platform/app_auth_plugin/app_auth_plugin.dart'; import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; import 'package:tmail_ui_user/features/login/domain/extensions/oidc_configuration_extensions.dart'; -import 'package:universal_html/html.dart' as html; class AuthenticationClientWeb implements AuthenticationClientBase { @@ -96,17 +94,6 @@ class AuthenticationClientWeb implements AuthenticationClientBase { scopes: scopes)); } - @override - Future getAuthenticationInfo() async { - final authUrl = html.window.sessionStorage[OIDCConstant.authResponseKey]; - log('AuthenticationClientWeb::getAuthenticationInfo(): authUrl: $authUrl'); - if (authUrl != null && authUrl.isNotEmpty) { - return authUrl; - } else { - throw CanNotAuthenticationInfoOnWeb(); - } - } - @override Future signUpTwakeWorkplace(OIDCConfiguration oidcConfiguration) { throw UnimplementedError(); diff --git a/lib/features/login/data/repository/authentication_oidc_repository_impl.dart b/lib/features/login/data/repository/authentication_oidc_repository_impl.dart index a8ad608d8..3821fea0e 100644 --- a/lib/features/login/data/repository/authentication_oidc_repository_impl.dart +++ b/lib/features/login/data/repository/authentication_oidc_repository_impl.dart @@ -93,4 +93,9 @@ class AuthenticationOIDCRepositoryImpl extends AuthenticationOIDCRepository { Future deleteTokenOIDC() { return _oidcDataSource.deleteTokenOIDC(); } + + @override + Future removeAuthDestinationUrl() { + return _oidcDataSource.removeAuthDestinationUrl(); + } } \ No newline at end of file diff --git a/lib/features/login/domain/exceptions/authentication_exception.dart b/lib/features/login/domain/exceptions/authentication_exception.dart index 170b5e6d2..825fbb6cb 100644 --- a/lib/features/login/domain/exceptions/authentication_exception.dart +++ b/lib/features/login/domain/exceptions/authentication_exception.dart @@ -42,8 +42,6 @@ class CanNotFoundUserName implements Exception {} class CanNotFoundPassword implements Exception {} -class CanNotAuthenticationInfoOnWeb implements Exception {} - class NotFoundAuthenticationInfoCache implements Exception {} class CanNotFoundSaasServerUrl implements Exception {} diff --git a/lib/features/login/domain/repository/authentication_oidc_repository.dart b/lib/features/login/domain/repository/authentication_oidc_repository.dart index 0148dd6a0..2574bba4f 100644 --- a/lib/features/login/domain/repository/authentication_oidc_repository.dart +++ b/lib/features/login/domain/repository/authentication_oidc_repository.dart @@ -38,4 +38,6 @@ abstract class AuthenticationOIDCRepository { List scopes); Future getAuthenticationInfo(); + + Future removeAuthDestinationUrl(); } \ No newline at end of file diff --git a/lib/features/login/domain/state/get_token_oidc_state.dart b/lib/features/login/domain/state/get_token_oidc_state.dart index 53d72d941..e27da20b4 100644 --- a/lib/features/login/domain/state/get_token_oidc_state.dart +++ b/lib/features/login/domain/state/get_token_oidc_state.dart @@ -9,11 +9,16 @@ class GetTokenOIDCSuccess extends UIState { final TokenOIDC tokenOIDC; final OIDCConfiguration configuration; + final Uri baseUri; - GetTokenOIDCSuccess(this.tokenOIDC, this.configuration); + GetTokenOIDCSuccess( + this.tokenOIDC, + this.configuration, + this.baseUri, + ); @override - List get props => [tokenOIDC, configuration]; + List get props => [tokenOIDC, configuration, baseUri]; } class GetTokenOIDCFailure extends FeatureFailure { diff --git a/lib/features/login/domain/state/remove_auth_destination_url_state.dart b/lib/features/login/domain/state/remove_auth_destination_url_state.dart new file mode 100644 index 000000000..fe1453614 --- /dev/null +++ b/lib/features/login/domain/state/remove_auth_destination_url_state.dart @@ -0,0 +1,11 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; + +class RemovingAuthDestinationUrl extends LoadingState {} + +class RemoveAuthDestinationUrlSuccess extends UIState {} + +class RemoveAuthDestinationUrlFailure extends FeatureFailure { + RemoveAuthDestinationUrlFailure(dynamic exception) + : super(exception: exception); +} diff --git a/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart b/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart index cf858e14c..301169d59 100644 --- a/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart +++ b/lib/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart @@ -14,7 +14,7 @@ class AuthenticateOidcOnBrowserInteractor { AuthenticateOidcOnBrowserInteractor(this.authenticationOIDCRepository); - Stream> execute(Uri baseUrl, OIDCConfiguration config) async* { + Stream> execute(OIDCConfiguration config) async* { try { yield Right(AuthenticateOidcOnBrowserLoading()); await authenticationOIDCRepository.authenticateOidcOnBrowser( diff --git a/lib/features/login/domain/usecases/get_token_oidc_interactor.dart b/lib/features/login/domain/usecases/get_token_oidc_interactor.dart index 9eab8e3e0..09ce13418 100644 --- a/lib/features/login/domain/usecases/get_token_oidc_interactor.dart +++ b/lib/features/login/domain/usecases/get_token_oidc_interactor.dart @@ -23,7 +23,7 @@ class GetTokenOIDCInteractor { GetTokenOIDCInteractor(this._credentialRepository, this.authenticationOIDCRepository, this._accountRepository); - Stream> execute(Uri baseUrl, OIDCConfiguration config) async* { + Stream> execute(Uri baseUri, OIDCConfiguration config) async* { try { yield Right(GetTokenOIDCLoading()); final tokenOIDC = await authenticationOIDCRepository.getTokenOIDC( @@ -33,7 +33,7 @@ class GetTokenOIDCInteractor { config.scopes); await Future.wait([ - _credentialRepository.saveBaseUrl(baseUrl), + _credentialRepository.saveBaseUrl(baseUri), authenticationOIDCRepository.persistTokenOIDC(tokenOIDC), authenticationOIDCRepository.persistOidcConfiguration(config), ]); @@ -45,7 +45,11 @@ class GetTokenOIDCInteractor { isSelected: true ) ); - yield Right(GetTokenOIDCSuccess(tokenOIDC, config)); + yield Right(GetTokenOIDCSuccess( + tokenOIDC, + config, + baseUri, + )); } on PlatformException catch (e) { logError('GetTokenOIDCInteractor::execute(): PlatformException ${e.message} - ${e.stacktrace}'); if (NoSuitableBrowserForOIDCException.verifyException(e)) { diff --git a/lib/features/login/domain/usecases/remove_auth_destination_url_interactor.dart b/lib/features/login/domain/usecases/remove_auth_destination_url_interactor.dart new file mode 100644 index 000000000..6bcdfe5e5 --- /dev/null +++ b/lib/features/login/domain/usecases/remove_auth_destination_url_interactor.dart @@ -0,0 +1,21 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:dartz/dartz.dart'; +import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; +import 'package:tmail_ui_user/features/login/domain/state/remove_auth_destination_url_state.dart'; + +class RemoveAuthDestinationUrlInteractor { + final AuthenticationOIDCRepository _authenticationOIDCRepository; + + const RemoveAuthDestinationUrlInteractor(this._authenticationOIDCRepository); + + Stream> execute() async* { + try { + yield Right(RemovingAuthDestinationUrl()); + await _authenticationOIDCRepository.removeAuthDestinationUrl(); + yield Right(RemoveAuthDestinationUrlSuccess()); + } catch (e) { + yield Left(RemoveAuthDestinationUrlFailure(e)); + } + } +} diff --git a/lib/features/login/presentation/login_bindings.dart b/lib/features/login/presentation/login_bindings.dart index 42dc64ae3..0b0106920 100644 --- a/lib/features/login/presentation/login_bindings.dart +++ b/lib/features/login/presentation/login_bindings.dart @@ -23,6 +23,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_authentication_ import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_url_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_username_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/try_guessing_web_finger_interactor.dart'; @@ -54,6 +55,7 @@ class LoginBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), )); } @@ -83,26 +85,6 @@ class LoginBindings extends BaseBindings { @override void bindingsInteractor() { - Get.lazyPut(() => CheckOIDCIsAvailableInteractor( - Get.find(), - )); - Get.lazyPut(() => GetOIDCConfigurationInteractor( - Get.find(), - )); - Get.lazyPut(() => GetTokenOIDCInteractor( - Get.find(), - Get.find(), - Get.find() - )); - Get.lazyPut(() => AuthenticateOidcOnBrowserInteractor( - Get.find(), - )); - Get.lazyPut(() => GetAuthenticationInfoInteractor( - Get.find(), - )); - Get.lazyPut(() => GetStoredOidcConfigurationInteractor( - Get.find(), - )); Get.lazyPut(() => SaveLoginUrlOnMobileInteractor(Get.find(),)); Get.lazyPut(() => GetAllRecentLoginUrlOnMobileInteractor(Get.find())); Get.lazyPut(() => SaveLoginUsernameOnMobileInteractor(Get.find(),)); diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart index 6820e2554..ec41a9e7a 100644 --- a/lib/features/login/presentation/login_controller.dart +++ b/lib/features/login/presentation/login_controller.dart @@ -17,17 +17,14 @@ import 'package:model/account/password.dart'; import 'package:model/oidc/oidc_configuration.dart'; import 'package:model/oidc/request/oidc_request.dart'; import 'package:model/oidc/response/oidc_response.dart'; -import 'package:model/oidc/token_oidc.dart'; import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart'; import 'package:tmail_ui_user/features/home/domain/state/auto_sign_in_via_deep_link_state.dart'; import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart'; import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart'; import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart'; import 'package:tmail_ui_user/features/login/domain/exceptions/login_exception.dart'; -import 'package:tmail_ui_user/features/login/domain/model/login_constants.dart'; import 'package:tmail_ui_user/features/login/domain/model/recent_login_url.dart'; import 'package:tmail_ui_user/features/login/domain/model/recent_login_username.dart'; -import 'package:tmail_ui_user/features/login/domain/state/authenticate_oidc_on_browser_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/authentication_user_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/check_oidc_is_available_state.dart'; import 'package:tmail_ui_user/features/login/domain/state/dns_lookup_to_get_jmap_url_state.dart'; @@ -49,6 +46,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_authentication_ import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_url_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_username_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/try_guessing_web_finger_interactor.dart'; @@ -67,7 +65,6 @@ 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_utils.dart'; import 'package:tmail_ui_user/main/utils/app_config.dart'; -import 'package:universal_html/html.dart' as html; class LoginController extends ReloadableController { @@ -85,6 +82,7 @@ class LoginController extends ReloadableController { final DNSLookupToGetJmapUrlInteractor _dnsLookupToGetJmapUrlInteractor; final SignInTwakeWorkplaceInteractor _signInTwakeWorkplaceInteractor; final TryGuessingWebFingerInteractor _tryGuessingWebFingerInteractor; + final RemoveAuthDestinationUrlInteractor _removeAuthDestinationUrlInteractor; final TextEditingController urlInputController = TextEditingController(); final TextEditingController usernameInputController = TextEditingController(); @@ -117,6 +115,7 @@ class LoginController extends ReloadableController { this._dnsLookupToGetJmapUrlInteractor, this._signInTwakeWorkplaceInteractor, this._tryGuessingWebFingerInteractor, + this._removeAuthDestinationUrlInteractor, ); @override @@ -131,25 +130,24 @@ class LoginController extends ReloadableController { void onReady() { super.onReady(); final arguments = Get.arguments; + log('LoginController::onReady: arguments = $arguments'); if (arguments is LoginArguments) { - if (arguments.loginFormType == LoginFormType.passwordForm) { - loginFormType.value = LoginFormType.dnsLookupForm; - } else { - loginFormType.value = arguments.loginFormType; - } + loginFormType.value = + arguments.loginFormType == LoginFormType.passwordForm + ? LoginFormType.dnsLookupForm + : arguments.loginFormType; + if (PlatformInfo.isWeb) { _checkOIDCIsAvailable(); } - } else { - if (PlatformInfo.isWeb) { - _getAuthenticationInfo(); - } + } else if (PlatformInfo.isWeb) { + _getAuthenticationInfo(); } } @override void handleFailureViewState(Failure failure) { - log('LoginController::handleFailureViewState(): $failure'); + log('$runtimeType::handleFailureViewState():Failure = $failure'); if (failure is GetAuthenticationInfoFailure) { getAuthenticatedAccountAction(); } else if (failure is CheckOIDCIsAvailableFailure) { @@ -182,6 +180,7 @@ class LoginController extends ReloadableController { @override void handleSuccessViewState(Success success) { + log('$runtimeType::handleSuccessViewState:Success = ${success.runtimeType}'); if (success is GetAuthenticationInfoSuccess) { _getStoredOidcConfiguration(); } else if (success is GetStoredOidcConfigurationSuccess) { @@ -200,7 +199,7 @@ class LoginController extends ReloadableController { onBaseUrlChange(success.oidcResponse.subject); getOIDCConfiguration(success.oidcResponse); } else if (success is SignInTwakeWorkplaceSuccess) { - _synchronizeTokenAndGetSession( + synchronizeTokenAndGetSession( baseUri: success.baseUri, tokenOIDC: success.tokenOIDC, oidcConfiguration: success.oidcConfiguration, @@ -289,7 +288,7 @@ class LoginController extends ReloadableController { } void _handleAutoSignInViaDeepLinkSuccess(AutoSignInViaDeepLinkSuccess success) { - _synchronizeTokenAndGetSession( + synchronizeTokenAndGetSession( baseUri: success.baseUri, tokenOIDC: success.tokenOIDC, oidcConfiguration: success.oidcConfiguration, @@ -438,23 +437,6 @@ class LoginController extends ReloadableController { } } - void _synchronizeTokenAndGetSession({ - required Uri baseUri, - required TokenOIDC tokenOIDC, - required OIDCConfiguration oidcConfiguration, - }) { - dynamicUrlInterceptors.setJmapUrl(baseUri.toString()); - dynamicUrlInterceptors.changeBaseUrl(baseUri.toString()); - authorizationInterceptors.setTokenAndAuthorityOidc( - newToken: tokenOIDC, - newConfig: oidcConfiguration); - authorizationIsolateInterceptors.setTokenAndAuthorityOidc( - newToken: tokenOIDC, - newConfig: oidcConfiguration); - - getSessionAction(); - } - void _getTokenOIDCAction(OIDCConfiguration config) { if (_currentBaseUrl != null) { consumeState(_getTokenOIDCInteractor.execute(_currentBaseUrl!, config)); @@ -463,25 +445,18 @@ class LoginController extends ReloadableController { } } - void _authenticateOidcOnBrowserAction(OIDCConfiguration config) async { - _removeAuthDestinationUrlInSessionStorage(); + void _authenticateOidcOnBrowserAction(OIDCConfiguration config) { + _removeAuthDestinationUrl(); - if (_currentBaseUrl != null) { - consumeState(_authenticateOidcOnBrowserInteractor.execute(_currentBaseUrl!, config)); - } else { - dispatchState(Left(AuthenticateOidcOnBrowserFailure(CanNotFoundBaseUrl()))); - } + consumeState(_authenticateOidcOnBrowserInteractor.execute(config)); } - void _removeAuthDestinationUrlInSessionStorage() { - final authDestinationUrlExist = html.window.sessionStorage.containsKey(LoginConstants.AUTH_DESTINATION_KEY); - if (authDestinationUrlExist) { - html.window.sessionStorage.remove(LoginConstants.AUTH_DESTINATION_KEY); - } + void _removeAuthDestinationUrl() { + consumeState(_removeAuthDestinationUrlInteractor.execute()); } void _getTokenOIDCSuccess(GetTokenOIDCSuccess success) { - _synchronizeTokenAndGetSession( + synchronizeTokenAndGetSession( baseUri: _currentBaseUrl!, tokenOIDC: success.tokenOIDC, oidcConfiguration: success.configuration, diff --git a/lib/main/bindings/credential/credential_bindings.dart b/lib/main/bindings/credential/credential_bindings.dart index 10e5a7e93..f78fc7ff6 100644 --- a/lib/main/bindings/credential/credential_bindings.dart +++ b/lib/main/bindings/credential/credential_bindings.dart @@ -1,6 +1,7 @@ import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tmail_ui_user/features/base/interactors_bindings.dart'; +import 'package:tmail_ui_user/features/caching/utils/session_storage_manager.dart'; import 'package:tmail_ui_user/features/login/data/datasource/account_datasource.dart'; import 'package:tmail_ui_user/features/login/data/datasource/authentication_datasource.dart'; import 'package:tmail_ui_user/features/login/data/datasource/authentication_oidc_datasource.dart'; @@ -21,12 +22,19 @@ import 'package:tmail_ui_user/features/login/domain/repository/account_repositor import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/authentication_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/authentication_user_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/check_oidc_is_available_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/get_authenticated_account_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_authentication_info_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_credential_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_token_oidc_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart'; @@ -62,6 +70,29 @@ class CredentialBindings extends InteractorsBindings { Get.find() )); Get.put(UpdateAccountCacheInteractor(Get.find())); + Get.put(CheckOIDCIsAvailableInteractor( + Get.find(), + )); + Get.put(GetOIDCConfigurationInteractor( + Get.find(), + )); + Get.put(GetTokenOIDCInteractor( + Get.find(), + Get.find(), + Get.find(), + )); + Get.put(AuthenticateOidcOnBrowserInteractor( + Get.find(), + )); + Get.put(GetAuthenticationInfoInteractor( + Get.find(), + )); + Get.put(GetStoredOidcConfigurationInteractor( + Get.find(), + )); + Get.put(RemoveAuthDestinationUrlInteractor( + Get.find(), + )); } @override @@ -77,6 +108,7 @@ class CredentialBindings extends InteractorsBindings { Get.find(), Get.find(), Get.find(), + Get.find(), Get.find(), Get.find(), )); diff --git a/model/lib/oidc/request/oidc_request.dart b/model/lib/oidc/request/oidc_request.dart index 3c8903e29..4c91f0efe 100644 --- a/model/lib/oidc/request/oidc_request.dart +++ b/model/lib/oidc/request/oidc_request.dart @@ -9,6 +9,13 @@ class OIDCRequest with EquatableMixin { OIDCRequest({required this.baseUrl, required this.resourceUrl}); + factory OIDCRequest.fromUri(Uri uri) { + return OIDCRequest( + baseUrl: uri.toString(), + resourceUrl: uri.origin, + ); + } + @override List get props => [baseUrl, resourceUrl, relUrl]; } \ No newline at end of file diff --git a/test/features/home/presentation/home_controller_test.dart b/test/features/home/presentation/home_controller_test.dart index db1a83668..c684140e3 100644 --- a/test/features/home/presentation/home_controller_test.dart +++ b/test/features/home/presentation/home_controller_test.dart @@ -19,9 +19,13 @@ import 'package:tmail_ui_user/features/home/domain/usecases/get_session_interact import 'package:tmail_ui_user/features/home/presentation/home_controller.dart'; import 'package:tmail_ui_user/features/login/data/network/interceptors/authorization_interceptors.dart'; import 'package:tmail_ui_user/features/login/domain/state/get_stored_token_oidc_state.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/authenticate_oidc_on_browser_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/check_oidc_is_available_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/get_authenticated_account_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/update_account_cache_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart'; @@ -46,6 +50,10 @@ import 'home_controller_test.mocks.dart'; MockSpec(), MockSpec(), MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -64,6 +72,10 @@ void main() { late MockEmailReceiveManager emailReceiveManager; late MockCleanupRecentLoginUrlCacheInteractor cleanupRecentLoginUrlCacheInteractor; late MockCleanupRecentLoginUsernameCacheInteractor cleanupRecentLoginUsernameCacheInteractor; + late MockCheckOIDCIsAvailableInteractor checkOIDCIsAvailableInteractor; + late MockGetOIDCConfigurationInteractor getOIDCConfigurationInteractor; + late MockAuthenticateOidcOnBrowserInteractor authenticateOidcOnBrowserInteractor; + late MockRemoveAuthDestinationUrlInteractor removeAuthDestinationUrlInteractor; late MockGetSessionInteractor mockGetSessionInteractor; late MockGetAuthenticatedAccountInteractor mockGetAuthenticatedAccountInteractor; @@ -89,7 +101,10 @@ void main() { emailReceiveManager = MockEmailReceiveManager(); cleanupRecentLoginUrlCacheInteractor = MockCleanupRecentLoginUrlCacheInteractor(); cleanupRecentLoginUsernameCacheInteractor = MockCleanupRecentLoginUsernameCacheInteractor(); - + checkOIDCIsAvailableInteractor = MockCheckOIDCIsAvailableInteractor(); + getOIDCConfigurationInteractor = MockGetOIDCConfigurationInteractor(); + authenticateOidcOnBrowserInteractor = MockAuthenticateOidcOnBrowserInteractor(); + removeAuthDestinationUrlInteractor = MockRemoveAuthDestinationUrlInteractor(); // mock reloadable controller mockGetSessionInteractor = MockGetSessionInteractor(); mockGetAuthenticatedAccountInteractor = MockGetAuthenticatedAccountInteractor(); @@ -139,7 +154,11 @@ void main() { cleanupEmailCacheInteractor, emailReceiveManager, cleanupRecentLoginUrlCacheInteractor, - cleanupRecentLoginUsernameCacheInteractor + cleanupRecentLoginUsernameCacheInteractor, + checkOIDCIsAvailableInteractor, + getOIDCConfigurationInteractor, + authenticateOidcOnBrowserInteractor, + removeAuthDestinationUrlInteractor, ); }); diff --git a/test/features/login/presentation/login_controller_test.dart b/test/features/login/presentation/login_controller_test.dart index 63a6bad78..5c239c4ba 100644 --- a/test/features/login/presentation/login_controller_test.dart +++ b/test/features/login/presentation/login_controller_test.dart @@ -32,6 +32,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_authentication_ import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_stored_oidc_configuration_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/get_token_oidc_interactor.dart'; +import 'package:tmail_ui_user/features/login/domain/usecases/remove_auth_destination_url_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_url_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/save_login_username_on_mobile_interactor.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/try_guessing_web_finger_interactor.dart'; @@ -73,6 +74,7 @@ import 'login_controller_test.mocks.dart'; MockSpec(), MockSpec(), MockSpec(), + MockSpec(), MockSpec(), MockSpec(), MockSpec(), @@ -97,6 +99,7 @@ void main() { late MockDNSLookupToGetJmapUrlInteractor mockDNSLookupToGetJmapUrlInteractor; late MockSignInTwakeWorkplaceInteractor mockSignInTwakeWorkplaceInteractor; late MockTryGuessingWebFingerInteractor mockTryGuessingWebFingerInteractor; + late MockRemoveAuthDestinationUrlInteractor mockRemoveAuthDestinationUrlInteractor; late MockGetSessionInteractor mockGetSessionInteractor; late MockGetAuthenticatedAccountInteractor mockGetAuthenticatedAccountInteractor; late MockUpdateAccountCacheInteractor mockUpdateAccountCacheInteractor; @@ -132,6 +135,7 @@ void main() { mockDNSLookupToGetJmapUrlInteractor = MockDNSLookupToGetJmapUrlInteractor(); mockSignInTwakeWorkplaceInteractor = MockSignInTwakeWorkplaceInteractor(); mockTryGuessingWebFingerInteractor = MockTryGuessingWebFingerInteractor(); + mockRemoveAuthDestinationUrlInteractor = MockRemoveAuthDestinationUrlInteractor(); // mock reloadable controller mockGetSessionInteractor = MockGetSessionInteractor(); @@ -196,6 +200,7 @@ void main() { mockDNSLookupToGetJmapUrlInteractor, mockSignInTwakeWorkplaceInteractor, mockTryGuessingWebFingerInteractor, + mockRemoveAuthDestinationUrlInteractor, ); });