Move files and Defaults to the shared container
This commit is contained in:
parent
8f91c4c516
commit
850dc75820
5 changed files with 82 additions and 24 deletions
|
|
@ -10,6 +10,7 @@
|
|||
94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADCE7A5C3CCC67D7D21BB3C4 /* libPods-pass.a */; };
|
||||
A217ACE21E9AB17C00A1A6CF /* OTPScannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A217ACE11E9AB17C00A1A6CF /* OTPScannerController.swift */; };
|
||||
A217ACE41E9BBBBD00A1A6CF /* GitConfigSettingTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A217ACE31E9BBBBD00A1A6CF /* GitConfigSettingTableViewController.swift */; };
|
||||
A26075721EEC6B8D005DB03E /* SwiftyUserDefaults.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCA049951E3357E000522E8F /* SwiftyUserDefaults.framework */; };
|
||||
A262A58D1E68749C006B0890 /* Base32.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A262A58C1E68749C006B0890 /* Base32.framework */; };
|
||||
A26700271EEC466A00176B8A /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A26700261EEC466A00176B8A /* ActionViewController.swift */; };
|
||||
A267002A1EEC466A00176B8A /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A26700281EEC466A00176B8A /* MainInterface.storyboard */; };
|
||||
|
|
@ -198,6 +199,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A26075721EEC6B8D005DB03E /* SwiftyUserDefaults.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -738,6 +740,10 @@
|
|||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = passextension/passextension.entitlements;
|
||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
);
|
||||
INFOPLIST_FILE = passextension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
|
|
@ -755,6 +761,10 @@
|
|||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = passextension/passextension.entitlements;
|
||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
);
|
||||
INFOPLIST_FILE = passextension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
error conditions that could cause the creation of the store to fail.
|
||||
*/
|
||||
let container = NSPersistentContainer(name: "pass")
|
||||
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
|
||||
let description = NSPersistentStoreDescription(url: Globals.sharedContainerURL)
|
||||
container.loadPersistentStores(completionHandler: { (description, error) in
|
||||
if let error = error as NSError? {
|
||||
// Replace this implementation with code to handle the error appropriately.
|
||||
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
import Foundation
|
||||
import SwiftyUserDefaults
|
||||
|
||||
var Defaults = UserDefaults(suiteName: Globals.groupIdentifier)!
|
||||
|
||||
extension DefaultsKeys {
|
||||
static let pgpKeySource = DefaultsKey<String?>("pgpKeySource")
|
||||
static let pgpPublicKeyURL = DefaultsKey<URL?>("pgpPublicKeyURL")
|
||||
|
|
|
|||
|
|
@ -10,15 +10,26 @@ import Foundation
|
|||
import UIKit
|
||||
|
||||
class Globals {
|
||||
static let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
|
||||
static let libraryPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0];
|
||||
static let pgpPublicKeyPath = "\(documentPath)/gpg_key.pub"
|
||||
static let pgpPrivateKeyPath = "\(documentPath)/gpg_key"
|
||||
|
||||
static let gitSSHPrivateKeyPath = "\(documentPath)/ssh_key"
|
||||
static let gitSSHPrivateKeyURL = URL(fileURLWithPath: gitSSHPrivateKeyPath)
|
||||
|
||||
static let repositoryPath = "\(libraryPath)/password-store"
|
||||
// Legacy paths (not shared)
|
||||
static let documentPathLegacy = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
|
||||
static let libraryPathLegacy = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0];
|
||||
static let pgpPublicKeyPathLegacy = "\(documentPathLegacy)/gpg_key.pub"
|
||||
static let pgpPrivateKeyPathLegacy = "\(documentPathLegacy)/gpg_key"
|
||||
static let gitSSHPrivateKeyPathLegacy = "\(documentPathLegacy)/ssh_key"
|
||||
static let gitSSHPrivateKeyURLLegacy = URL(fileURLWithPath: gitSSHPrivateKeyPathLegacy)
|
||||
static let repositoryPathLegacy = "\(libraryPathLegacy)/password-store"
|
||||
|
||||
static let groupIdentifier = "group." + Bundle.main.bundleIdentifier!
|
||||
static let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)!
|
||||
static let documentPath = sharedContainerURL.appendingPathComponent("Keys").path
|
||||
static let libraryPath = sharedContainerURL.appendingPathComponent("Repository").path
|
||||
static let pgpPublicKeyPath = documentPath + "/gpg_key.pub"
|
||||
static let pgpPrivateKeyPath = documentPath + "/gpg_key"
|
||||
static let gitSSHPrivateKeyPath = documentPath + "/ssh_key"
|
||||
static let gitSSHPrivateKeyURL = URL(fileURLWithPath: gitSSHPrivateKeyPath)
|
||||
static let repositoryPath = libraryPath + "/password-store"
|
||||
|
||||
static var passcodeConfiguration = PasscodeLockConfiguration()
|
||||
|
||||
static let passwordDefaultLength = ["Random": (min: 4, max: 64, def: 16),
|
||||
|
|
|
|||
|
|
@ -68,14 +68,40 @@ class PasswordStore {
|
|||
}
|
||||
}
|
||||
|
||||
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
|
||||
let fm = FileManager.default
|
||||
lazy var context: NSManagedObjectContext = {
|
||||
/*
|
||||
The persistent container for the application. This implementation
|
||||
creates and returns a container, having loaded the store for the
|
||||
application to it. This property is optional since there are legitimate
|
||||
error conditions that could cause the creation of the store to fail.
|
||||
*/
|
||||
let container = NSPersistentContainer(name: "pass")
|
||||
let description = NSPersistentStoreDescription(url: Globals.sharedContainerURL)
|
||||
container.loadPersistentStores(completionHandler: { (description, error) in
|
||||
if let error = error as NSError? {
|
||||
// Replace this implementation with code to handle the error appropriately.
|
||||
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
||||
|
||||
/*
|
||||
Typical reasons for an error here include:
|
||||
* The parent directory does not exist, cannot be created, or disallows writing.
|
||||
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
|
||||
* The device is out of space.
|
||||
* The store could not be migrated to the current model version.
|
||||
Check the error message to determine what the actual problem was.
|
||||
*/
|
||||
fatalError("Unresolved error \(error), \(error.userInfo)")
|
||||
}
|
||||
})
|
||||
return container.viewContext
|
||||
}()
|
||||
|
||||
var numberOfPasswords : Int {
|
||||
return self.fetchPasswordEntityCoreData(withDir: false).count
|
||||
}
|
||||
|
||||
var sizeOfRepositoryByteCount : UInt64 {
|
||||
let fm = FileManager.default
|
||||
var size = UInt64(0)
|
||||
do {
|
||||
if fm.fileExists(atPath: self.storeURL.path) {
|
||||
|
|
@ -89,8 +115,11 @@ class PasswordStore {
|
|||
|
||||
|
||||
private init() {
|
||||
// File migration to group
|
||||
migration()
|
||||
|
||||
do {
|
||||
if FileManager.default.fileExists(atPath: storeURL.path) {
|
||||
if fm.fileExists(atPath: storeURL.path) {
|
||||
try storeRepository = GTRepository.init(url: storeURL)
|
||||
}
|
||||
try initPGPKeys()
|
||||
|
|
@ -99,6 +128,20 @@ class PasswordStore {
|
|||
}
|
||||
}
|
||||
|
||||
private func migration() {
|
||||
let needMigration = fm.fileExists(atPath: Globals.documentPathLegacy) && !fm.fileExists(atPath: Globals.documentPath) && fm.fileExists(atPath: Globals.libraryPathLegacy) && !fm.fileExists(atPath: Globals.libraryPath)
|
||||
guard needMigration == true else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
try fm.copyItem(atPath: Globals.documentPathLegacy, toPath: Globals.documentPath)
|
||||
try fm.copyItem(atPath: Globals.libraryPathLegacy, toPath: Globals.libraryPath)
|
||||
} catch {
|
||||
print("Cannot migrate: \(error)")
|
||||
}
|
||||
updatePasswordEntityCoreData()
|
||||
}
|
||||
|
||||
enum SSHKeyType {
|
||||
case `public`, secret
|
||||
}
|
||||
|
|
@ -160,7 +203,6 @@ class PasswordStore {
|
|||
|
||||
|
||||
private func importKey(from keyPath: String) -> PGPKey? {
|
||||
let fm = FileManager.default
|
||||
if fm.fileExists(atPath: keyPath) {
|
||||
if let keys = pgp.importKeys(fromFile: keyPath, allowDuplicates: false) as? [PGPKey] {
|
||||
return keys.first
|
||||
|
|
@ -230,7 +272,6 @@ class PasswordStore {
|
|||
let credentialProvider = try credential.credentialProvider()
|
||||
let options = [GTRepositoryCloneOptionsCredentialProvider: credentialProvider]
|
||||
storeRepository = try GTRepository.clone(from: remoteRepoURL, toWorkingDirectory: tempStoreURL, options: options, transferProgressBlock:transferProgressBlock)
|
||||
let fm = FileManager.default
|
||||
if fm.fileExists(atPath: storeURL.path) {
|
||||
try fm.removeItem(at: storeURL)
|
||||
}
|
||||
|
|
@ -271,7 +312,6 @@ class PasswordStore {
|
|||
|
||||
private func updatePasswordEntityCoreData() {
|
||||
deleteCoreData(entityName: "PasswordEntity")
|
||||
let fm = FileManager.default
|
||||
do {
|
||||
var q = try fm.contentsOfDirectory(atPath: self.storeURL.path).filter{
|
||||
!$0.hasPrefix(".")
|
||||
|
|
@ -443,8 +483,8 @@ class PasswordStore {
|
|||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
let url = storeURL.appendingPathComponent(path)
|
||||
if FileManager.default.fileExists(atPath: url.path) {
|
||||
try FileManager.default.removeItem(at: url)
|
||||
if fm.fileExists(atPath: url.path) {
|
||||
try fm.removeItem(at: url)
|
||||
}
|
||||
try storeRepository.index().removeFile(path)
|
||||
try storeRepository.index().write()
|
||||
|
|
@ -452,7 +492,6 @@ class PasswordStore {
|
|||
|
||||
private func deleteDirectoryTree(at url: URL) throws {
|
||||
var tempURL = storeURL.appendingPathComponent(url.deletingLastPathComponent().path)
|
||||
let fm = FileManager.default
|
||||
var count = try fm.contentsOfDirectory(atPath: tempURL.path).count
|
||||
while count == 0 {
|
||||
try fm.removeItem(at: tempURL)
|
||||
|
|
@ -463,13 +502,12 @@ class PasswordStore {
|
|||
|
||||
private func createDirectoryTree(at url: URL) throws {
|
||||
let tempURL = storeURL.appendingPathComponent(url.deletingLastPathComponent().path)
|
||||
try FileManager.default.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil)
|
||||
try fm.createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil)
|
||||
}
|
||||
|
||||
private func gitMv(from: String, to: String) throws {
|
||||
let fromURL = storeURL.appendingPathComponent(from)
|
||||
let toURL = storeURL.appendingPathComponent(to)
|
||||
let fm = FileManager.default
|
||||
guard fm.fileExists(atPath: fromURL.path) else {
|
||||
print("\(from) not exist")
|
||||
return
|
||||
|
|
@ -779,8 +817,6 @@ class PasswordStore {
|
|||
return encryptedData
|
||||
}
|
||||
|
||||
|
||||
|
||||
func removePGPKeys() {
|
||||
Utils.removeFileIfExists(atPath: Globals.pgpPublicKeyPath)
|
||||
Utils.removeFileIfExists(atPath: Globals.pgpPrivateKeyPath)
|
||||
|
|
@ -803,12 +839,10 @@ class PasswordStore {
|
|||
}
|
||||
|
||||
func gitSSHKeyExists() -> Bool {
|
||||
let fm = FileManager.default
|
||||
return fm.fileExists(atPath: Globals.gitSSHPrivateKeyPath)
|
||||
}
|
||||
|
||||
func pgpKeyExists() -> Bool {
|
||||
let fm = FileManager.default
|
||||
return fm.fileExists(atPath: Globals.pgpPublicKeyPath) && fm.fileExists(atPath: Globals.pgpPrivateKeyPath)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue