Skip to content

Commit b08be7c

Browse files
committed
Merge branch 'release/1.6.0-alpha3' into main
2 parents 86347f2 + 034cb3d commit b08be7c

File tree

195 files changed

+4604
-158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+4604
-158
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ jobs:
1616
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
1717
restore-keys: |
1818
${{ runner.os }}-spm-
19+
- name: Run process.sh script
20+
run: |
21+
./Scripts/process.sh --fail-on-errors
22+
failed=$?
23+
exit $failed
1924
- name: Create CloudAccessSecrets
2025
run: ./create-cloud-access-secrets-file.sh
2126
env:

.swiftformat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
--minversion 0.47.10
2+
13
# format options
24

35
--commas inline

CloudAccessPrivate/.swiftpm/xcode/xcshareddata/xcschemes/CloudAccessPrivateCore.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1220"
3+
LastUpgradeVersion = "1240"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

CloudAccessPrivate/Package.swift

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// swift-tools-version:5.1
2-
// The swift-tools-version declares the minimum version of Swift required to build this package.
32

43
import PackageDescription
54

@@ -10,7 +9,6 @@ let package = Package(
109
.macOS(.v10_12)
1110
],
1211
products: [
13-
// Products define the executables and libraries a package produces, and make them visible to other packages.
1412
.library(
1513
name: "CloudAccessPrivate",
1614
targets: ["CloudAccessPrivate"]
@@ -21,18 +19,15 @@ let package = Package(
2119
)
2220
],
2321
dependencies: [
24-
// Dependencies declare other packages that this package depends on.
25-
.package(url: "https://github.com/google/GTMAppAuth.git", .upToNextMinor(from: "1.1.0")),
2622
.package(url: "https://github.com/openid/AppAuth-iOS.git", .upToNextMinor(from: "1.4.0")),
27-
.package(url: "https://github.com/cryptomator/cloud-access-swift.git", .upToNextMinor(from: "0.9.1")),
23+
.package(url: "https://github.com/cryptomator/cloud-access-swift.git", .upToNextMinor(from: "0.11.0")),
24+
.package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", .upToNextMinor(from: "3.7.0")),
2825
.package(url: "https://github.com/phil1995/dropbox-sdk-obj-c.git", .branch("main")),
2926
.package(url: "https://github.com/google/google-api-objectivec-client-for-rest.git", .upToNextMinor(from: "1.4.3")),
30-
.package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack.git", .upToNextMinor(from: "3.7.0"))
31-
27+
.package(url: "https://github.com/google/GTMAppAuth.git", .upToNextMinor(from: "1.1.0")),
28+
.package(url: "https://github.com/google/gtm-session-fetcher.git", .upToNextMinor(from: "1.4.0"))
3229
],
3330
targets: [
34-
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
35-
// Targets can depend on other targets in this package, and on products in packages this package depends on.
3631
.target(
3732
name: "CloudAccessPrivate",
3833
dependencies: [
@@ -47,6 +42,7 @@ let package = Package(
4742
"CryptomatorCloudAccess",
4843
"GoogleAPIClientForREST_Drive",
4944
"GTMAppAuth",
45+
"GTMSessionFetcher",
5046
"ObjectiveDropboxOfficial"
5147
]
5248
),

CloudAccessPrivate/Sources/CloudAccessPrivateCore/CryptomatorDatabase.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ public class CryptomatorDatabase {
2929

3030
private static var migrator: DatabaseMigrator {
3131
var migrator = DatabaseMigrator()
32+
3233
migrator.registerMigration("v1") { db in
3334
try db.create(table: "cloudProviderAccounts") { table in
3435
table.column("accountUID", .text).primaryKey()
3536
table.column("cloudProviderType", .text).notNull()
3637
}
3738
try db.create(table: "vaultAccounts") { table in
3839
table.column("vaultUID", .text).primaryKey()
39-
table.column("delegateAccountUID", .text).notNull()
40+
table.column("delegateAccountUID", .text).notNull().references("cloudProviderAccounts")
4041
table.column("vaultPath", .text).notNull()
4142
table.column("lastUpToDateCheck", .date).notNull()
4243
}

CloudAccessPrivate/Sources/CloudAccessPrivateCore/Manager/CloudProviderAccountManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public struct CloudProviderAccount: Decodable, FetchableRecord, TableRecord {
1313
static let accountUIDKey = "accountUID"
1414
static let cloudProviderTypeKey = "cloudProviderType"
1515
public let accountUID: String
16-
let cloudProviderType: CloudProviderType
16+
public let cloudProviderType: CloudProviderType
1717

1818
public init(accountUID: String, cloudProviderType: CloudProviderType) {
1919
self.accountUID = accountUID

CloudAccessPrivate/Sources/CloudAccessPrivateCore/Manager/VaultAccountManager.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ public struct VaultAccount: Decodable, FetchableRecord, TableRecord {
1515
static let delegateAccountUIDKey = "delegateAccountUID"
1616
static let vaultPathKey = "vaultPath"
1717
static let lastUpToDateCheckKey = "lastUpToDateCheck"
18-
let vaultUID: String
18+
public let vaultUID: String
1919
let delegateAccountUID: String
2020
public let vaultPath: CloudPath
2121
let lastUpToDateCheck: Date
2222

23+
public static let delegateAccount = belongsTo(CloudProviderAccount.self)
24+
2325
public init(vaultUID: String, delegateAccountUID: String, vaultPath: CloudPath, lastUpToDateCheck: Date = Date()) {
2426
self.vaultUID = vaultUID
2527
self.delegateAccountUID = delegateAccountUID
@@ -69,7 +71,7 @@ public class VaultAccountManager {
6971
return account
7072
}
7173

72-
public func getAllAccounts() throws -> [VaultAccount] {
74+
func getAllAccounts() throws -> [VaultAccount] {
7375
try dbPool.read { db in
7476
try VaultAccount.fetchAll(db)
7577
}

CloudAccessPrivate/Sources/CloudAccessPrivateCore/Manager/VaultManager.swift

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class VaultManager {
5151
guard VaultManager.cachedDecorators[vaultUID] == nil else {
5252
throw VaultManagerError.vaultAlreadyExists
5353
}
54+
let vaultVersion = 7
5455
let masterkey = try Masterkey.createNew()
5556
let cryptor = Cryptor(masterkey: masterkey)
5657
let delegate = try providerManager.getProvider(with: delegateAccountUID)
@@ -60,7 +61,7 @@ public class VaultManager {
6061
let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(UUID().uuidString, isDirectory: true)
6162
try FileManager.default.createDirectory(at: tmpDirURL, withIntermediateDirectories: true)
6263
let localMasterkeyURL = tmpDirURL.appendingPathComponent(UUID().uuidString, isDirectory: false)
63-
let masterkeyData = try self.exportMasterkey(masterkey, password: password)
64+
let masterkeyData = try self.exportMasterkey(masterkey, vaultVersion: vaultVersion, password: password)
6465
try masterkeyData.write(to: localMasterkeyURL)
6566
let masterkeyCloudPath = vaultPath.appendingPathComponent("masterkey.cryptomator")
6667
return delegate.uploadFile(from: localMasterkeyURL, to: masterkeyCloudPath, replaceExisting: false)
@@ -76,8 +77,10 @@ public class VaultManager {
7677
let shorteningDecorator = try VaultFormat7ShorteningProviderDecorator(delegate: decorator, vaultPath: vaultPath)
7778
let account = VaultAccount(vaultUID: vaultUID, delegateAccountUID: delegateAccountUID, vaultPath: vaultPath, lastUpToDateCheck: Date())
7879
try self.vaultAccountManager.saveNewAccount(account)
79-
try self.saveFileProviderConformMasterkeyToKeychain(masterkey, forVaultUID: vaultUID, password: password, storePasswordInKeychain: storePasswordInKeychain)
80+
try self.saveFileProviderConformMasterkeyToKeychain(masterkey, forVaultUID: vaultUID, vaultVersion: vaultVersion, password: password, storePasswordInKeychain: storePasswordInKeychain)
8081
VaultManager.cachedDecorators[vaultUID] = shorteningDecorator
82+
}.then {
83+
self.addFileProviderDomain(forVaultUID: vaultUID, vaultPath: vaultPath)
8184
}
8285
} catch {
8386
return Promise(error)
@@ -102,19 +105,20 @@ public class VaultManager {
102105
*/
103106
public func manualUnlockVault(withUID vaultUID: String, password: String) throws -> CloudProvider {
104107
let keychainEntry = try getVaultFromKeychain(forVaultUID: vaultUID)
105-
let masterkey = try Masterkey.createFromMasterkeyFile(jsonData: keychainEntry.masterkeyData, password: password)
106-
return try createVaultDecorator(from: masterkey, vaultUID: vaultUID)
108+
let masterkeyFile = try MasterkeyFile.withContentFromData(data: keychainEntry.masterkeyData)
109+
let masterkey = try masterkeyFile.unlock(passphrase: password)
110+
return try createVaultDecorator(from: masterkey, vaultUID: vaultUID, vaultVersion: masterkeyFile.version)
107111
}
108112

109-
func createVaultDecorator(from masterkey: Masterkey, vaultUID: String) throws -> CloudProvider {
113+
func createVaultDecorator(from masterkey: Masterkey, vaultUID: String, vaultVersion: Int) throws -> CloudProvider {
110114
let vaultAccount = try vaultAccountManager.getAccount(with: vaultUID)
111115
let delegate = try providerManager.getProvider(with: vaultAccount.delegateAccountUID)
112-
return try createVaultDecorator(from: masterkey, delegate: delegate, vaultPath: vaultAccount.vaultPath, vaultUID: vaultUID)
116+
return try createVaultDecorator(from: masterkey, delegate: delegate, vaultPath: vaultAccount.vaultPath, vaultUID: vaultUID, vaultVersion: vaultVersion)
113117
}
114118

115-
func createVaultDecorator(from masterkey: Masterkey, delegate: CloudProvider, vaultPath: CloudPath, vaultUID: String) throws -> CloudProvider {
119+
func createVaultDecorator(from masterkey: Masterkey, delegate: CloudProvider, vaultPath: CloudPath, vaultUID: String, vaultVersion: Int) throws -> CloudProvider {
116120
let cryptor = Cryptor(masterkey: masterkey)
117-
switch masterkey.version {
121+
switch vaultVersion {
118122
case 7:
119123
let decorator = try VaultFormat7ProviderDecorator(delegate: delegate, vaultPath: vaultPath, cryptor: cryptor)
120124
let shorteningDecorator = try VaultFormat7ShorteningProviderDecorator(delegate: decorator, vaultPath: vaultPath)
@@ -140,8 +144,9 @@ public class VaultManager {
140144
guard let password = vault.password else {
141145
throw VaultManagerError.passwordNotInKeychain
142146
}
143-
let masterkey = try Masterkey.createFromMasterkeyFile(jsonData: vault.masterkeyData, password: password)
144-
return try createVaultDecorator(from: masterkey, vaultUID: vaultUID)
147+
let masterkeyFile = try MasterkeyFile.withContentFromData(data: vault.masterkeyData)
148+
let masterkey = try masterkeyFile.unlock(passphrase: password)
149+
return try createVaultDecorator(from: masterkey, vaultUID: vaultUID, vaultVersion: masterkeyFile.version)
145150
}
146151

147152
/**
@@ -161,12 +166,15 @@ public class VaultManager {
161166
let tmpDirURL = FileManager.default.temporaryDirectory
162167
let localMasterkeyURL = tmpDirURL.appendingPathComponent(UUID().uuidString, isDirectory: false)
163168
return delegate.downloadFile(from: masterkeyPath, to: localMasterkeyURL).then {
164-
let masterkey = try Masterkey.createFromMasterkeyFile(fileURL: localMasterkeyURL, password: password)
169+
let masterkeyFile = try MasterkeyFile.withContentFromURL(url: localMasterkeyURL)
170+
let masterkey = try masterkeyFile.unlock(passphrase: password)
165171
let vaultPath = self.getVaultPath(from: masterkeyPath)
166-
_ = try self.createVaultDecorator(from: masterkey, delegate: delegate, vaultPath: vaultPath, vaultUID: vaultUID)
172+
_ = try self.createVaultDecorator(from: masterkey, delegate: delegate, vaultPath: vaultPath, vaultUID: vaultUID, vaultVersion: masterkeyFile.version)
167173
let vaultAccount = VaultAccount(vaultUID: vaultUID, delegateAccountUID: delegateAccountUID, vaultPath: vaultPath, lastUpToDateCheck: Date())
168-
try self.saveFileProviderConformMasterkeyToKeychain(masterkey, forVaultUID: vaultUID, password: password, storePasswordInKeychain: storePasswordInKeychain)
174+
try self.saveFileProviderConformMasterkeyToKeychain(masterkey, forVaultUID: vaultUID, vaultVersion: masterkeyFile.version, password: password, storePasswordInKeychain: storePasswordInKeychain)
169175
try self.vaultAccountManager.saveNewAccount(vaultAccount)
176+
}.then {
177+
self.addFileProviderDomain(forVaultUID: vaultUID, vaultPath: self.getVaultPath(from: masterkeyPath))
170178
}
171179
} catch {
172180
VaultManager.cachedDecorators[vaultUID] = nil
@@ -220,8 +228,8 @@ public class VaultManager {
220228
/**
221229
- Postcondition: The masterkey is stored in the keychain with a ScryptCostParameter, which allows the usage in the FileProviderExtension (15mb Memory Limit). Additionally: storePasswordInKeychain <=> the password for the masterkey is also stored in the keychain.
222230
*/
223-
func saveFileProviderConformMasterkeyToKeychain(_ masterkey: Masterkey, forVaultUID vaultUID: String, password: String, storePasswordInKeychain: Bool) throws {
224-
let masterkeyDataForFileProvider = try masterkey.exportEncrypted(password: password, pepper: [UInt8](), scryptCostParam: VaultManager.scryptCostParamForFileProvider)
231+
func saveFileProviderConformMasterkeyToKeychain(_ masterkey: Masterkey, forVaultUID vaultUID: String, vaultVersion: Int, password: String, storePasswordInKeychain: Bool) throws {
232+
let masterkeyDataForFileProvider = try MasterkeyFile.lock(masterkey: masterkey, vaultVersion: vaultVersion, passphrase: password, pepper: [UInt8](), scryptCostParam: VaultManager.scryptCostParamForFileProvider)
225233
let keychainEntry = VaultKeychainEntry(masterkeyData: masterkeyDataForFileProvider, password: storePasswordInKeychain ? password : nil)
226234
let jsonEnccoder = JSONEncoder()
227235
let encodedEntry = try jsonEnccoder.encode(keychainEntry)
@@ -239,8 +247,8 @@ public class VaultManager {
239247
return masterkeyPath.deletingLastPathComponent()
240248
}
241249

242-
func exportMasterkey(_ masterkey: Masterkey, password: String) throws -> Data {
243-
return try masterkey.exportEncrypted(password: password)
250+
func exportMasterkey(_ masterkey: Masterkey, vaultVersion: Int, password: String) throws -> Data {
251+
return try MasterkeyFile.lock(masterkey: masterkey, vaultVersion: vaultVersion, passphrase: password)
244252
}
245253

246254
func removeFileProviderDomain(withVaultUID vaultUID: String) -> Promise<Void> {
@@ -254,6 +262,12 @@ public class VaultManager {
254262
NSFileProviderManager.remove(domainForVault)
255263
}
256264
}
265+
266+
func addFileProviderDomain(forVaultUID vaultUID: String, vaultPath: CloudPath) -> Promise<Void> {
267+
let identifier = NSFileProviderDomainIdentifier(vaultUID)
268+
let domain = NSFileProviderDomain(identifier: identifier, displayName: vaultPath.lastPathComponent, pathRelativeToDocumentStorage: vaultUID)
269+
return NSFileProviderManager.add(domain)
270+
}
257271
}
258272

259273
extension NSFileProviderManager {
@@ -280,4 +294,16 @@ extension NSFileProviderManager {
280294
}
281295
}
282296
}
297+
298+
class func add(_ domain: NSFileProviderDomain) -> Promise<Void> {
299+
return Promise<Void> { fulfill, reject in
300+
NSFileProviderManager.add(domain) { error in
301+
if let error = error {
302+
reject(error)
303+
} else {
304+
fulfill(())
305+
}
306+
}
307+
}
308+
}
283309
}

0 commit comments

Comments
 (0)