From a39304841833241812bbcd75ff42fadeb485c94c Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 8 Jun 2022 15:24:12 +0700 Subject: [PATCH] TF-624 Hide credential form when oidc is available on browser --- .../home/presentation/home_bindings.dart | 3 + .../home/presentation/home_controller.dart | 40 ++++++++- .../login/presentation/base_login_view.dart | 2 +- .../login/presentation/login_controller.dart | 17 +++- .../login/presentation/login_view_web.dart | 87 +++++++++++++++---- .../presentation/model/login_arguments.dart | 13 +++ 6 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 lib/features/login/presentation/model/login_arguments.dart diff --git a/lib/features/home/presentation/home_bindings.dart b/lib/features/home/presentation/home_bindings.dart index 1accfca59..83258bfe3 100644 --- a/lib/features/home/presentation/home_bindings.dart +++ b/lib/features/home/presentation/home_bindings.dart @@ -25,6 +25,7 @@ import 'package:tmail_ui_user/features/login/data/repository/authentication_oidc import 'package:tmail_ui_user/features/login/domain/repository/account_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/authentication_oidc_repository.dart'; import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.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'; @@ -47,6 +48,7 @@ class HomeBindings extends BaseBindings { Get.find(), Get.find(), Get.find(), + Get.find(), )); } @@ -88,6 +90,7 @@ class HomeBindings extends BaseBindings { Get.lazyPut(() => CleanupEmailCacheInteractor(Get.find())); Get.lazyPut(() => CleanupRecentSearchCacheInteractor(Get.find())); Get.lazyPut(() => DeleteAuthorityOidcInteractor(Get.find())); + 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 efef61e0b..f5a0170ec 100644 --- a/lib/features/home/presentation/home_controller.dart +++ b/lib/features/home/presentation/home_controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/account/account.dart'; +import 'package:model/oidc/request/oidc_request.dart'; import 'package:model/oidc/token_oidc.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; @@ -13,13 +14,18 @@ import 'package:tmail_ui_user/features/cleanup/domain/model/recent_search_cleanu import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_email_cache_interactor.dart'; import 'package:tmail_ui_user/features/cleanup/domain/usecases/cleanup_recent_search_cache_interactor.dart'; import 'package:tmail_ui_user/features/login/data/network/config/authorization_interceptors.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_stored_token_oidc_state.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/presentation/login_form_type.dart'; +import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.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/utils/app_config.dart'; import 'package:tmail_ui_user/main/utils/email_receive_manager.dart'; class HomeController extends BaseController { @@ -32,6 +38,7 @@ class HomeController extends BaseController { final DeleteCredentialInteractor _deleteCredentialInteractor; final CachingManager _cachingManager; final DeleteAuthorityOidcInteractor _deleteAuthorityOidcInteractor; + final CheckOIDCIsAvailableInteractor _checkOIDCIsAvailableInteractor; HomeController( this._getAuthenticatedAccountInteractor, @@ -43,6 +50,7 @@ class HomeController extends BaseController { this._deleteCredentialInteractor, this._cachingManager, this._deleteAuthorityOidcInteractor, + this._checkOIDCIsAvailableInteractor, ); Account? currentAccount; @@ -94,8 +102,8 @@ class HomeController extends BaseController { }); } - void _goToLogin() { - pushAndPop(AppRoutes.LOGIN); + void _goToLogin({LoginArguments? arguments}) { + pushAndPop(AppRoutes.LOGIN, arguments: arguments); } @override @@ -131,7 +139,33 @@ class HomeController extends BaseController { _deleteCredentialInteractor.execute(), _deleteAuthorityOidcInteractor.execute(), _cachingManager.clearAll() - ]).then((value) => _goToLogin()); + ]).then((value) { + if (BuildUtils.isWeb) { + _checkOIDCIsAvailable(); + } else { + _goToLogin(); + } + }); + } + + Uri? _parseUri(String? url) => url != null && url.trim().isNotEmpty + ? Uri.parse(url.trim()) + : null; + + void _checkOIDCIsAvailable() async { + final baseUri = _parseUri(AppConfig.baseUrl); + log('LoginController::_checkOIDCIsAvailable(): baseUri: $baseUri'); + if (baseUri != null) { + await _checkOIDCIsAvailableInteractor + .execute(OIDCRequest(baseUrl: baseUri.toString(), resourceUrl: baseUri.origin)) + .then((response) => response.fold( + (failure) => _goToLogin(arguments: LoginArguments(LoginFormType.credentialForm)), + (success) => success is CheckOIDCIsAvailableSuccess + ? _goToLogin(arguments: LoginArguments(LoginFormType.ssoForm)) + : _goToLogin(arguments: LoginArguments(LoginFormType.credentialForm)))); + } else { + _goToLogin(arguments: LoginArguments(LoginFormType.credentialForm)); + } } void _goToSessionWithTokenOidc(GetStoredTokenOidcSuccess storedTokenOidcSuccess) { diff --git a/lib/features/login/presentation/base_login_view.dart b/lib/features/login/presentation/base_login_view.dart index 9af6715c0..4bdfc97bf 100644 --- a/lib/features/login/presentation/base_login_view.dart +++ b/lib/features/login/presentation/base_login_view.dart @@ -49,7 +49,7 @@ abstract class BaseLoginView extends GetWidget { } }, (success) { - if (loginController.loginFormType.value == LoginFormType.credentialForm || kIsWeb) { + if (loginController.loginFormType.value == LoginFormType.credentialForm) { return AppLocalizations.of(context).loginInputCredentialMessage; } else if (loginController.loginFormType.value == LoginFormType.ssoForm) { return AppLocalizations.of(context).loginInputSSOMessage; diff --git a/lib/features/login/presentation/login_controller.dart b/lib/features/login/presentation/login_controller.dart index 13e2d4749..59c80dce4 100644 --- a/lib/features/login/presentation/login_controller.dart +++ b/lib/features/login/presentation/login_controller.dart @@ -20,6 +20,7 @@ import 'package:tmail_ui_user/features/login/domain/usecases/get_oidc_configurat 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/presentation/login_form_type.dart'; +import 'package:tmail_ui_user/features/login/presentation/model/login_arguments.dart'; import 'package:tmail_ui_user/features/login/presentation/state/login_state.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; @@ -85,10 +86,21 @@ class LoginController extends GetxController { super.onInit(); } + @override + void onReady() { + if (BuildUtils.isWeb) { + final arguments = Get.arguments; + if (arguments is LoginArguments) { + loginFormType.value = arguments.loginFormType; + } + } + super.onReady(); + } + void _getAuthenticationInfo() async { await _getAuthenticationInfoInteractor.execute() .then((result) => result.fold( - (failure) => null, + (failure) => {}, (success) { if (success is GetAuthenticationInfoSuccess) { _getStoredOidcConfiguration(); @@ -99,7 +111,7 @@ class LoginController extends GetxController { void _getStoredOidcConfiguration() async { await _getStoredOidcConfigurationInteractor.execute() .then((result) => result.fold( - (failure) => null, + (failure) => {}, (success) { if (success is GetStoredOidcConfigurationSuccess) { _getTokenOIDCAction(success.oidcConfiguration); @@ -141,6 +153,7 @@ class LoginController extends GetxController { } void _showFormLoginWithCredentialAction() { + log('LoginController::_showFormLoginWithCredentialAction()'); loginState.value = LoginState(Right(InputUrlCompletion())); loginFormType.value = LoginFormType.credentialForm; } diff --git a/lib/features/login/presentation/login_view_web.dart b/lib/features/login/presentation/login_view_web.dart index d1db4ea92..2572c2bee 100644 --- a/lib/features/login/presentation/login_view_web.dart +++ b/lib/features/login/presentation/login_view_web.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'; import 'package:tmail_ui_user/features/login/presentation/base_login_view.dart'; +import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; import 'package:tmail_ui_user/features/login/presentation/state/login_state.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -46,13 +47,40 @@ class LoginView extends BaseLoginView { ) ), Obx(() => buildLoginMessage(context, loginController.loginState.value)), - buildInputCredentialForm(context), - buildLoginButton(context), - Obx(() => loginController.loginState.value.viewState.fold( - (failure) => _buildSSOButton(context), - (success) => success is LoginLoadingAction - ? buildLoadingCircularProgress() - : _buildSSOButton(context))), + Obx(() { + switch (controller.loginFormType.value) { + case LoginFormType.credentialForm: + return buildInputCredentialForm(context); + case LoginFormType.ssoForm: + return const SizedBox(height: 150); + default: + return const SizedBox.shrink(); + } + }), + Obx(() { + switch (controller.loginFormType.value) { + case LoginFormType.baseUrlForm: + return Obx(() => loginController.loginState.value.viewState.fold( + (failure) => const SizedBox.shrink(), + (success) => success is LoginLoadingAction + ? buildLoadingCircularProgress() + : const SizedBox.shrink())); + case LoginFormType.credentialForm: + return Obx(() => loginController.loginState.value.viewState.fold( + (failure) => buildLoginButton(context), + (success) => success is LoginLoadingAction + ? buildLoadingCircularProgress() + : buildLoginButton(context))); + case LoginFormType.ssoForm: + return Obx(() => loginController.loginState.value.viewState.fold( + (failure) => _buildSSOButton(context), + (success) => success is LoginLoadingAction + ? buildLoadingCircularProgress() + : _buildSSOButton(context))); + default: + return const SizedBox.shrink(); + } + }) ], ) ), @@ -166,13 +194,40 @@ class LoginView extends BaseLoginView { ) ), Obx(() => buildLoginMessage(context, loginController.loginState.value)), - buildInputCredentialForm(context), - buildLoginButton(context), - Obx(() => loginController.loginState.value.viewState.fold( - (failure) => _buildSSOButton(context), - (success) => success is LoginLoadingAction - ? buildLoadingCircularProgress() - : _buildSSOButton(context))), + Obx(() { + switch (controller.loginFormType.value) { + case LoginFormType.credentialForm: + return buildInputCredentialForm(context); + case LoginFormType.ssoForm: + return const SizedBox(height: 150); + default: + return const SizedBox.shrink(); + } + }), + Obx(() { + switch (controller.loginFormType.value) { + case LoginFormType.baseUrlForm: + return Obx(() => loginController.loginState.value.viewState.fold( + (failure) => const SizedBox.shrink(), + (success) => success is LoginLoadingAction + ? buildLoadingCircularProgress() + : const SizedBox.shrink())); + case LoginFormType.credentialForm: + return Obx(() => loginController.loginState.value.viewState.fold( + (failure) => buildLoginButton(context), + (success) => success is LoginLoadingAction + ? buildLoadingCircularProgress() + : buildLoginButton(context))); + case LoginFormType.ssoForm: + return Obx(() => loginController.loginState.value.viewState.fold( + (failure) => _buildSSOButton(context), + (success) => success is LoginLoadingAction + ? buildLoadingCircularProgress() + : _buildSSOButton(context))); + default: + return const SizedBox.shrink(); + } + }) ], ) ) @@ -218,10 +273,10 @@ class LoginView extends BaseLoginView { key: const Key('ssoSubmitForm'), style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith((Set states) => Colors.white), - backgroundColor: MaterialStateProperty.resolveWith((Set states) => AppColor.textFieldErrorBorderColor), + backgroundColor: MaterialStateProperty.resolveWith((Set states) => AppColor.primaryColor), shape: MaterialStateProperty.all(RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), - side: const BorderSide(width: 0, color: AppColor.textFieldErrorBorderColor) + side: const BorderSide(width: 0, color: AppColor.primaryColor) )) ), child: Text(AppLocalizations.of(context).singleSignOn, diff --git a/lib/features/login/presentation/model/login_arguments.dart b/lib/features/login/presentation/model/login_arguments.dart new file mode 100644 index 000000000..b87eb6b9f --- /dev/null +++ b/lib/features/login/presentation/model/login_arguments.dart @@ -0,0 +1,13 @@ + +import 'package:tmail_ui_user/features/login/presentation/login_form_type.dart'; +import 'package:tmail_ui_user/main/routes/router_arguments.dart'; + +class LoginArguments extends RouterArguments { + + final LoginFormType loginFormType; + + LoginArguments(this.loginFormType); + + @override + List get props => [loginFormType]; +} \ No newline at end of file