TF-607 Implement logoutOidc action when user click signOut

This commit is contained in:
dab246
2022-06-03 11:34:18 +07:00
committed by Dat H. Pham
parent 45fbbc6a6f
commit ced3fecd1f
16 changed files with 184 additions and 20 deletions
@@ -4,12 +4,14 @@ import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:model/account/authentication_type.dart';
import 'package:tmail_ui_user/features/base/base_controller.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/domain/state/get_credential_state.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart';
import 'package:tmail_ui_user/features/login/domain/usecases/get_credential_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.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/routes/app_routes.dart';
@@ -23,7 +25,9 @@ abstract class ReloadableController extends BaseController {
final DeleteCredentialInteractor _deleteCredentialInteractor = Get.find<DeleteCredentialInteractor>();
final CachingManager _cachingManager = Get.find<CachingManager>();
ReloadableController();
final LogoutOidcInteractor _logoutOidcInteractor;
ReloadableController(this._logoutOidcInteractor);
@override
void onData(Either<Failure, Success> newState) {
@@ -93,13 +97,23 @@ abstract class ReloadableController extends BaseController {
void handleReloaded(Session session) {}
void _clearAllCacheAction() async {
await _cachingManager.clearAll();
}
void logoutAction() {
_deleteCredentialAction();
_clearAllCacheAction();
void logoutAction() async {
final authenticationType = _authorizationInterceptors.authenticationType;
if (authenticationType == AuthenticationType.oidc) {
await _logoutOidcInteractor.execute()
.then((value) async {
await Future.wait([
_deleteCredentialInteractor.execute(),
_cachingManager.clearAll(),
]);
});
} else {
await Future.wait([
_deleteCredentialInteractor.execute(),
_cachingManager.clearAll(),
]);
}
_authorizationInterceptors.clear();
goToLogin();
}
}
@@ -23,5 +23,5 @@ abstract class AuthenticationOIDCDataSource {
List<String> scopes,
String refreshToken);
Future<void> logout(TokenId tokenId, OIDCConfiguration config);
Future<bool> logout(TokenId tokenId, OIDCConfiguration config);
}
@@ -71,7 +71,11 @@ class AuthenticationOIDCDataSourceImpl extends AuthenticationOIDCDataSource {
}
@override
Future<void> logout(TokenId tokenId, OIDCConfiguration config) {
throw UnimplementedError();
Future<bool> logout(TokenId tokenId, OIDCConfiguration config) {
return Future.sync(() async {
return await _oidcHttpClient.logoutOidc(tokenId, config);
}).catchError((error) {
throw error;
});
}
}
@@ -51,6 +51,8 @@ class AuthorizationInterceptors extends InterceptorsWrapper {
OIDCConfiguration? get oidcConfig => _configOIDC;
AuthenticationType get authenticationType => _authenticationType;
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
switch(_authenticationType) {
@@ -8,6 +8,7 @@ import 'package:flutter_appauth/flutter_appauth.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_id.dart';
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/service_path_extension.dart';
@@ -98,4 +99,14 @@ class OIDCHttpClient {
throw NotFoundAccessTokenException();
}
}
Future<bool> logoutOidc(TokenId tokenId, OIDCConfiguration config) async {
final endSession = await _appAuth.endSession(EndSessionRequest(
idTokenHint: tokenId.uuid,
postLogoutRedirectUrl: config.redirectUrl,
discoveryUrl: config.discoveryUrl
));
log('OIDCHttpClient::logoutOidc(): ${endSession?.state}');
return endSession?.state?.isNotEmpty == true;
}
}
@@ -63,7 +63,7 @@ class AuthenticationOIDCRepositoryImpl extends AuthenticationOIDCRepository {
}
@override
Future<void> logout(TokenId tokenId, OIDCConfiguration config) {
throw UnimplementedError();
Future<bool> logout(TokenId tokenId, OIDCConfiguration config) {
return _oidcDataSource.logout(tokenId, config);
}
}
@@ -23,5 +23,5 @@ abstract class AuthenticationOIDCRepository {
List<String> scopes,
String refreshToken);
Future<void> logout(TokenId tokenId, OIDCConfiguration config);
Future<bool> logout(TokenId tokenId, OIDCConfiguration config);
}
@@ -24,6 +24,7 @@ class GetAuthenticatedAccountInteractor {
try {
yield Right<Failure, Success>(LoadingState());
final account = await _accountRepository.getCurrentAccount();
log('GetAuthenticatedAccountInteractor::execute(): account: $account');
yield Right(GetAuthenticatedAccountSuccess(account));
if (account.authenticationType == AuthenticationType.oidc) {
yield* _getStoredTokenOidcInteractor.execute(account.id);
@@ -18,6 +18,7 @@ class GetStoredTokenOidcInteractor {
Stream<Either<Failure, Success>> execute(String tokenIdHash) async* {
try {
log('GetStoredTokenOidcInteractor::execute(): tokenIdHash: $tokenIdHash');
yield Right<Failure, Success>(LoadingState());
final futureValue = await Future.wait([
_credentialRepository.getBaseUrl(),
@@ -14,6 +14,18 @@ import 'package:tmail_ui_user/features/email/domain/repository/email_repository.
import 'package:tmail_ui_user/features/email/domain/usecases/delete_email_permanently_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/email_bindings.dart';
import 'package:tmail_ui_user/features/login/data/datasource/account_datasource.dart';
import 'package:tmail_ui_user/features/login/data/datasource/authentication_oidc_datasource.dart';
import 'package:tmail_ui_user/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart';
import 'package:tmail_ui_user/features/login/data/datasource_impl/hive_account_datasource_impl.dart';
import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.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/oidc_http_client.dart';
import 'package:tmail_ui_user/features/login/data/repository/account_repository_impl.dart';
import 'package:tmail_ui_user/features/login/data/repository/authentication_oidc_repository_impl.dart';
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/mailbox/data/datasource/mailbox_datasource.dart';
import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart';
@@ -36,6 +48,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_s
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_recent_search_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/thread/data/datasource/thread_datasource.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/local_thread_datasource_impl.dart';
import 'package:tmail_ui_user/features/thread/data/datasource_impl/thread_datasource_impl.dart';
@@ -58,6 +71,7 @@ class MailboxDashBoardBindings extends BaseBindings {
@override
void bindingsController() {
Get.put(MailboxDashBoardController(
Get.find<LogoutOidcInteractor>(),
Get.find<MoveToMailboxInteractor>(),
Get.find<DeleteEmailPermanentlyInteractor>(),
Get.find<SaveRecentSearchInteractor>(),
@@ -75,6 +89,8 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut<ThreadDataSource>(() => Get.find<ThreadDataSourceImpl>());
Get.lazyPut<StateDataSource>(() => Get.find<StateDataSourceImpl>());
Get.lazyPut<MailboxDataSource>(() => Get.find<MailboxDataSourceImpl>());
Get.lazyPut<AccountDatasource>(() => Get.find<HiveAccountDatasourceImpl>());
Get.lazyPut<AuthenticationOIDCDataSource>(() => Get.find<AuthenticationOIDCDataSourceImpl>());
}
@override
@@ -90,6 +106,12 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut(() => StateDataSourceImpl(Get.find<StateCacheClient>()));
Get.lazyPut(() => MailboxDataSourceImpl(Get.find<MailboxAPI>()));
Get.lazyPut(() => MailboxCacheDataSourceImpl(Get.find<MailboxCacheManager>()));
Get.lazyPut(() => HiveAccountDatasourceImpl(Get.find<AccountCacheManager>()));
Get.lazyPut(() => AuthenticationOIDCDataSourceImpl(
Get.find<OIDCHttpClient>(),
Get.find<TokenOidcCacheManager>(),
Get.find<OidcConfigurationCacheManager>()
));
}
@override
@@ -102,6 +124,10 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut(() => GetAllRecentSearchLatestInteractor(Get.find<SearchRepository>()));
Get.lazyPut(() => QuickSearchEmailInteractor(Get.find<ThreadRepository>()));
Get.lazyPut(() => MarkAsMailboxReadInteractor(Get.find<MailboxRepository>()));
Get.lazyPut(() => LogoutOidcInteractor(
Get.find<AccountRepository>(),
Get.find<AuthenticationOIDCRepository>(),
));
}
@override
@@ -110,6 +136,8 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.lazyPut<SearchRepository>(() => Get.find<SearchRepositoryImpl>());
Get.lazyPut<ThreadRepository>(() => Get.find<ThreadRepositoryImpl>());
Get.lazyPut<MailboxRepository>(() => Get.find<MailboxRepositoryImpl>());
Get.lazyPut<AccountRepository>(() => Get.find<AccountRepositoryImpl>());
Get.lazyPut<AuthenticationOIDCRepository>(() => Get.find<AuthenticationOIDCRepositoryImpl>());
}
@override
@@ -136,5 +164,7 @@ class MailboxDashBoardBindings extends BaseBindings {
Get.find<ThreadDataSource>(),
Get.find<EmailDataSource>(),
));
Get.lazyPut(() => AccountRepositoryImpl(Get.find<AccountDatasource>()));
Get.lazyPut(() => AuthenticationOIDCRepositoryImpl(Get.find<AuthenticationOIDCDataSource>()));
}
}
@@ -37,12 +37,10 @@ import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_int
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/model/recent_search.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_all_recent_search_latest_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/mark_as_mailbox_read_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/quick_search_email_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/remove_email_drafts_state.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_all_recent_search_latest_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/mark_as_mailbox_read_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/quick_search_email_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/remove_email_drafts_interactor.dart';
@@ -50,6 +48,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/domain/usecases/save_re
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/action/dashboard_action.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/email_receive_time_type.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/model/quick_search_filter.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/manage_account_arguments.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/domain/model/filter_message_option.dart';
@@ -65,7 +64,6 @@ import 'package:tmail_ui_user/main/utils/email_receive_manager.dart';
class MailboxDashBoardController extends ReloadableController {
final GetUserProfileInteractor _getUserProfileInteractor = Get.find<GetUserProfileInteractor>();
final AppToast _appToast = Get.find<AppToast>();
final ImagePaths _imagePaths = Get.find<ImagePaths>();
final RemoveEmailDraftsInteractor _removeEmailDraftsInteractor = Get.find<RemoveEmailDraftsInteractor>();
@@ -106,13 +104,14 @@ class MailboxDashBoardController extends ReloadableController {
late StreamSubscription _emailReceiveManagerStreamSubscription;
MailboxDashBoardController(
LogoutOidcInteractor logoutOidcInteractor,
this._moveToMailboxInteractor,
this._deleteEmailPermanentlyInteractor,
this._saveRecentSearchInteractor,
this._getAllRecentSearchLatestInteractor,
this._quickSearchEmailInteractor,
this._markAsMailboxReadInteractor,
);
) : super(logoutOidcInteractor);
@override
void onInit() {
@@ -0,0 +1,20 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
class LogoutOidcSuccess extends UIState {
LogoutOidcSuccess();
@override
List<Object> get props => [];
}
class LogoutOidcFailure extends FeatureFailure {
final dynamic exception;
LogoutOidcFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -0,0 +1,48 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:model/account/authentication_type.dart';
import 'package:model/oidc/oidc_configuration.dart';
import 'package:model/oidc/token_oidc.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
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/manage_account/domain/state/log_out_oidc_state.dart';
class LogoutOidcInteractor {
final AccountRepository _accountRepository;
final AuthenticationOIDCRepository _authenticationOIDCRepository;
LogoutOidcInteractor(this._accountRepository, this._authenticationOIDCRepository);
Future<Either<Failure, Success>> execute() async {
try {
final currentAccount = await _accountRepository.getCurrentAccount();
if (currentAccount.authenticationType == AuthenticationType.oidc) {
final result = await Future.wait([
_authenticationOIDCRepository.getStoredTokenOIDC(currentAccount.id),
_authenticationOIDCRepository.getStoredOidcConfiguration()
]).then((result) async {
final tokenOidc = result.first as TokenOIDC;
final oidcConfig = result.last as OIDCConfiguration;
return await _authenticationOIDCRepository.logout(tokenOidc.tokenId, oidcConfig);
});
log('LogoutOidcInteractor::execute(): statusSuccess: $result');
if (result) {
return Right<Failure, Success>(LogoutOidcSuccess());
} else {
return Left<Failure, Success>(LogoutOidcFailure(null));
}
} else {
return Left<Failure, Success>(LogoutOidcFailure(NotFoundAuthenticatedAccountException()));
}
} catch (e) {
log('LogoutOidcInteractor::execute(): EXCEPTION: $e');
return Left<Failure, Success>(LogoutOidcFailure(e));
}
}
}
@@ -1,7 +1,20 @@
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/login/data/datasource/account_datasource.dart';
import 'package:tmail_ui_user/features/login/data/datasource/authentication_oidc_datasource.dart';
import 'package:tmail_ui_user/features/login/data/datasource_impl/authentication_oidc_datasource_impl.dart';
import 'package:tmail_ui_user/features/login/data/datasource_impl/hive_account_datasource_impl.dart';
import 'package:tmail_ui_user/features/login/data/local/account_cache_manager.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/oidc_http_client.dart';
import 'package:tmail_ui_user/features/login/data/repository/account_repository_impl.dart';
import 'package:tmail_ui_user/features/login/data/repository/authentication_oidc_repository_impl.dart';
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/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/menu/manage_account_menu_bindings.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/profiles/profiles_bindings.dart';
@@ -17,27 +30,43 @@ class ManageAccountDashBoardBindings extends BaseBindings {
@override
void bindingsController() {
Get.lazyPut(() => ManageAccountDashBoardController());
Get.lazyPut(() => ManageAccountDashBoardController(Get.find<LogoutOidcInteractor>()));
}
@override
void bindingsDataSource() {
Get.lazyPut<AccountDatasource>(() => Get.find<HiveAccountDatasourceImpl>());
Get.lazyPut<AuthenticationOIDCDataSource>(() => Get.find<AuthenticationOIDCDataSourceImpl>());
}
@override
void bindingsDataSourceImpl() {
Get.lazyPut(() => HiveAccountDatasourceImpl(Get.find<AccountCacheManager>()));
Get.lazyPut(() => AuthenticationOIDCDataSourceImpl(
Get.find<OIDCHttpClient>(),
Get.find<TokenOidcCacheManager>(),
Get.find<OidcConfigurationCacheManager>()
));
}
@override
void bindingsInteractor() {
Get.lazyPut(() => GetUserProfileInteractor(Get.find<CredentialRepository>()));
Get.lazyPut(() => LogoutOidcInteractor(
Get.find<AccountRepository>(),
Get.find<AuthenticationOIDCRepository>(),
));
}
@override
void bindingsRepository() {
Get.lazyPut<AccountRepository>(() => Get.find<AccountRepositoryImpl>());
Get.lazyPut<AuthenticationOIDCRepository>(() => Get.find<AuthenticationOIDCRepositoryImpl>());
}
@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => AccountRepositoryImpl(Get.find<AccountDatasource>()));
Get.lazyPut(() => AuthenticationOIDCRepositoryImpl(Get.find<AuthenticationOIDCDataSource>()));
}
}
@@ -9,6 +9,7 @@ import 'package:model/model.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:tmail_ui_user/features/base/reloadable/reloadable_controller.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/domain/state/get_user_profile_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/log_out_oidc_interactor.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart';
import 'package:tmail_ui_user/features/manage_account/presentation/model/manage_account_arguments.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
@@ -27,7 +28,9 @@ class ManageAccountDashBoardController extends ReloadableController {
Session? sessionCurrent;
ManageAccountDashBoardController();
ManageAccountDashBoardController(
LogoutOidcInteractor logoutOidcInteractor
) : super(logoutOidcInteractor);
@override
void onReady() {
+2
View File
@@ -24,6 +24,8 @@ class OIDCConfiguration with EquatableMixin {
}
}
String get clientIdHash => clientId.hashCode.toString();
@override
List<Object?> get props => [
authority,