Skip to content
This repository has been archived by the owner on Oct 6, 2023. It is now read-only.

Commit

Permalink
Added iCloud backups
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanLipnik committed Aug 24, 2021
1 parent 80db301 commit 65b9fce
Show file tree
Hide file tree
Showing 14 changed files with 287 additions and 18 deletions.
15 changes: 15 additions & 0 deletions AutoFill iOS/AutoFill_iOS.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,23 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.ethanlipnik.OpenSesame</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
<string>CloudDocuments</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.com.ethanlipnik.OpenSesame</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.OpenSesame.ethanlipnik</string>
Expand Down
15 changes: 15 additions & 0 deletions AutoFill macOS/AutoFill_macOS.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,23 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.aps-environment</key>
<string>development</string>
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.ethanlipnik.OpenSesame</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudDocuments</string>
<string>CloudKit</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.com.ethanlipnik.OpenSesame</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.OpenSesame.ethanlipnik</string>
Expand Down
5 changes: 5 additions & 0 deletions OpenSesame (iOS).entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
<string>CloudDocuments</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.com.ethanlipnik.OpenSesame</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
Expand Down
5 changes: 5 additions & 0 deletions OpenSesame (macOS).entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudKit</string>
<string>CloudDocuments</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.com.ethanlipnik.OpenSesame</string>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
Expand Down
12 changes: 12 additions & 0 deletions OpenSesame--iOS--Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,17 @@
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.com.ethanlipnik.OpenSesame</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerName</key>
<string>OpenSesame</string>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
</dict>
</dict>
</dict>
</plist>
12 changes: 12 additions & 0 deletions OpenSesame--macOS--Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,17 @@
<array>
<string>_OpenSesame._tcp</string>
</array>
<key>NSUbiquitousContainers</key>
<dict>
<key>iCloud.com.ethanlipnik.OpenSesame</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerName</key>
<string>OpenSesame</string>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
</dict>
</dict>
</dict>
</plist>
22 changes: 21 additions & 1 deletion OpenSesame.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
AA016A3226D577B8007397A7 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA016A3126D577B8007397A7 /* SettingsView.swift */; };
AA016A3326D581D4007397A7 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA8B504626CD6457003C92AE /* CloudKit.framework */; };
AA016A3426D581DF007397A7 /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA8B504926CD6468003C92AE /* CloudKit.framework */; };
AA016A3626D586DC007397A7 /* SettingsView+SyncView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA016A3526D586DC007397A7 /* SettingsView+SyncView.swift */; };
AA05CCB626CD7A0800E27F6D /* FaviconFinder in Frameworks */ = {isa = PBXBuildFile; productRef = AA05CCB526CD7A0800E27F6D /* FaviconFinder */; };
AA05CCB826CD7A0D00E27F6D /* FaviconFinder in Frameworks */ = {isa = PBXBuildFile; productRef = AA05CCB726CD7A0D00E27F6D /* FaviconFinder */; };
AA05CCCC26CDA6BE00E27F6D /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = AA05CCCB26CDA6BE00E27F6D /* KeychainAccess */; };
Expand Down Expand Up @@ -215,6 +219,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
AA016A3126D577B8007397A7 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SettingsView.swift; path = "../../../../../../../../../../Macintosh HD/Users/ethan/Projects/OpenSesame/OpenSesame/Shared/Views/SettingsView/iOS/SettingsView.swift"; sourceTree = "<group>"; };
AA016A3526D586DC007397A7 /* SettingsView+SyncView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "SettingsView+SyncView.swift"; path = "../../../../../../../../../../Macintosh HD/Users/ethan/Projects/OpenSesame/OpenSesame/Shared/Views/SettingsView/macOS/SettingsView+SyncView.swift"; sourceTree = "<group>"; };
AA05CCD426CDB85000E27F6D /* UserAuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAuthenticationService.swift; sourceTree = "<group>"; };
AA05CCE026CDDA5200E27F6D /* AutoFill iOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "AutoFill iOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
AA05CCE326CDDA5200E27F6D /* CredentialProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialProviderViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -294,6 +300,7 @@
buildActionMask = 2147483647;
files = (
AA05CCE126CDDA5200E27F6D /* AuthenticationServices.framework in Frameworks */,
AA016A3326D581D4007397A7 /* CloudKit.framework in Frameworks */,
AA05CCF426CDDBFF00E27F6D /* DomainParser in Frameworks */,
AA05CD0626CDE08C00E27F6D /* KeychainAccess in Frameworks */,
);
Expand All @@ -304,6 +311,7 @@
buildActionMask = 2147483647;
files = (
AA519A7526CEE6CA00C1E354 /* DomainParser in Frameworks */,
AA016A3426D581DF007397A7 /* CloudKit.framework in Frameworks */,
AA519A7326CEE6CA00C1E354 /* KeychainAccess in Frameworks */,
AA519A5E26CEE5B700C1E354 /* AuthenticationServices.framework in Frameworks */,
);
Expand Down Expand Up @@ -356,6 +364,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
AA016A3026D577AC007397A7 /* iOS */ = {
isa = PBXGroup;
children = (
AA016A3126D577B8007397A7 /* SettingsView.swift */,
);
path = iOS;
sourceTree = "<group>";
};
AA02830326D04B13004FCEA7 /* AppDelegate */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -418,13 +434,13 @@
isa = PBXGroup;
children = (
AAD3DBDC26D3417500531E92 /* MainView.swift */,
AAD3DB8F26D3258900531E92 /* FaviconView.swift */,
AAD3DB9F26D330A400531E92 /* ContentView */,
AAD3DB9226D3265700531E92 /* LockView */,
AAD3DB8026D30D3300531E92 /* ImportExport */,
AA05CCCF26CDB16A00E27F6D /* Vault */,
AAD3DBB726D33B6400531E92 /* AccountView */,
AAE4A8BB26CDFB3200D1C58E /* SettingsView */,
AAD3DB8F26D3258900531E92 /* FaviconView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -592,6 +608,7 @@
isa = PBXGroup;
children = (
AAE4A8BC26CDFB3200D1C58E /* SettingsView.swift */,
AA016A3526D586DC007397A7 /* SettingsView+SyncView.swift */,
AA49EA4A26D3EBE100B12838 /* SettingsView+GeneralView.swift */,
AA49EA4B26D3EBE100B12838 /* SettingsView+MenuBarView.swift */,
);
Expand All @@ -612,6 +629,7 @@
AAE4A8BB26CDFB3200D1C58E /* SettingsView */ = {
isa = PBXGroup;
children = (
AA016A3026D577AC007397A7 /* iOS */,
AAD3DBDF26D341BA00531E92 /* macOS */,
);
path = SettingsView;
Expand Down Expand Up @@ -942,6 +960,7 @@
AA49EA1726D3EB2600B12838 /* LockView+UnlockButtons.swift in Sources */,
AA49EA1326D3EB2600B12838 /* LockView+Functions.swift in Sources */,
AA49EA0426D3EB0100B12838 /* AppDelegate iOS.swift in Sources */,
AA016A3226D577B8007397A7 /* SettingsView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -974,6 +993,7 @@
AA49EA0C26D3EB1600B12838 /* ContentView+List.swift in Sources */,
AA49EA3126D3EB8600B12838 /* AccountDetailView+OTPView.swift in Sources */,
AA49EA1226D3EB2600B12838 /* LockView+CreatePassword.swift in Sources */,
AA016A3626D586DC007397A7 /* SettingsView+SyncView.swift in Sources */,
AA49EA4026D3EBA300B12838 /* Data+Misc.swift in Sources */,
AA49EA1426D3EB2600B12838 /* LockView+Functions.swift in Sources */,
AA49EA0626D3EB0400B12838 /* AppDelegate macOS.swift in Sources */,
Expand Down
54 changes: 54 additions & 0 deletions Shared/Persistence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ struct PersistenceController {
}
return result
}()

static var containerUrl: URL? {
return FileManager.default.url(forUbiquityContainerIdentifier: nil)
}

let container: NSPersistentCloudKitContainer

Expand Down Expand Up @@ -63,6 +67,22 @@ struct PersistenceController {
UserDefaults(suiteName: "group.OpenSesame.ethanlipnik")?.set(1.1, forKey: "coreDataVersion")
}

loadStore()

// Check if iCloud Drive folder exists, if not, create one.
if let url = PersistenceController.containerUrl, !FileManager.default.fileExists(atPath: url.path, isDirectory: nil) {
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
}
catch {
print(error.localizedDescription)
}
}

print("iCloud Drive folder location", PersistenceController.containerUrl?.path as Any)
}

func loadStore() {
let viewContext = container.viewContext
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
Expand All @@ -85,6 +105,40 @@ struct PersistenceController {
}
})
}

func uploadStoreTo(_ service: CloudService) throws {
switch service {
case .iCloud:
if let iCloudContainer = PersistenceController.containerUrl?.appendingPathComponent("group.OpenSesame.ethanlipnik.sqlite") {
if FileManager.default.fileExists(atPath: iCloudContainer.path) {
try FileManager.default.removeItem(at: iCloudContainer)
}
try FileManager.default.copyItem(at: PersistenceController.storeURL, to: iCloudContainer)

print("Uploaded store to iCloud", iCloudContainer.path)
} else {
throw CocoaError(.fileNoSuchFile)
}
}
}

func downloadStoreFrom(_ service: CloudService) throws {
switch service {
case .iCloud:
if let iCloudContainer = PersistenceController.containerUrl?.appendingPathComponent("group.OpenSesame.ethanlipnik.sqlite") {
if FileManager.default.fileExists(atPath: PersistenceController.storeURL.path) {
try FileManager.default.removeItem(at: PersistenceController.storeURL)
}
try FileManager.default.copyItem(at: iCloudContainer, to: PersistenceController.storeURL)

loadStore()
}
}
}

enum CloudService {
case iCloud
}
}

public extension URL {
Expand Down
17 changes: 13 additions & 4 deletions Shared/Views/ContentView/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,19 @@ struct ContentView: View {
list
.toolbar {
ToolbarItem(placement: ToolbarItemPlacement.navigation) {
Button {
isLocked = true
} label: {
Label("Lock", systemImage: "lock.fill")
HStack {
Button {
isLocked = true
} label: {
Label("Lock", systemImage: "lock.fill")
}
#if os(iOS)
NavigationLink {
SettingsView()
} label: {
Label("Settings", systemImage: "gearshape.fill")
}
#endif
}
}
#if os(iOS)
Expand Down
37 changes: 37 additions & 0 deletions Shared/Views/LockView/LockView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct LockView: View {
@State var encryptionTest: Data? = nil

@State var isAuthenticating: Bool = false
@State var needsToResetPassword: Bool = false


// MARK: - Variable Types
Expand Down Expand Up @@ -67,6 +68,42 @@ struct LockView: View {
.padding()
.navigationTitle("OpenSesame")

#if os(macOS)
.toolbar { // LockView only toolbar
ToolbarItem(placement: .primaryAction) {
if isLocked {
Button {
needsToResetPassword.toggle()
} label: {
Label("Info", systemImage: "info")
}
}
}
}
#else
.overlay(Button(action: {
needsToResetPassword.toggle()
}, label: {
Image(systemName: "info")
}).padding(), alignment: .topTrailing)
#endif
.alert("Forgot your password?", isPresented: $needsToResetPassword, actions: {
Button("Reset password") {
let keychain = Keychain(service: "com.ethanlipnik.OpenSesame", accessGroup: "B6QG723P8Z.OpenSesame")
.synchronizable(true)

try! keychain
.remove("masterPassword")
try! keychain
.remove("encryptionTest")

encryptionTest = nil
encryptionTestDoesntExist = true
}
}, message: {
Text("You can change it but you won't be able to decrypt any of your accounts.")
})

// MARK: - Master Password Creation
.sheet(isPresented: $encryptionTestDoesntExist) {
CreatePasswordView(completionAction: createMasterPassword)
Expand Down
14 changes: 1 addition & 13 deletions Shared/Views/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import SwiftUI
import KeychainAccess

struct MainView: View {
// MARK: - Environment
Expand Down Expand Up @@ -42,19 +43,6 @@ struct MainView: View {
.blur(radius: isLocked ? 0 : 25)
.allowsHitTesting(isLocked) // Prevent lock screen from being interacted with even though it's in the foreground.
.animation(.default, value: isLocked)
#if os(macOS)
.toolbar { // LockView only toolbar
ToolbarItem(placement: .primaryAction) {
if isLocked {
Button {

} label: {
Label("Info", systemImage: "info")
}
}
}
}
#endif
}
#if os(macOS)
.blur(radius: shouldHideApp ? 25 : 0)
Expand Down

0 comments on commit 65b9fce

Please sign in to comment.