Skip to content

Commit

Permalink
Merge pull request #329 from cryptomator/feature/hub-poc-3
Browse files Browse the repository at this point in the history
Improve Cryptomator Hub Authentication Flow
  • Loading branch information
tobihagemann committed Nov 24, 2023
2 parents a9405be + 1d749f7 commit bb5824b
Show file tree
Hide file tree
Showing 47 changed files with 1,224 additions and 310 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ on:
jobs:
build:
name: Build and test
runs-on: macos-12
runs-on: macos-13
env:
DERIVED_DATA_PATH: 'DerivedData'
DEVICE: 'iPhone 12 Pro'
DEVICE: 'iPhone 14 Pro'
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
strategy:
matrix:
Expand Down
58 changes: 26 additions & 32 deletions Cryptomator/AddVault/Hub/HubAddVaultCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class AddHubVaultCoordinator: Coordinator {
let vaultUID: String
let accountUID: String
let vaultItem: VaultItem
let hubAuthenticator: HubAuthenticating
let vaultManager: VaultManager
weak var parentCoordinator: Coordinator?
weak var delegate: (VaultInstalling & AnyObject)?
Expand All @@ -33,54 +32,49 @@ class AddHubVaultCoordinator: Coordinator {
vaultUID: String,
accountUID: String,
vaultItem: VaultItem,
hubAuthenticator: HubAuthenticating,
vaultManager: VaultManager = VaultDBManager.shared) {
self.navigationController = navigationController
self.downloadedVaultConfig = downloadedVaultConfig
self.vaultUID = vaultUID
self.accountUID = accountUID
self.vaultItem = vaultItem
self.hubAuthenticator = hubAuthenticator
self.vaultManager = vaultManager
}

func start() {
let viewModel = HubAuthenticationViewModel(vaultConfig: downloadedVaultConfig.vaultConfig,
hubUserAuthenticator: self,
delegate: self)
let viewController = HubAuthenticationViewController(viewModel: viewModel)
navigationController.pushViewController(viewController, animated: true)
let unlockHandler = AddHubVaultUnlockHandler(vaultUID: vaultUID,
accountUID: accountUID, vaultItem: vaultItem,
downloadedVaultConfig: downloadedVaultConfig,
vaultManager: vaultManager,
delegate: self)
let child = HubAuthenticationCoordinator(navigationController: navigationController,
vaultConfig: downloadedVaultConfig.vaultConfig,
unlockHandler: unlockHandler,
parent: self,
delegate: self)
childCoordinators.append(child)
child.start()
}
}

extension AddHubVaultCoordinator: HubAuthenticationFlowDelegate {
func didSuccessfullyRemoteUnlock(_ response: HubUnlockResponse) async {
let jwe = response.jwe
let privateKey = response.privateKey
let hubVault = ExistingHubVault(vaultUID: vaultUID,
delegateAccountUID: accountUID,
jweData: jwe.compactSerializedData,
privateKey: privateKey,
vaultItem: vaultItem,
downloadedVaultConfig: downloadedVaultConfig)
do {
try await vaultManager.addExistingHubVault(hubVault).getValue()
childDidFinish(self)
await showSuccessfullyAddedVault()
} catch {
DDLogError("Add existing Hub vault failed: \(error)")
handleError(error, for: navigationController)
}
extension AddHubVaultCoordinator: HubVaultUnlockHandlerDelegate {
func successfullyProcessedUnlockedVault() {
delegate?.showSuccessfullyAddedVault(withName: vaultItem.name, vaultUID: vaultUID)
}

@MainActor
private func showSuccessfullyAddedVault() {
delegate?.showSuccessfullyAddedVault(withName: vaultItem.name, vaultUID: vaultUID)
func failedToProcessUnlockedVault(error: Error) {
handleError(error, for: navigationController, onOKTapped: { [weak self] in
self?.parentCoordinator?.childDidFinish(self)
})
}
}

extension AddHubVaultCoordinator: HubUserLogin {
public func authenticate(with hubConfig: HubConfig) async throws -> OIDAuthState {
try await hubAuthenticator.authenticate(with: hubConfig, from: navigationController)
extension AddHubVaultCoordinator: HubAuthenticationCoordinatorDelegate {
func userDidCancelHubAuthentication() {
// do nothing as the user already sees the login screen again
}

func userDismissedHubAuthenticationErrorMessage() {
// do nothing as the user already sees the login screen again
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ private class AuthenticatedOpenExistingVaultCoordinator: VaultInstalling, Folder
downloadedVaultConfig: downloadedVaultConfig,
vaultUID: UUID().uuidString,
accountUID: account.accountUID,
vaultItem: vaultItem,
hubAuthenticator: CryptomatorHubAuthenticator.shared)
vaultItem: vaultItem)
child.parentCoordinator = self
child.delegate = self
childCoordinators.append(child)
Expand Down
7 changes: 4 additions & 3 deletions Cryptomator/Settings/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Combine
import CryptomatorCommonCore
import CryptomatorFileProvider
import Dependencies
import Foundation
import Promises
import StoreKit
Expand Down Expand Up @@ -90,13 +91,13 @@ class SettingsViewModel: TableViewModel<SettingsSection> {
return viewModel
}()

private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector

private var subscribers = Set<AnyCancellable>()
private lazy var showDebugModeWarningPublisher = PassthroughSubject<Void, Never>()

init(cryptomatorSettings: CryptomatorSettings = CryptomatorUserDefaults.shared, fileProviderConnector: FileProviderConnector = FileProviderXPCConnector.shared) {
init(cryptomatorSettings: CryptomatorSettings = CryptomatorUserDefaults.shared) {
self.cryptomatorSettings = cryptomatorSettings
self.fileProviderConnector = fileProviderConnector
}

func refreshCacheSize() -> Promise<Void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CocoaLumberjackSwift
import Combine
import CryptomatorCommonCore
import CryptomatorCryptoLib
import Dependencies
import FileProvider
import Foundation
import Promises
Expand Down Expand Up @@ -60,27 +61,23 @@ class ChangePasswordViewModel: TableViewModel<ChangePasswordSection>, ChangePass
return _sections
}

lazy var cells: [ChangePasswordSection: [BindableTableViewCellViewModel]] = {
return [
.oldPassword: [oldPasswordCellViewModel],
.newPassword: [newPasswordCellViewModel],
.newPasswordConfirmation: [newPasswordConfirmationCellViewModel]
]
}()

private lazy var _sections: [Section<ChangePasswordSection>] = {
return [
Section(id: .oldPassword, elements: [oldPasswordCellViewModel]),
Section(id: .newPassword, elements: [newPasswordCellViewModel]),
Section(id: .newPasswordConfirmation, elements: [newPasswordConfirmationCellViewModel])
]
}()
lazy var cells: [ChangePasswordSection: [BindableTableViewCellViewModel]] = [
.oldPassword: [oldPasswordCellViewModel],
.newPassword: [newPasswordCellViewModel],
.newPasswordConfirmation: [newPasswordConfirmationCellViewModel]
]

private lazy var _sections: [Section<ChangePasswordSection>] = [
Section(id: .oldPassword, elements: [oldPasswordCellViewModel]),
Section(id: .newPassword, elements: [newPasswordCellViewModel]),
Section(id: .newPasswordConfirmation, elements: [newPasswordConfirmationCellViewModel])
]

private static let minimumPasswordLength = 8
private let vaultAccount: VaultAccount
private let domain: NSFileProviderDomain
private let vaultManager: VaultManager
private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector

private let oldPasswordCellViewModel = TextFieldCellViewModel(type: .password, isInitialFirstResponder: true)
private let newPasswordCellViewModel = TextFieldCellViewModel(type: .password)
Expand All @@ -100,11 +97,10 @@ class ChangePasswordViewModel: TableViewModel<ChangePasswordSection>, ChangePass

private lazy var subscribers = Set<AnyCancellable>()

init(vaultAccount: VaultAccount, domain: NSFileProviderDomain, vaultManager: VaultManager = VaultDBManager.shared, fileProviderConnector: FileProviderConnector = FileProviderXPCConnector.shared) {
init(vaultAccount: VaultAccount, domain: NSFileProviderDomain, vaultManager: VaultManager = VaultDBManager.shared) {
self.vaultAccount = vaultAccount
self.domain = domain
self.vaultManager = vaultManager
self.fileProviderConnector = fileProviderConnector
super.init()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Combine
import CryptomatorCommonCore
import Dependencies
import FileProvider
import Foundation
import Promises
Expand Down Expand Up @@ -40,19 +41,18 @@ class VaultKeepUnlockedViewModel: TableViewModel<VaultKeepUnlockedSection>, Vaul
private(set) var keepUnlockedItems = [KeepUnlockedDurationItem]()
private let vaultKeepUnlockedSettings: VaultKeepUnlockedSettings
private let masterkeyCacheManager: MasterkeyCacheManager
private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector
private let vaultInfo: VaultInfo
private let currentKeepUnlockedDuration: Bindable<KeepUnlockedDuration>
private var subscriber: AnyCancellable?
private var vaultUID: String {
return vaultInfo.vaultUID
}

init(currentKeepUnlockedDuration: Bindable<KeepUnlockedDuration>, vaultInfo: VaultInfo, vaultKeepUnlockedSettings: VaultKeepUnlockedSettings = VaultKeepUnlockedManager.shared, masterkeyCacheManager: MasterkeyCacheManager = MasterkeyCacheKeychainManager.shared, fileProviderConnector: FileProviderConnector = FileProviderXPCConnector.shared) {
init(currentKeepUnlockedDuration: Bindable<KeepUnlockedDuration>, vaultInfo: VaultInfo, vaultKeepUnlockedSettings: VaultKeepUnlockedSettings = VaultKeepUnlockedManager.shared, masterkeyCacheManager: MasterkeyCacheManager = MasterkeyCacheKeychainManager.shared) {
self.vaultInfo = vaultInfo
self.vaultKeepUnlockedSettings = vaultKeepUnlockedSettings
self.masterkeyCacheManager = masterkeyCacheManager
self.fileProviderConnector = fileProviderConnector
self.currentKeepUnlockedDuration = currentKeepUnlockedDuration

self.keepUnlockedItems = KeepUnlockedDuration.allCases.map {
Expand Down
7 changes: 3 additions & 4 deletions Cryptomator/VaultDetail/MoveVault/MoveVaultViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import CocoaLumberjackSwift
import CryptomatorCloudAccessCore
import CryptomatorCommonCore
import Dependencies
import FileProvider
import Foundation
import GRDB
Expand All @@ -28,19 +29,17 @@ class MoveVaultViewModel: ChooseFolderViewModel, MoveVaultViewModelProtocol {
private let vaultManager: VaultManager
private let vaultInfo: VaultInfo
private let domain: NSFileProviderDomain
private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector

init(provider: CloudProvider,
currentFolderChoosingCloudPath: CloudPath,
vaultInfo: VaultInfo,
domain: NSFileProviderDomain,
cloudProviderManager: CloudProviderManager = CloudProviderDBManager.shared,
vaultManager: VaultManager = VaultDBManager.shared,
fileProviderConnector: FileProviderConnector = FileProviderXPCConnector.shared) {
vaultManager: VaultManager = VaultDBManager.shared) {
self.vaultInfo = vaultInfo
self.domain = domain
self.vaultManager = vaultManager
self.fileProviderConnector = fileProviderConnector
super.init(canCreateFolder: true, cloudPath: currentFolderChoosingCloudPath, provider: provider)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import CocoaLumberjackSwift
import CryptomatorCloudAccessCore
import CryptomatorCommonCore
import Dependencies
import FileProvider
import Foundation
import GRDB
Expand All @@ -31,19 +32,18 @@ class RenameVaultViewModel: SetVaultNameViewModel, RenameVaultViewModelProtcol {
// swiftlint:disable:next weak_delegate
private let delegate: MoveVaultViewModel
private let vaultInfo: VaultInfo
@Dependency(\.fileProviderConnector) private var fileProviderConnector

init(provider: CloudProvider,
vaultInfo: VaultInfo,
domain: NSFileProviderDomain,
vaultManager: VaultManager = VaultDBManager.shared,
fileProviderConnector: FileProviderConnector = FileProviderXPCConnector.shared) {
vaultManager: VaultManager = VaultDBManager.shared) {
self.delegate = MoveVaultViewModel(
provider: provider,
currentFolderChoosingCloudPath: CloudPath("/"),
vaultInfo: vaultInfo,
domain: domain,
vaultManager: vaultManager,
fileProviderConnector: fileProviderConnector
vaultManager: vaultManager
)
self.vaultInfo = vaultInfo
}
Expand Down
18 changes: 8 additions & 10 deletions Cryptomator/VaultDetail/VaultDetailViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CocoaLumberjackSwift
import Combine
import CryptomatorCloudAccessCore
import CryptomatorCommonCore
import Dependencies
import GRDB
import LocalAuthentication
import Promises
Expand Down Expand Up @@ -73,7 +74,7 @@ class VaultDetailViewModel: VaultDetailViewModelProtocol {

private let vaultInfo: VaultInfo
private let vaultManager: VaultManager
private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector
private let context = LAContext()
private let vaultKeepUnlockedSettings: VaultKeepUnlockedSettings
private let passwordManager: VaultPasswordManager
Expand Down Expand Up @@ -136,12 +137,10 @@ class VaultDetailViewModel: VaultDetailViewModelProtocol {
}
}

private lazy var sectionFooter: [VaultDetailSection: HeaderFooterViewModel] = {
[.vaultInfoSection: VaultDetailInfoFooterViewModel(vault: vaultInfo),
.changeVaultPasswordSection: BaseHeaderFooterViewModel(title: LocalizedString.getValue("vaultDetail.changePassword.footer")),
.lockingSection: unlockSectionFooterViewModel,
.removeVaultSection: BaseHeaderFooterViewModel(title: LocalizedString.getValue("vaultDetail.removeVault.footer"))]
}()
private lazy var sectionFooter: [VaultDetailSection: HeaderFooterViewModel] = [.vaultInfoSection: VaultDetailInfoFooterViewModel(vault: vaultInfo),
.changeVaultPasswordSection: BaseHeaderFooterViewModel(title: LocalizedString.getValue("vaultDetail.changePassword.footer")),
.lockingSection: unlockSectionFooterViewModel,
.removeVaultSection: BaseHeaderFooterViewModel(title: LocalizedString.getValue("vaultDetail.removeVault.footer"))]

private lazy var unlockSectionFooterViewModel = UnlockSectionFooterViewModel(vaultUnlocked: vaultInfo.vaultIsUnlocked.value, biometricalUnlockEnabled: biometricalUnlockEnabled, biometryTypeName: context.enrolledBiometricsAuthenticationName(), keepUnlockedDuration: currentKeepUnlockedDuration.value)

Expand All @@ -156,13 +155,12 @@ class VaultDetailViewModel: VaultDetailViewModelProtocol {
private var observation: DatabaseCancellable?

convenience init(vaultInfo: VaultInfo) {
self.init(vaultInfo: vaultInfo, vaultManager: VaultDBManager.shared, fileProviderConnector: FileProviderXPCConnector.shared, passwordManager: VaultPasswordKeychainManager(), dbManager: DatabaseManager.shared, vaultKeepUnlockedSettings: VaultKeepUnlockedManager.shared)
self.init(vaultInfo: vaultInfo, vaultManager: VaultDBManager.shared, passwordManager: VaultPasswordKeychainManager(), dbManager: DatabaseManager.shared, vaultKeepUnlockedSettings: VaultKeepUnlockedManager.shared)
}

init(vaultInfo: VaultInfo, vaultManager: VaultManager, fileProviderConnector: FileProviderConnector, passwordManager: VaultPasswordManager, dbManager: DatabaseManager, vaultKeepUnlockedSettings: VaultKeepUnlockedSettings) {
init(vaultInfo: VaultInfo, vaultManager: VaultManager, passwordManager: VaultPasswordManager, dbManager: DatabaseManager, vaultKeepUnlockedSettings: VaultKeepUnlockedSettings) {
self.vaultInfo = vaultInfo
self.vaultManager = vaultManager
self.fileProviderConnector = fileProviderConnector
self.passwordManager = passwordManager
self.title = Bindable(vaultInfo.vaultName)
self.vaultKeepUnlockedSettings = vaultKeepUnlockedSettings
Expand Down
6 changes: 3 additions & 3 deletions Cryptomator/VaultList/VaultCellViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Combine
import CryptomatorCommonCore
import Dependencies
import Promises
import UIKit

Expand All @@ -33,11 +34,10 @@ class VaultCellViewModel: TableViewCellViewModel, VaultCellViewModelProtocol {

let vault: VaultInfo
private lazy var errorPublisher = PassthroughSubject<Error, Never>()
private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector

init(vault: VaultInfo, fileProviderConnector: FileProviderConnector = FileProviderXPCConnector.shared) {
init(vault: VaultInfo) {
self.vault = vault
self.fileProviderConnector = fileProviderConnector
}

func lockVault() -> Promise<Void> {
Expand Down
8 changes: 4 additions & 4 deletions Cryptomator/VaultList/VaultListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import CocoaLumberjackSwift
import Combine
import CryptomatorCommonCore
import Dependencies
import FileProvider
import Foundation
import GRDB
Expand All @@ -27,21 +28,20 @@ class VaultListViewModel: ViewModel, VaultListViewModelProtocol {
var vaultCellViewModels: [VaultCellViewModel]
private let dbManager: DatabaseManager
private let vaultManager: VaultDBManager
private let fileProviderConnector: FileProviderConnector
@Dependency(\.fileProviderConnector) private var fileProviderConnector
private var observation: DatabaseCancellable?
private lazy var subscribers = Set<AnyCancellable>()
private lazy var errorPublisher = PassthroughSubject<Error, Never>()
private lazy var databaseChangedPublisher = CurrentValueSubject<Result<[TableViewCellViewModel], Error>, Never>(.success([]))
private var removedRow = false

convenience init() {
self.init(dbManager: DatabaseManager.shared, vaultManager: VaultDBManager.shared, fileProviderConnector: FileProviderXPCConnector.shared)
self.init(dbManager: DatabaseManager.shared, vaultManager: VaultDBManager.shared)
}

init(dbManager: DatabaseManager, vaultManager: VaultDBManager, fileProviderConnector: FileProviderConnector) {
init(dbManager: DatabaseManager, vaultManager: VaultDBManager) {
self.dbManager = dbManager
self.vaultManager = vaultManager
self.fileProviderConnector = fileProviderConnector
self.vaultCellViewModels = [VaultCellViewModel]()
}

Expand Down
Loading

0 comments on commit bb5824b

Please sign in to comment.