From c48d7b79df9866414034e02001cce0464e3f5dca Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 7 Dec 2021 19:16:22 +0300 Subject: [PATCH 1/2] Fatal error message is shown when cancelling Google login --- .../Functionality/Services/GlobalRouter.swift | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/FlowCrypt/Functionality/Services/GlobalRouter.swift b/FlowCrypt/Functionality/Services/GlobalRouter.swift index 0fe280d4e..5609ddcd5 100644 --- a/FlowCrypt/Functionality/Services/GlobalRouter.swift +++ b/FlowCrypt/Functionality/Services/GlobalRouter.swift @@ -79,7 +79,7 @@ extension GlobalRouter: GlobalRouterType { } } catch { logger.logError("Failed to sign in due to \(error.localizedDescription)") - handle(error: error, appContext: appContext) + handleSignInError(error: error, appContext: appContext) } } @@ -95,7 +95,7 @@ extension GlobalRouter: GlobalRouterType { } } catch { logger.logError("Failed to sign out due to \(error.localizedDescription)") - handle(error: error, appContext: appContext) + hanleFatalError(error) } } @@ -134,7 +134,7 @@ extension GlobalRouter: GlobalRouterType { proceed(with: appContext.withSession(session)) } catch { logger.logError("Failed to switch active user due to \(error.localizedDescription)") - handle(error: error, appContext: appContext) + hanleFatalError(error) } } @@ -157,15 +157,32 @@ extension GlobalRouter: GlobalRouterType { } @MainActor - private func handle(error: Error, appContext: AppContext) { - if let gmailUserError = error as? GoogleUserServiceError, - case .userNotAllowedAllNeededScopes = gmailUserError { - logger.logInfo("gmail login failed with error \(gmailUserError.errorMessage)") - let navigationController = keyWindow.rootViewController?.navigationController - let checkAuthViewController = CheckMailAuthViewController(appContext: appContext) - navigationController?.pushViewController(checkAuthViewController, animated: true) - } else { - keyWindow.rootViewController = FatalErrorViewController(error: error) + private func handleSignInError(error: Error, appContext: AppContext) { + if let gmailUserError = error as? GoogleUserServiceError { + logger.logInfo("Gmail login failed with error: \(gmailUserError.errorMessage)") + + if case .cancelledAuthorization = gmailUserError { + proceed() + return + } + + if case .userNotAllowedAllNeededScopes = gmailUserError { + let navigationController = keyWindow.rootViewController?.navigationController + let checkAuthViewController = CheckMailAuthViewController(appContext: appContext) + navigationController?.pushViewController(checkAuthViewController, animated: true) + return + } } + + keyWindow.rootViewController?.showAlert( + title: "error".localized, + message: error.localizedDescription, + onOk: { [weak self] in self?.proceed() } + ) + } + + @MainActor + private func hanleFatalError(_ error: Error) { + keyWindow.rootViewController = FatalErrorViewController(error: error) } } From 97f64c9d215fc69ba526e9155a7dead540b2ecf5 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 9 Dec 2021 19:08:36 +0300 Subject: [PATCH 2/2] Code review fixes --- FlowCrypt.xcodeproj/project.pbxproj | 4 - .../Bootstrap/FatalErrorViewController.swift | 96 ------------------- .../Setup/SetupBackupsViewController.swift | 6 +- ...eatePassphraseAbstractViewController.swift | 6 +- .../Setup/SetupInitialViewController.swift | 19 ++-- .../SideMenu/Menu/MyMenuViewController.swift | 12 ++- .../Functionality/Services/GlobalRouter.swift | 45 +++------ 7 files changed, 45 insertions(+), 143 deletions(-) delete mode 100644 FlowCrypt/Controllers/Bootstrap/FatalErrorViewController.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index a8be82e02..25c44049c 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -37,7 +37,6 @@ 2C141B2F274578C20038A3F8 /* KeyInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C141B2E274578C20038A3F8 /* KeyInfo.swift */; }; 2C2A3B4B2719EE6100B7F27B /* KeyServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2A3B4A2719EE6100B7F27B /* KeyServiceTests.swift */; }; 2C2A3B4D2719EF7300B7F27B /* PassPhraseServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C2A3B4C2719EF7300B7F27B /* PassPhraseServiceMock.swift */; }; - 2C339B07275CB136005DEA79 /* FatalErrorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C339B06275CB136005DEA79 /* FatalErrorViewController.swift */; }; 2C4E60F72757D91A00DE5770 /* EncryptedStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4E60F62757D91A00DE5770 /* EncryptedStorageMock.swift */; }; 2C60AB0C272564D40040D7F2 /* InvalidStorageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */; }; 2CAF25322756C37E005C7C7C /* AppContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAF25312756C37E005C7C7C /* AppContext.swift */; }; @@ -451,7 +450,6 @@ 2C141B2E274578C20038A3F8 /* KeyInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyInfo.swift; sourceTree = ""; }; 2C2A3B4A2719EE6100B7F27B /* KeyServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyServiceTests.swift; sourceTree = ""; }; 2C2A3B4C2719EF7300B7F27B /* PassPhraseServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhraseServiceMock.swift; sourceTree = ""; }; - 2C339B06275CB136005DEA79 /* FatalErrorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FatalErrorViewController.swift; sourceTree = ""; }; 2C4E60F62757D91A00DE5770 /* EncryptedStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedStorageMock.swift; sourceTree = ""; }; 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvalidStorageViewController.swift; sourceTree = ""; }; 2CAF25312756C37E005C7C7C /* AppContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppContext.swift; sourceTree = ""; }; @@ -1963,7 +1961,6 @@ isa = PBXGroup; children = ( D24F4C2123E2359B00C5EEE4 /* BootstrapViewController.swift */, - 2C339B06275CB136005DEA79 /* FatalErrorViewController.swift */, 2C60AB0B272564D40040D7F2 /* InvalidStorageViewController.swift */, ); path = Bootstrap; @@ -2537,7 +2534,6 @@ D2A9CA3D242619EC00E1D898 /* SignInViewDecorator.swift in Sources */, 9F4300CC2571045B00791CFB /* InboxViewControllerContainerDecorator.swift in Sources */, 9F4163E6266520B600106194 /* CommonNodesInputs.swift in Sources */, - 2C339B07275CB136005DEA79 /* FatalErrorViewController.swift in Sources */, 9F883912271F242900669B56 /* ThreadDetailsDecorator.swift in Sources */, 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */, 51B4AE5327144E590001F33B /* PubKey.swift in Sources */, diff --git a/FlowCrypt/Controllers/Bootstrap/FatalErrorViewController.swift b/FlowCrypt/Controllers/Bootstrap/FatalErrorViewController.swift deleted file mode 100644 index 1535fea65..000000000 --- a/FlowCrypt/Controllers/Bootstrap/FatalErrorViewController.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// FatalErrorViewController.swift -// FlowCrypt -// -// Created by  Ivan Ushakov on 05.12.2021 -// Copyright © 2017-present FlowCrypt a. s. All rights reserved. -// - -import FlowCryptUI -import AsyncDisplayKit - -final class FatalErrorViewController: TableNodeViewController { - private enum Parts: Int, CaseIterable { - case screenTitle - case title - case description - } - - private let error: Error - - init(error: Error) { - self.error = error - super.init(node: TableNode()) - } - - @available(*, unavailable) - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() - view.backgroundColor = .backgroundColor - - node.delegate = self - node.dataSource = self - node.bounces = false - node.reloadData() - } -} - -extension FatalErrorViewController: ASTableDelegate, ASTableDataSource { - func tableNode(_: ASTableNode, numberOfRowsInSection _: Int) -> Int { - Parts.allCases.count - } - - func tableNode(_ node: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock { - return { [weak self] in - guard let self = self, let part = Parts(rawValue: indexPath.row) else { - return ASCellNode() - } - - let insets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) - switch part { - case .screenTitle: - return SetupTitleNode( - SetupTitleNode.Input( - title: "fatal_error_screen_title".localized - .attributed( - .bold(18), - color: .mainTextColor, - alignment: .center - ), - insets: insets, - backgroundColor: .backgroundColor - ) - ) - case .title: - return SetupTitleNode( - SetupTitleNode.Input( - title: "fatal_error_screen_text".localized - .attributed( - .regular(16), - color: .mainTextColor, - alignment: .center - ), - insets: insets, - backgroundColor: .backgroundColor - ) - ) - case .description: - return SetupTitleNode( - SetupTitleNode.Input( - title: self.error.localizedDescription.attributed( - .regular(16), - color: .mainTextColor, - alignment: .center - ), - insets: insets, - backgroundColor: .backgroundColor - ) - ) - } - } - } -} diff --git a/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift b/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift index 1b0bfbaf5..4d082919d 100644 --- a/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift @@ -173,7 +173,11 @@ extension SetupBackupsViewController { } func handleBackButtonTap() { - appContext.globalRouter.signOut(appContext: appContext) + do { + try appContext.globalRouter.signOut(appContext: appContext) + } catch { + showAlert(message: error.localizedDescription) + } } private func moveToMainFlow() { diff --git a/FlowCrypt/Controllers/Setup/SetupCreatePassphraseAbstractViewController.swift b/FlowCrypt/Controllers/Setup/SetupCreatePassphraseAbstractViewController.swift index 40995ef16..913d82a50 100644 --- a/FlowCrypt/Controllers/Setup/SetupCreatePassphraseAbstractViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupCreatePassphraseAbstractViewController.swift @@ -87,7 +87,11 @@ class SetupCreatePassphraseAbstractViewController: TableNodeViewController, Pass } func handleBackButtonTap() { - appContext.globalRouter.signOut(appContext: self.appContext) + do { + try appContext.globalRouter.signOut(appContext: self.appContext) + } catch { + showAlert(message: error.localizedDescription) + } } } diff --git a/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift b/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift index a81d12356..af2f73314 100644 --- a/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupInitialViewController.swift @@ -131,8 +131,12 @@ extension SetupInitialViewController { } } - private func handleOtherAccount() { - appContext.globalRouter.signOut(appContext: appContext) + private func signOut() { + do { + try appContext.globalRouter.signOut(appContext: appContext) + } catch { + showAlert(message: error.localizedDescription) + } } private func handle(error: Error) { @@ -148,8 +152,7 @@ extension SetupInitialViewController { state = .searchingKeyBackupsInInbox case .inconsistentClientConfiguration(let error): showAlert(message: error.description) { [weak self] in - guard let self = self else { return } - self.appContext.globalRouter.signOut(appContext: self.appContext) + self?.signOut() } } } @@ -168,14 +171,12 @@ extension SetupInitialViewController { self?.state = .fetchingKeysFromEKM }, onOk: { [weak self] in - guard let self = self else { return } - self.appContext.globalRouter.signOut(appContext: self.appContext) + self?.signOut() } ) case .keysAreNotDecrypted: showAlert(message: "organisational_rules_ekm_keys_are_not_decrypted_error".localized, onOk: { [weak self] in - guard let self = self else { return } - self.appContext.globalRouter.signOut(appContext: self.appContext) + self?.signOut() }) } } catch { @@ -276,7 +277,7 @@ extension SetupInitialViewController { } case .anotherAccount: return ButtonCellNode(input: .chooseAnotherAccount) { [weak self] in - self?.handleOtherAccount() + self?.signOut() } } } diff --git a/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift b/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift index fe64c1d49..8ffb62fa6 100644 --- a/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift +++ b/FlowCrypt/Controllers/SideMenu/Menu/MyMenuViewController.swift @@ -221,7 +221,11 @@ extension MyMenuViewController { return } - appContext.globalRouter.switchActive(user: account, appContext: appContext) + do { + try appContext.globalRouter.switchActive(user: account, appContext: appContext) + } catch { + showAlert(message: error.localizedDescription) + } } } @@ -298,7 +302,11 @@ extension MyMenuViewController { } sideMenuController()?.setContentViewController(SettingsViewController(appContext: appContext)) case .logOut: - appContext.globalRouter.signOut(appContext: appContext) + do { + try appContext.globalRouter.signOut(appContext: appContext) + } catch { + showAlert(message: error.localizedDescription) + } } } diff --git a/FlowCrypt/Functionality/Services/GlobalRouter.swift b/FlowCrypt/Functionality/Services/GlobalRouter.swift index 5609ddcd5..6e6311478 100644 --- a/FlowCrypt/Functionality/Services/GlobalRouter.swift +++ b/FlowCrypt/Functionality/Services/GlobalRouter.swift @@ -14,8 +14,8 @@ protocol GlobalRouterType { func proceed() func signIn(appContext: AppContext, route: GlobalRoutingType) async func askForContactsPermission(for route: GlobalRoutingType, appContext: AppContext) async throws - func switchActive(user: User, appContext: AppContext) - func signOut(appContext: AppContext) + func switchActive(user: User, appContext: AppContext) throws + func signOut(appContext: AppContext) throws } enum GlobalRoutingType { @@ -83,19 +83,14 @@ extension GlobalRouter: GlobalRouterType { } } - func signOut(appContext: AppContext) { - do { - if let session = try appContext.userAccountService.startActiveSessionForNextUser() { - logger.logInfo("Start session for another email user \(session)") - proceed(with: appContext.withSession(session)) - } else { - logger.logInfo("Sign out") - appContext.userAccountService.cleanup() - proceed() - } - } catch { - logger.logError("Failed to sign out due to \(error.localizedDescription)") - hanleFatalError(error) + func signOut(appContext: AppContext) throws { + if let session = try appContext.userAccountService.startActiveSessionForNextUser() { + logger.logInfo("Start session for another email user \(session)") + proceed(with: appContext.withSession(session)) + } else { + logger.logInfo("Sign out") + appContext.userAccountService.cleanup() + proceed() } } @@ -124,18 +119,13 @@ extension GlobalRouter: GlobalRouterType { } } - func switchActive(user: User, appContext: AppContext) { + func switchActive(user: User, appContext: AppContext) throws { logger.logInfo("Switching active user \(user)") - do { - guard let session = try appContext.userAccountService.switchActiveSessionFor(user: user) else { - logger.logWarning("Can't switch active user with \(user.email)") - return - } - proceed(with: appContext.withSession(session)) - } catch { - logger.logError("Failed to switch active user due to \(error.localizedDescription)") - hanleFatalError(error) + guard let session = try appContext.userAccountService.switchActiveSessionFor(user: user) else { + logger.logWarning("Can't switch active user with \(user.email)") + return } + proceed(with: appContext.withSession(session)) } @MainActor @@ -180,9 +170,4 @@ extension GlobalRouter: GlobalRouterType { onOk: { [weak self] in self?.proceed() } ) } - - @MainActor - private func hanleFatalError(_ error: Error) { - keyWindow.rootViewController = FatalErrorViewController(error: error) - } }