TF-2965 Add retry capability for OIDC check request

This commit is contained in:
DatDang
2024-09-12 16:05:06 +07:00
committed by Dat H. Pham
parent 2739a284d8
commit 0d4c266300
11 changed files with 192 additions and 18 deletions
@@ -2,4 +2,6 @@ class CanNotFoundOIDCAuthority implements Exception {}
class CanNotFoundOIDCLinks implements Exception {}
class CanNotFoundToken implements Exception {}
class CanNotFindToken implements Exception {}
class CanRetryOIDCException implements Exception {}
@@ -13,6 +13,7 @@ import 'package:tmail_ui_user/features/login/data/network/config/oidc_constant.d
import 'package:tmail_ui_user/features/login/data/network/endpoint.dart';
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
import 'package:tmail_ui_user/main/utils/app_config.dart';
import 'package:dio/dio.dart' show DioError;
class OIDCHttpClient {
@@ -21,24 +22,29 @@ class OIDCHttpClient {
OIDCHttpClient(this._dioClient);
Future<OIDCResponse> checkOIDCIsAvailable(OIDCRequest oidcRequest) async {
final result = await _dioClient.get(
try {
final result = await _dioClient.get(
Endpoint.webFinger
.generateOIDCPath(Uri.parse(oidcRequest.baseUrl))
.withQueryParameters([
StringQueryParameter('resource', oidcRequest.resourceUrl),
StringQueryParameter('rel', OIDCRequest.relUrl),
])
.generateEndpointPath()
);
log('OIDCHttpClient::checkOIDCIsAvailable(): RESULT: $result');
if (result != null) {
.generateOIDCPath(Uri.parse(oidcRequest.baseUrl))
.withQueryParameters([
StringQueryParameter('resource', oidcRequest.resourceUrl),
StringQueryParameter('rel', OIDCRequest.relUrl),
])
.generateEndpointPath()
);
log('OIDCHttpClient::checkOIDCIsAvailable(): RESULT: $result');
if (result is Map<String, dynamic>) {
return OIDCResponse.fromJson(result);
} else {
return OIDCResponse.fromJson(jsonDecode(result));
}
} else {
throw CanNotFoundOIDCLinks();
} on DioError catch (exception) {
if (exception.response?.statusCode == 404) {
throw CanNotFoundOIDCLinks();
}
throw CanRetryOIDCException();
} catch (_) {
throw CanRetryOIDCException();
}
}
@@ -125,8 +125,9 @@ class LoginController extends ReloadableController {
log('LoginController::handleFailureViewState(): $failure');
if (failure is GetAuthenticationInfoFailure) {
getAuthenticatedAccountAction();
} else if (failure is CheckOIDCIsAvailableFailure ||
failure is GetStoredOidcConfigurationFailure ||
} else if (failure is CheckOIDCIsAvailableFailure) {
_handleCheckOIDCIsAvailableFailure(failure);
} else if (failure is GetStoredOidcConfigurationFailure ||
failure is GetOIDCIsAvailableFailure ||
failure is GetOIDCConfigurationFailure
) {
@@ -174,8 +175,9 @@ class LoginController extends ReloadableController {
@override
void handleUrgentException({Failure? failure, Exception? exception}) {
logError('LoginController::handleUrgentException:Exception: $exception | Failure: $failure');
if (failure is CheckOIDCIsAvailableFailure ||
failure is GetStoredOidcConfigurationFailure ||
if (failure is CheckOIDCIsAvailableFailure) {
_handleCheckOIDCIsAvailableFailure(failure);
} else if (failure is GetStoredOidcConfigurationFailure ||
failure is GetOIDCConfigurationFailure ||
failure is GetOIDCIsAvailableFailure) {
_handleCommonOIDCFailure();
@@ -197,6 +199,23 @@ class LoginController extends ReloadableController {
);
}
void _handleCheckOIDCIsAvailableFailure(CheckOIDCIsAvailableFailure failure) {
if (failure.exception is CanNotFoundOIDCLinks) {
_handleCommonOIDCFailure();
} else {
loginFormType.value = LoginFormType.retry;
}
}
void retryCheckOidc() {
if (PlatformInfo.isMobile) {
loginFormType.value = LoginFormType.dnsLookupForm;
} else {
loginFormType.value = LoginFormType.none;
}
_checkOIDCIsAvailable();
}
void _getAuthenticationInfo() {
consumeState(_getAuthenticationInfoInteractor.execute());
}
@@ -453,6 +472,9 @@ class LoginController extends ReloadableController {
} else {
_username = UserName(value);
}
if (loginFormType.value == LoginFormType.retry && PlatformInfo.isMobile) {
loginFormType.value = LoginFormType.dnsLookupForm;
}
}
void onPasswordChange(String value) {
@@ -1,5 +1,6 @@
enum LoginFormType {
none,
retry,
baseUrlForm,
credentialForm,
passwordForm,
@@ -88,6 +88,7 @@ class LoginView extends BaseLoginView {
Obx(() {
switch (controller.loginFormType.value) {
case LoginFormType.dnsLookupForm:
case LoginFormType.retry:
return DNSLookupInputForm(
textEditingController: controller.usernameInputController,
onTextChange: controller.onUsernameChange,
@@ -174,6 +175,9 @@ class LoginView extends BaseLoginView {
style: const TextStyle(fontSize: 16, color: Colors.white)
),
onPressed: () {
if (controller.loginFormType.value == LoginFormType.retry) {
controller.loginFormType.value = LoginFormType.dnsLookupForm;
}
if (controller.loginFormType.value == LoginFormType.dnsLookupForm) {
controller.invokeDNSLookupToGetJmapUrl();
} else {
@@ -206,6 +210,7 @@ class LoginView extends BaseLoginView {
switch (controller.loginFormType.value) {
case LoginFormType.dnsLookupForm:
case LoginFormType.baseUrlForm:
case LoginFormType.retry:
return _buildNextButtonInContext(context);
case LoginFormType.passwordForm:
case LoginFormType.credentialForm:
@@ -10,6 +10,7 @@ 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/privacy_link_widget.dart';
import 'package:tmail_ui_user/features/login/presentation/widgets/login_message_widget.dart';
import 'package:tmail_ui_user/features/login/presentation/widgets/try_again_button.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class LoginView extends BaseLoginView {
@@ -57,6 +58,11 @@ class LoginView extends BaseLoginView {
switch (controller.loginFormType.value) {
case LoginFormType.credentialForm:
return buildInputCredentialForm(context);
case LoginFormType.retry:
return TryAgainButton(
onRetry: controller.retryCheckOidc,
responsiveUtils: controller.responsiveUtils,
);
default:
return const SizedBox.shrink();
}
@@ -199,6 +205,11 @@ class LoginView extends BaseLoginView {
switch (controller.loginFormType.value) {
case LoginFormType.credentialForm:
return buildInputCredentialForm(context);
case LoginFormType.retry:
return TryAgainButton(
onRetry: controller.retryCheckOidc,
responsiveUtils: controller.responsiveUtils,
);
default:
return const SizedBox.shrink();
}
@@ -0,0 +1,31 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class TryAgainButton extends StatelessWidget {
const TryAgainButton({
super.key,
required this.onRetry,
required this.responsiveUtils,
});
final VoidCallback onRetry;
final ResponsiveUtils responsiveUtils;
@override
Widget build(BuildContext context) {
return TMailButtonWidget.fromText(
text: AppLocalizations.of(context).tryAgain,
textStyle: const TextStyle(fontSize: 16, color: Colors.white),
backgroundColor: AppColor.primaryColor,
onTapActionCallback: onRetry,
borderRadius: 10,
margin: const EdgeInsetsDirectional.only(bottom: 16, start: 24, end: 24),
width: responsiveUtils.getDeviceWidth(context),
textAlign: TextAlign.center,
padding: const EdgeInsets.symmetric(vertical: 12),
);
}
}