Skip to content

Commit 80a1670

Browse files
Added Box support (#352)
Co-authored-by: Tobias Hagemann <[email protected]>
1 parent a855f11 commit 80a1670

34 files changed

+364
-107
lines changed

Cryptomator.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+27-18
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,26 @@
1414
"kind" : "remoteSourceControl",
1515
"location" : "https://github.com/leif-ibsen/ASN1",
1616
"state" : {
17-
"revision" : "8a5cb6ce9b4a009a5b8d82465caf1aafb720096e",
18-
"version" : "2.5.0"
17+
"revision" : "4b4e82513e3b4d51a7573972fd7123222dd3a3bd",
18+
"version" : "2.6.0"
1919
}
2020
},
2121
{
2222
"identity" : "asn1swift",
2323
"kind" : "remoteSourceControl",
2424
"location" : "https://github.com/tikhop/ASN1Swift",
2525
"state" : {
26-
"revision" : "177417b6bf89431a0750ee640012b6aed8961c6a",
27-
"version" : "1.2.5"
26+
"revision" : "403cd95194e6a962e16db7c0d373d89fce83e0f7",
27+
"version" : "1.2.7"
2828
}
2929
},
3030
{
3131
"identity" : "aws-sdk-ios-spm",
3232
"kind" : "remoteSourceControl",
3333
"location" : "https://github.com/aws-amplify/aws-sdk-ios-spm.git",
3434
"state" : {
35-
"revision" : "cfcf97f6994b6ffd9a3244dc638458f5822aba56",
36-
"version" : "2.34.0"
35+
"revision" : "8ff8bebfe24271f7b16c5abaeb78daf82bee3a80",
36+
"version" : "2.34.2"
3737
}
3838
},
3939
{
@@ -50,17 +50,26 @@
5050
"kind" : "remoteSourceControl",
5151
"location" : "https://github.com/leif-ibsen/BigInt",
5252
"state" : {
53-
"revision" : "ba54c8b51392627d4cc9b05a672cce558be56e04",
54-
"version" : "1.17.0"
53+
"revision" : "bf55e4ce076a5e2dde0db13d9b03d820cfad420d",
54+
"version" : "1.19.0"
55+
}
56+
},
57+
{
58+
"identity" : "box-swift-sdk-gen",
59+
"kind" : "remoteSourceControl",
60+
"location" : "https://github.com/box/box-swift-sdk-gen.git",
61+
"state" : {
62+
"revision" : "7b2e3963a4f9d7c608ba9176fa3c32d260599906",
63+
"version" : "0.3.1"
5564
}
5665
},
5766
{
5867
"identity" : "cloud-access-swift",
5968
"kind" : "remoteSourceControl",
6069
"location" : "https://github.com/cryptomator/cloud-access-swift.git",
6170
"state" : {
62-
"revision" : "cd7a18abcaf09349f066363c7524b738f4f4ad79",
63-
"version" : "1.10.1"
71+
"revision" : "6ee5a3374c1530c0808b7855e567cac2b7618952",
72+
"version" : "1.11.0"
6473
}
6574
},
6675
{
@@ -86,8 +95,8 @@
8695
"kind" : "remoteSourceControl",
8796
"location" : "https://github.com/leif-ibsen/Digest",
8897
"state" : {
89-
"revision" : "1202dcb976e481e7c228492c5a8d5159cfa4ea97",
90-
"version" : "1.4.0"
98+
"revision" : "05f079878ec5fb05c7d9c94f35dbc4f5ec054d54",
99+
"version" : "1.6.0"
91100
}
92101
},
93102
{
@@ -149,8 +158,8 @@
149158
"kind" : "remoteSourceControl",
150159
"location" : "https://github.com/AzureAD/microsoft-authentication-library-for-objc.git",
151160
"state" : {
152-
"revision" : "9d15d7980a52945dd17ea529bcf4c92f2c0d9a12",
153-
"version" : "1.3.1"
161+
"revision" : "d2f81ded070ac6452b2a6acb5bc45eb566427fe7",
162+
"version" : "1.3.3"
154163
}
155164
},
156165
{
@@ -203,8 +212,8 @@
203212
"kind" : "remoteSourceControl",
204213
"location" : "https://github.com/apple/swift-log",
205214
"state" : {
206-
"revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5",
207-
"version" : "1.5.4"
215+
"revision" : "9cb486020ebf03bfa5b5df985387a14a98744537",
216+
"version" : "1.6.1"
208217
}
209218
},
210219
{
@@ -239,8 +248,8 @@
239248
"kind" : "remoteSourceControl",
240249
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
241250
"state" : {
242-
"revision" : "b13b1d1a8e787a5ffc71ac19dcaf52183ab27ba2",
243-
"version" : "1.1.1"
251+
"revision" : "96beb108a57f24c8476ae1f309239270772b2940",
252+
"version" : "1.2.5"
244253
}
245254
}
246255
],

Cryptomator/AddVault/CreateNewVault/CreateNewVaultCoordinator.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class CreateNewVaultCoordinator: AccountListing, CloudChoosing, DefaultShowEditA
2424
}
2525

2626
func start() {
27-
let viewModel = ChooseCloudViewModel(clouds: [.localFileSystem(type: .iCloudDrive), .dropbox, .googleDrive, .oneDrive, .pCloud, .webDAV(type: .custom), .s3(type: .custom), .localFileSystem(type: .custom)], headerTitle: LocalizedString.getValue("addVault.createNewVault.chooseCloud.header"))
27+
let viewModel = ChooseCloudViewModel(clouds: [.localFileSystem(type: .iCloudDrive), .dropbox, .googleDrive, .oneDrive, .pCloud, .box, .webDAV(type: .custom), .s3(type: .custom), .localFileSystem(type: .custom)], headerTitle: LocalizedString.getValue("addVault.createNewVault.chooseCloud.header"))
2828
let chooseCloudVC = ChooseCloudViewController(viewModel: viewModel)
2929
chooseCloudVC.title = LocalizedString.getValue("addVault.createNewVault.title")
3030
chooseCloudVC.coordinator = self

Cryptomator/AddVault/OpenExistingVault/OpenExistingVaultCoordinator.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class OpenExistingVaultCoordinator: AccountListing, CloudChoosing, DefaultShowEd
2525
}
2626

2727
func start() {
28-
let viewModel = ChooseCloudViewModel(clouds: [.localFileSystem(type: .iCloudDrive), .dropbox, .googleDrive, .oneDrive, .pCloud, .webDAV(type: .custom), .s3(type: .custom), .localFileSystem(type: .custom)], headerTitle: LocalizedString.getValue("addVault.openExistingVault.chooseCloud.header"))
28+
let viewModel = ChooseCloudViewModel(clouds: [.localFileSystem(type: .iCloudDrive), .dropbox, .googleDrive, .oneDrive, .pCloud, .box, .webDAV(type: .custom), .s3(type: .custom), .localFileSystem(type: .custom)], headerTitle: LocalizedString.getValue("addVault.openExistingVault.chooseCloud.header"))
2929
let chooseCloudVC = ChooseCloudViewController(viewModel: viewModel)
3030
chooseCloudVC.title = LocalizedString.getValue("addVault.openExistingVault.title")
3131
chooseCloudVC.coordinator = self

Cryptomator/AppDelegate.swift

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
4949
DDLogError("Setting up OneDrive failed with error: \(error)")
5050
}
5151
PCloudSetup.constants = PCloudSetup(appKey: CloudAccessSecrets.pCloudAppKey, sharedContainerIdentifier: nil)
52+
BoxSetup.constants = BoxSetup(clientId: CloudAccessSecrets.boxClientId, clientSecret: CloudAccessSecrets.boxClientSecret, sharedContainerIdentifier: nil)
5253

5354
// Set up payment queue
5455
SKPaymentQueue.default().add(StoreObserver.shared)

Cryptomator/Common/CloudAccountList/AccountListViewController.swift

+14-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
// Copyright © 2021 Skymatic GmbH. All rights reserved.
77
//
88

9+
import AuthenticationServices
10+
import CocoaLumberjackSwift
911
import CryptomatorCommon
1012
import CryptomatorCommonCore
1113
import Foundation
1214
import Promises
1315
import UIKit
1416

15-
class AccountListViewController: ListViewController<AccountCellContent> {
17+
class AccountListViewController: ListViewController<AccountCellContent>, ASWebAuthenticationPresentationContextProviding {
1618
weak var coordinator: (Coordinator & AccountListing)?
1719
private let viewModel: AccountListViewModelProtocol
1820

@@ -103,6 +105,16 @@ class AccountListViewController: ListViewController<AccountCellContent> {
103105
}
104106
}
105107

108+
// MARK: - ASWebAuthenticationPresentationContextProviding
109+
110+
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
111+
guard let window = UIApplication.shared.windows.first else {
112+
DDLogInfo("No window could be found as presentation anchor.")
113+
return ASPresentationAnchor()
114+
}
115+
return window
116+
}
117+
106118
// MARK: - Internal
107119

108120
private func handleLogout(_ sender: AccountCellButton) {
@@ -130,7 +142,7 @@ class AccountListViewController: ListViewController<AccountCellContent> {
130142

131143
private func supportsEditing(_ cloudProviderType: CloudProviderType) -> Bool {
132144
switch cloudProviderType {
133-
case .dropbox, .googleDrive, .localFileSystem, .oneDrive, .pCloud:
145+
case .box, .dropbox, .googleDrive, .localFileSystem, .oneDrive, .pCloud:
134146
return false
135147
case .s3, .webDAV:
136148
return true

Cryptomator/Common/CloudAccountList/AccountListViewModel.swift

+34-17
Original file line numberDiff line numberDiff line change
@@ -66,46 +66,55 @@ class AccountListViewModel: AccountListViewModelProtocol {
6666
}
6767
}
6868

69+
func refreshBoxItems() -> Promise<Void> {
70+
return all(accountInfos
71+
.map { BoxCredential(tokenStorage: BoxTokenStorage(userID: $0.accountUID)) }
72+
.map { self.createAccountCellContent(for: $0) }
73+
).then { accounts in
74+
self.accounts = accounts
75+
}
76+
}
77+
6978
func createAccountCellContent(from accountInfo: AccountInfo) throws -> AccountCellContent {
7079
switch cloudProviderType {
80+
case .box:
81+
return createAccountCellContentPlaceholder()
7182
case .dropbox:
72-
let credential = DropboxCredential(tokenUID: accountInfo.accountUID)
73-
return createAccountCellContentPlaceholder(for: credential)
83+
return createAccountCellContentPlaceholder()
7484
case .googleDrive:
7585
let credential = GoogleDriveCredential(userID: accountInfo.accountUID)
7686
return try createAccountCellContent(for: credential)
87+
case .localFileSystem:
88+
throw AccountListError.unsupportedCloudProviderType
7789
case .oneDrive:
7890
let credential = try OneDriveCredential(with: accountInfo.accountUID)
7991
return try createAccountCellContent(for: credential)
8092
case .pCloud:
81-
let credential = try PCloudCredential(userID: accountInfo.accountUID)
82-
return createAccountCellContentPlaceholder(for: credential)
83-
case .webDAV:
84-
guard let credential = WebDAVCredentialManager.shared.getCredentialFromKeychain(with: accountInfo.accountUID) else {
85-
throw CloudProviderAccountError.accountNotFoundError
86-
}
87-
return createAccountCellContent(for: credential)
88-
case .localFileSystem:
89-
throw AccountListError.unsupportedCloudProviderType
93+
return createAccountCellContentPlaceholder()
9094
case .s3:
9195
guard let credential = S3CredentialManager.shared.getCredential(with: accountInfo.accountUID) else {
9296
throw CloudProviderAccountError.accountNotFoundError
9397
}
9498
let displayName = try S3CredentialManager.shared.getDisplayName(for: credential)
9599
return createAccountCellContent(for: credential, displayName: displayName)
100+
case .webDAV:
101+
guard let credential = WebDAVCredentialManager.shared.getCredentialFromKeychain(with: accountInfo.accountUID) else {
102+
throw CloudProviderAccountError.accountNotFoundError
103+
}
104+
return createAccountCellContent(for: credential)
96105
}
97106
}
98107

108+
private func createAccountCellContentPlaceholder() -> AccountCellContent {
109+
return AccountCellContent(mainLabelText: "(…)", detailLabelText: nil)
110+
}
111+
99112
private func createAccountCellContent(for credential: DropboxCredential) -> Promise<AccountCellContent> {
100113
return credential.getUsername().then { username in
101114
AccountCellContent(mainLabelText: username, detailLabelText: nil)
102115
}
103116
}
104117

105-
private func createAccountCellContentPlaceholder(for credential: DropboxCredential) -> AccountCellContent {
106-
return AccountCellContent(mainLabelText: "(…)", detailLabelText: nil)
107-
}
108-
109118
private func createAccountCellContent(for credential: GoogleDriveCredential) throws -> AccountCellContent {
110119
let username = try credential.getUsername()
111120
return AccountCellContent(mainLabelText: username, detailLabelText: nil)
@@ -122,8 +131,10 @@ class AccountListViewModel: AccountListViewModelProtocol {
122131
}
123132
}
124133

125-
private func createAccountCellContentPlaceholder(for credential: PCloudCredential) -> AccountCellContent {
126-
return AccountCellContent(mainLabelText: "(…)", detailLabelText: nil)
134+
func createAccountCellContent(for credential: BoxCredential) -> Promise<AccountCellContent> {
135+
return credential.getUsername().then { username in
136+
AccountCellContent(mainLabelText: username, detailLabelText: nil)
137+
}
127138
}
128139

129140
func createAccountCellContent(for credential: WebDAVCredential) -> AccountCellContent {
@@ -203,6 +214,12 @@ class AccountListViewModel: AccountListViewModelProtocol {
203214
}.catch { error in
204215
self.databaseChangedPublisher.send(.failure(error))
205216
}
217+
} else if self.cloudProviderType == .box {
218+
self.refreshBoxItems().then {
219+
self.databaseChangedPublisher.send(.success(self.accounts))
220+
}.catch { error in
221+
self.databaseChangedPublisher.send(.failure(error))
222+
}
206223
}
207224
})
208225
return databaseChangedPublisher.eraseToAnyPublisher()

Cryptomator/Common/CloudAuthenticator.swift

+27-8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ class CloudAuthenticator {
6060
}
6161
}
6262

63+
func authenticateBox(from viewController: UIViewController) -> Promise<CloudProviderAccount> {
64+
let tokenStorage = BoxTokenStorage()
65+
let credential = BoxCredential(tokenStorage: tokenStorage)
66+
return BoxAuthenticator.authenticate(from: viewController, tokenStorage: tokenStorage).then { _ -> Promise<CloudProviderAccount> in
67+
return credential.getUserID().then { userID in
68+
tokenStorage.userID = userID // this will actually save the access token to the keychain
69+
let account = CloudProviderAccount(accountUID: userID, cloudProviderType: .box)
70+
try self.accountManager.saveNewAccount(account)
71+
return account
72+
}
73+
}
74+
}
75+
6376
func authenticateWebDAV(from viewController: UIViewController) -> Promise<CloudProviderAccount> {
6477
return WebDAVAuthenticator.authenticate(from: viewController).then { credential -> CloudProviderAccount in
6578
let account = CloudProviderAccount(accountUID: credential.identifier, cloudProviderType: .webDAV(type: .custom))
@@ -78,43 +91,49 @@ class CloudAuthenticator {
7891

7992
func authenticate(_ cloudProviderType: CloudProviderType, from viewController: UIViewController) -> Promise<CloudProviderAccount> {
8093
switch cloudProviderType {
94+
case .box:
95+
return authenticateBox(from: viewController)
8196
case .dropbox:
8297
return authenticateDropbox(from: viewController)
8398
case .googleDrive:
8499
return authenticateGoogleDrive(from: viewController)
100+
case .localFileSystem:
101+
return Promise(CloudAuthenticatorError.functionNotYetSupported)
85102
case .oneDrive:
86103
return authenticateOneDrive(from: viewController)
87104
case .pCloud:
88105
return authenticatePCloud(from: viewController)
89-
case .webDAV:
90-
return authenticateWebDAV(from: viewController)
91-
case .localFileSystem:
92-
return Promise(CloudAuthenticatorError.functionNotYetSupported)
93106
case .s3:
94107
return authenticateS3(from: viewController)
108+
case .webDAV:
109+
return authenticateWebDAV(from: viewController)
95110
}
96111
}
97112

98113
func deauthenticate(account: CloudProviderAccount) throws {
99114
switch account.cloudProviderType {
115+
case .box:
116+
let tokenStorage = BoxTokenStorage(userID: account.accountUID)
117+
let credential = BoxCredential(tokenStorage: tokenStorage)
118+
_ = credential.deauthenticate()
100119
case .dropbox:
101120
let credential = DropboxCredential(tokenUID: account.accountUID)
102121
credential.deauthenticate()
103122
case .googleDrive:
104123
let credential = GoogleDriveCredential(userID: account.accountUID)
105124
credential.deauthenticate()
125+
case .localFileSystem:
126+
break
106127
case .oneDrive:
107128
let credential = try OneDriveCredential(with: account.accountUID)
108129
try credential.deauthenticate()
109130
case .pCloud:
110131
let credential = try PCloudCredential(userID: account.accountUID)
111132
try credential.deauthenticate()
112-
case .webDAV:
113-
try WebDAVCredentialManager.shared.removeCredentialFromKeychain(with: account.accountUID)
114-
case .localFileSystem:
115-
break
116133
case .s3:
117134
try S3CredentialManager.shared.removeCredential(with: account.accountUID)
135+
case .webDAV:
136+
try WebDAVCredentialManager.shared.removeCredentialFromKeychain(with: account.accountUID)
118137
}
119138
let correspondingVaults = try vaultAccountManager.getAllAccounts().filter { $0.delegateAccountUID == account.accountUID }
120139
_ = Promise<Void>(on: .global()) { fulfill, _ in

Cryptomator/Common/CloudProviderType+Localization.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@ import Foundation
1212
extension CloudProviderType {
1313
func localizedString() -> String {
1414
switch self {
15+
case .box:
16+
return "Box"
1517
case .dropbox:
1618
return "Dropbox"
1719
case .googleDrive:
1820
return "Google Drive"
21+
case let .localFileSystem(localFileSystemType):
22+
return localFileSystemType.localizedString()
1923
case .oneDrive:
2024
return "OneDrive"
2125
case .pCloud:
2226
return "pCloud"
23-
case .webDAV:
24-
return "WebDAV"
25-
case let .localFileSystem(localFileSystemType):
26-
return localFileSystemType.localizedString()
2727
case .s3:
2828
return "S3"
29+
case .webDAV:
30+
return "WebDAV"
2931
}
3032
}
3133
}

0 commit comments

Comments
 (0)