From 274e01d11396c41fd7bf7a645ca9fb734c726ea6 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 17 Jan 2024 13:20:59 +0700 Subject: [PATCH] TF-2464 Save both `EmailDelivery` and `EmailState` in the keychain Signed-off-by: dab246 (cherry picked from commit a37fe7ea8bcc38eb96df39f46128c9e1f7af046e) --- .../Keychain/KeyChainControllerDelegate.swift | 2 +- .../Keychain/KeychainController.swift | 4 +- .../Model/KeychainSharingSession.swift | 7 ++- ios/TwakeMailNSE/NotificationService.swift | 23 ++++--- .../state_datasource_impl.dart | 2 +- .../keychain_sharing_session_extension.dart | 5 +- .../keychain/keychain_sharing_session.dart | 3 + .../listener/email_change_listener.dart | 6 +- lib/main/utils/ios_sharing_manager.dart | 62 +++++++++++++------ 9 files changed, 74 insertions(+), 40 deletions(-) diff --git a/ios/TwakeMailNSE/Keychain/KeyChainControllerDelegate.swift b/ios/TwakeMailNSE/Keychain/KeyChainControllerDelegate.swift index 5143f7fe5..e7f6b9827 100644 --- a/ios/TwakeMailNSE/Keychain/KeyChainControllerDelegate.swift +++ b/ios/TwakeMailNSE/Keychain/KeyChainControllerDelegate.swift @@ -8,5 +8,5 @@ struct KeychainCredentials { protocol KeychainControllerDelegate: AnyObject { func retrieveSharingSessionFromKeychain(accountId: String) -> KeychainSharingSession? func retrieveSharingSessions() -> [KeychainCredentials] - func updateEmailStateToKeychain(accountId: String, newState: String) + func updateEmailDeliveryStateToKeychain(accountId: String, newEmailDeliveryState: String) } diff --git a/ios/TwakeMailNSE/Keychain/KeychainController.swift b/ios/TwakeMailNSE/Keychain/KeychainController.swift index a5bd00c6e..a2bacbf4b 100644 --- a/ios/TwakeMailNSE/Keychain/KeychainController.swift +++ b/ios/TwakeMailNSE/Keychain/KeychainController.swift @@ -40,10 +40,10 @@ class KeychainController: KeychainControllerDelegate { } } - func updateEmailStateToKeychain(accountId: String, newState: String) { + func updateEmailDeliveryStateToKeychain(accountId: String, newEmailDeliveryState: String) { do { if let sharingSession = retrieveSharingSessionFromKeychain(accountId: accountId) { - let newSharingSession = sharingSession.updateEmailState(newState: newState) + let newSharingSession = sharingSession.updateEmailDeliveryState(newEmailDeliveryState: newEmailDeliveryState) try keychain.set(newSharingSession.toJson() ?? "", key: accountId) } } catch {} diff --git a/ios/TwakeMailNSE/Model/KeychainSharingSession.swift b/ios/TwakeMailNSE/Model/KeychainSharingSession.swift index 0a00c88d4..47bd690b4 100644 --- a/ios/TwakeMailNSE/Model/KeychainSharingSession.swift +++ b/ios/TwakeMailNSE/Model/KeychainSharingSession.swift @@ -6,6 +6,7 @@ struct KeychainSharingSession: Codable { let authenticationType: AuthenticationType let apiUrl: String let emailState: String? + let emailDeliveryState: String? let tokenOIDC: TokenOidc? let basicAuth: String? let tokenEndpoint: String? @@ -13,13 +14,14 @@ struct KeychainSharingSession: Codable { } extension KeychainSharingSession { - func updateEmailState(newState: String) -> KeychainSharingSession { + func updateEmailDeliveryState(newEmailDeliveryState: String) -> KeychainSharingSession { return KeychainSharingSession( accountId: self.accountId, userName: self.userName, authenticationType: self.authenticationType, apiUrl: self.apiUrl, - emailState: newState, + emailState: emailState, + emailDeliveryState: newEmailDeliveryState, tokenOIDC: self.tokenOIDC, basicAuth: self.basicAuth, tokenEndpoint: self.tokenEndpoint, @@ -34,6 +36,7 @@ extension KeychainSharingSession { authenticationType: self.authenticationType, apiUrl: self.apiUrl, emailState: self.emailState, + emailDeliveryState: self.emailDeliveryState, tokenOIDC: TokenOidc( token: newTokenOidc.token, tokenId: newTokenOidc.tokenId, diff --git a/ios/TwakeMailNSE/NotificationService.swift b/ios/TwakeMailNSE/NotificationService.swift index 07a492cb0..1c860443d 100644 --- a/ios/TwakeMailNSE/NotificationService.swift +++ b/ios/TwakeMailNSE/NotificationService.swift @@ -21,7 +21,7 @@ class NotificationService: UNNotificationServiceExtension { guard let payloadData = request.content.userInfo as? [String: Any], !keychainController.retrieveSharingSessions().isEmpty else { - self.modifiedContent?.body = NSLocalizedString(newEmailDefaultMessageKey, comment: "Localizable") + self.modifiedContent?.body = NSLocalizedString(newNotificationDefaultMessageKey, comment: "Localizable") return self.notify() } @@ -46,24 +46,28 @@ class NotificationService: UNNotificationServiceExtension { let mapStateChanges: [String: [TypeName: String]] = PayloadParser.shared.parsingPayloadNotification(payloadData: payloadData) if (mapStateChanges.isEmpty) { - self.modifiedContent?.body = NSLocalizedString(newEmailDefaultMessageKey, comment: "Localizable") + self.modifiedContent?.body = NSLocalizedString(newNotificationDefaultMessageKey, comment: "Localizable") return self.notify() } else { guard let currentAccountId = mapStateChanges.keys.first, let keychainSharingSession = keychainController.retrieveSharingSessionFromKeychain(accountId: currentAccountId), + keychainSharingSession.tokenOIDC != nil || keychainSharingSession.basicAuth != nil, let listStateOfAccount = mapStateChanges[currentAccountId], - let newEmailState = listStateOfAccount[TypeName.emailDelivery], - let oldEmailState = keychainSharingSession.emailState, - newEmailState != oldEmailState, - keychainSharingSession.tokenOIDC != nil || keychainSharingSession.basicAuth != nil else { + let newEmailDeliveryState = listStateOfAccount[TypeName.emailDelivery] else { self.modifiedContent?.body = NSLocalizedString(newNotificationDefaultMessageKey, comment: "Localizable") return self.notify() } + guard let oldEmailDeliveryState = keychainSharingSession.emailDeliveryState ?? keychainSharingSession.emailState, + newEmailDeliveryState != oldEmailDeliveryState else { + self.modifiedContent?.body = NSLocalizedString(newEmailDefaultMessageKey, comment: "Localizable") + return self.notify() + } + JmapClient.shared.getNewEmails( apiUrl: keychainSharingSession.apiUrl, accountId: keychainSharingSession.accountId, - sinceState: oldEmailState, + sinceState: oldEmailDeliveryState, authenticationType: keychainSharingSession.authenticationType, tokenOidc: keychainSharingSession.tokenOIDC, basicAuth: keychainSharingSession.basicAuth, @@ -74,7 +78,10 @@ class NotificationService: UNNotificationServiceExtension { self.modifiedContent?.body = NSLocalizedString(self.newNotificationDefaultMessageKey, comment: "Localizable") return self.notify() } else { - self.keychainController.updateEmailStateToKeychain(accountId: keychainSharingSession.accountId, newState: newEmailState) + self.keychainController.updateEmailDeliveryStateToKeychain( + accountId: keychainSharingSession.accountId, + newEmailDeliveryState: newEmailDeliveryState + ) if (emails.count > 1) { for email in emails { diff --git a/lib/features/mailbox/data/datasource_impl/state_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/state_datasource_impl.dart index 3539ad7c5..bb3fb3897 100644 --- a/lib/features/mailbox/data/datasource_impl/state_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/state_datasource_impl.dart @@ -36,7 +36,7 @@ class StateDataSourceImpl extends StateDataSource { if (PlatformInfo.isIOS && stateCache.type == StateType.email) { final emailDeliveryStateKeychain = await _iosSharingManager.getEmailDeliveryStateFromKeychain(accountId); if (emailDeliveryStateKeychain == null || emailDeliveryStateKeychain.isEmpty) { - await _iosSharingManager.updateEmailDeliveryStateInKeyChain(accountId, stateCache.state); + await _iosSharingManager.updateEmailStateInKeyChain(accountId, stateCache.state); } } return Future.value(null); diff --git a/lib/features/push_notification/data/extensions/keychain_sharing_session_extension.dart b/lib/features/push_notification/data/extensions/keychain_sharing_session_extension.dart index cb5d67d9d..5b603b070 100644 --- a/lib/features/push_notification/data/extensions/keychain_sharing_session_extension.dart +++ b/lib/features/push_notification/data/extensions/keychain_sharing_session_extension.dart @@ -3,13 +3,14 @@ import 'package:tmail_ui_user/features/push_notification/data/keychain/keychain_ extension KeychainSharingSessionExtension on KeychainSharingSession { - KeychainSharingSession updating({String? emailDeliveryState}) { + KeychainSharingSession updating({String? emailState, String? emailDeliveryState}) { return KeychainSharingSession( accountId: accountId, userName: userName, authenticationType: authenticationType, apiUrl: apiUrl, - emailState: emailDeliveryState ?? emailDeliveryState, + emailState: emailState ?? emailState, + emailDeliveryState: emailDeliveryState ?? emailDeliveryState, tokenOIDC: tokenOIDC, basicAuth: basicAuth, tokenEndpoint: tokenEndpoint, diff --git a/lib/features/push_notification/data/keychain/keychain_sharing_session.dart b/lib/features/push_notification/data/keychain/keychain_sharing_session.dart index e0e6666dc..2847726b0 100644 --- a/lib/features/push_notification/data/keychain/keychain_sharing_session.dart +++ b/lib/features/push_notification/data/keychain/keychain_sharing_session.dart @@ -18,6 +18,7 @@ class KeychainSharingSession with EquatableMixin { AuthenticationType authenticationType; String apiUrl; String? emailState; + String? emailDeliveryState; TokenOIDC? tokenOIDC; String? basicAuth; String? tokenEndpoint; @@ -29,6 +30,7 @@ class KeychainSharingSession with EquatableMixin { required this.authenticationType, required this.apiUrl, this.emailState, + this.emailDeliveryState, this.tokenOIDC, this.basicAuth, this.tokenEndpoint, @@ -46,6 +48,7 @@ class KeychainSharingSession with EquatableMixin { authenticationType, apiUrl, emailState, + emailDeliveryState, tokenOIDC, basicAuth, tokenEndpoint, diff --git a/lib/features/push_notification/presentation/listener/email_change_listener.dart b/lib/features/push_notification/presentation/listener/email_change_listener.dart index a3d8f21ac..a929e93ec 100644 --- a/lib/features/push_notification/presentation/listener/email_change_listener.dart +++ b/lib/features/push_notification/presentation/listener/email_change_listener.dart @@ -333,10 +333,6 @@ class EmailChangeListener extends ChangeListener { if (_iosSharingManager == null) { return; } - - final emailDeliveryStateKeychain = await _iosSharingManager!.getEmailDeliveryStateFromKeychain(accountId); - if (emailDeliveryStateKeychain == null || emailDeliveryStateKeychain.isEmpty) { - await _iosSharingManager!.updateEmailDeliveryStateInKeyChain(accountId, emailDeliveryState); - } + await _iosSharingManager!.updateEmailDeliveryStateInKeyChain(accountId, emailDeliveryState); } } \ No newline at end of file diff --git a/lib/main/utils/ios_sharing_manager.dart b/lib/main/utils/ios_sharing_manager.dart index b456ae5a5..e42d4f335 100644 --- a/lib/main/utils/ios_sharing_manager.dart +++ b/lib/main/utils/ios_sharing_manager.dart @@ -36,11 +36,8 @@ class IOSSharingManager { Future getEmailDeliveryStateFromKeychain(AccountId accountId) async { try { - if (await _keychainSharingManager.isSessionExist(accountId)) { - final keychainSharingStored = await _keychainSharingManager.getSharingSession(accountId); - return keychainSharingStored?.emailState; - } - return null; + final keychainSharingStored = await getKeychainSharingSession(accountId); + return keychainSharingStored?.emailDeliveryState; } catch (e) { logError('IOSSharingManager::_getEmailDeliveryStateFromKeychain: Exception: $e'); return null; @@ -67,12 +64,18 @@ class IOSSharingManager { userName: personalAccount.userName! ); + final emailState = await _getEmailState( + accountId: personalAccount.accountId!, + userName: personalAccount.userName! + ); + final keychainSharingSession = KeychainSharingSession( accountId: personalAccount.accountId!, userName: personalAccount.userName!, authenticationType: personalAccount.authenticationType, apiUrl: personalAccount.apiUrl!, - emailState: emailDeliveryState, + emailState: emailState, + emailDeliveryState: emailDeliveryState, tokenOIDC: authenticationInfo.value1, basicAuth: authenticationInfo.value2 ); @@ -123,15 +126,8 @@ class IOSSharingManager { required UserName userName }) async { try { - String? emailDeliveryState = await getEmailDeliveryStateFromKeychain(accountId); - if (emailDeliveryState == null || emailDeliveryState.isEmpty) { - final emailState = await _stateCacheManager.getState( - accountId, - userName, - StateType.email - ); - emailDeliveryState = emailState?.value; - } + final emailDeliveryState = await getEmailDeliveryStateFromKeychain(accountId); + log('IOSSharingManager::_getEmailState:emailDeliveryState: $emailDeliveryState'); return emailDeliveryState; } catch (e) { logError('IOSSharingManager::_getEmailDeliveryState:Exception: $e'); @@ -139,13 +135,41 @@ class IOSSharingManager { } } + Future _getEmailState({ + required AccountId accountId, + required UserName userName + }) async { + try { + final emailState = await _stateCacheManager.getState( + accountId, + userName, + StateType.email + ); + log('IOSSharingManager::_getEmailState:emailState: $emailState'); + return emailState?.value; + } catch (e) { + logError('IOSSharingManager::_getEmailState:Exception: $e'); + return null; + } + } + Future updateEmailDeliveryStateInKeyChain(AccountId accountId, String newEmailDeliveryState) async { - final keychainSharingSession = await getKeychainSharingSession(accountId); - log('IOSSharingManager::updateEmailDeliveryStateInKeyChain:keychainSharingSession: $keychainSharingSession'); - if (keychainSharingSession == null) { + final keychainSharingStored = await getKeychainSharingSession(accountId); + log('IOSSharingManager::updateEmailDeliveryStateInKeyChain:keychainSharingStored: $keychainSharingStored | newEmailDeliveryState: $newEmailDeliveryState'); + if (keychainSharingStored == null) { return; } - final newKeychain = keychainSharingSession.updating(emailDeliveryState: newEmailDeliveryState); + final newKeychain = keychainSharingStored.updating(emailDeliveryState: newEmailDeliveryState); + await _keychainSharingManager.save(newKeychain); + } + + Future updateEmailStateInKeyChain(AccountId accountId, String newEmailState) async { + final keychainSharingStored = await getKeychainSharingSession(accountId); + log('IOSSharingManager::updateEmailStateInKeyChain:keychainSharingStored: $keychainSharingStored | newEmailState: $newEmailState'); + if (keychainSharingStored == null) { + return; + } + final newKeychain = keychainSharingStored.updating(emailState: newEmailState); await _keychainSharingManager.save(newKeychain); } } \ No newline at end of file