From b2ee8c429f8f4e7e25afc5f4391ea4949dec8de1 Mon Sep 17 00:00:00 2001 From: Bob Sun Date: Mon, 13 Feb 2017 01:15:42 +0800 Subject: [PATCH] support edit password --- pass.xcodeproj/project.pbxproj | 12 +++ pass/Base.lproj/Main.storyboard | 75 +++++++++++--- .../EditPasswordTableViewController.swift | 53 ++++++++++ .../PasswordDetailTableViewController.swift | 83 +++++++++++++--- .../PasswordEditorTableViewController.swift | 77 +++++++++++++++ .../Controllers/PasswordsViewController.swift | 1 + pass/Models/Password.swift | 97 +++++++++++++------ pass/Models/PasswordEntity.swift | 1 - pass/Models/PasswordStore.swift | 64 +++++++++++- pass/Views/ContentTableViewCell.swift | 28 ++++++ pass/Views/FillPasswordTableViewCell.swift | 10 +- pass/Views/TextFieldTableViewCell.swift | 8 +- pass/Views/TextViewTableViewCell.swift | 9 +- pass/Views/TextViewTableViewCell.xib | 13 ++- 14 files changed, 459 insertions(+), 72 deletions(-) create mode 100644 pass/Controllers/EditPasswordTableViewController.swift create mode 100644 pass/Controllers/PasswordEditorTableViewController.swift create mode 100644 pass/Views/ContentTableViewCell.swift diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 4b58c8f..6cbe651 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -55,6 +55,9 @@ DCFB779F1E4F40C7008DE471 /* FillPasswordTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB779D1E4F40C7008DE471 /* FillPasswordTableViewCell.xib */; }; DCFB77A11E4F68C8008DE471 /* PasswordEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77A01E4F68C8008DE471 /* PasswordEntity.swift */; }; DCFB77A31E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */; }; + DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */; }; + DCFB77A91E502FF6008DE471 /* PasswordEditorTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */; }; + DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -111,6 +114,9 @@ DCFB779D1E4F40C7008DE471 /* FillPasswordTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FillPasswordTableViewCell.xib; sourceTree = ""; }; DCFB77A01E4F68C8008DE471 /* PasswordEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordEntity.swift; sourceTree = ""; }; DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordDetailTitleTableViewCell.xib; sourceTree = ""; }; + DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditPasswordTableViewController.swift; sourceTree = ""; }; + DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordEditorTableViewController.swift; sourceTree = ""; }; + DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTableViewCell.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -144,6 +150,8 @@ isa = PBXGroup; children = ( DC037CB71E4DD1A500609409 /* AddPasswordTableViewController.swift */, + DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */, + DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */, DC037CB11E4CAB1700609409 /* AboutRepositoryTableViewController.swift */, DC037CAF1E4CA51F00609409 /* GeneralSettingsTableViewController.swift */, DC962CDE1E4B62C10033B5D8 /* AboutTableViewController.swift */, @@ -201,6 +209,7 @@ DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */, DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */, DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */, + DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */, ); path = Views; sourceTree = ""; @@ -408,10 +417,12 @@ DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */, DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */, DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */, + DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */, DCA0499C1E3362F400522E8F /* PGPKeySettingTableViewController.swift in Sources */, DC7E6EEA1E432E48006C2443 /* Password.swift in Sources */, DC4914961E434301007FF592 /* LabelTableViewCell.swift in Sources */, DCAAF7451E2FA66800AB94BC /* SettingsTableViewController.swift in Sources */, + DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */, DCA0499A1E335CC800522E8F /* GitServerSettingTableViewController.swift in Sources */, DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */, DC037CAE1E4C9B9B00609409 /* PasswordRepositorySettingsTableViewController.swift in Sources */, @@ -436,6 +447,7 @@ DC19400B1E4B36B60077E0A3 /* Utils.swift in Sources */, DCA0499E1E33BAC100522E8F /* Globals.swift in Sources */, DCFB77A11E4F68C8008DE471 /* PasswordEntity.swift in Sources */, + DCFB77A91E502FF6008DE471 /* PasswordEditorTableViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/pass/Base.lproj/Main.storyboard b/pass/Base.lproj/Main.storyboard index 267d78c..5d8b354 100644 --- a/pass/Base.lproj/Main.storyboard +++ b/pass/Base.lproj/Main.storyboard @@ -423,7 +423,7 @@ - + @@ -492,7 +492,7 @@ - + @@ -624,7 +624,7 @@ - + @@ -656,7 +656,7 @@ - + @@ -672,10 +672,13 @@ + + + - + @@ -734,6 +737,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -751,7 +786,7 @@ - + @@ -769,7 +804,7 @@ - + @@ -888,7 +923,7 @@ - + @@ -1037,7 +1072,7 @@ - + @@ -1056,7 +1091,7 @@ - + @@ -1074,7 +1109,25 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/pass/Controllers/EditPasswordTableViewController.swift b/pass/Controllers/EditPasswordTableViewController.swift new file mode 100644 index 0000000..af41505 --- /dev/null +++ b/pass/Controllers/EditPasswordTableViewController.swift @@ -0,0 +1,53 @@ +// +// EditPasswordTableViewController.swift +// pass +// +// Created by Mingshen Sun on 12/2/2017. +// Copyright © 2017 Bob Sun. All rights reserved. +// + +import UIKit + +class EditPasswordTableViewController: PasswordEditorTableViewController { + + var password: Password? + + override func viewDidLoad() { + tableData = [ + [[.type: PasswordEditorCellType.textFieldCell, .title: "name", .content: password!.name]], + [[.type: PasswordEditorCellType.fillPasswordCell, .title: "password", .content: password!.password]], + [[.type: PasswordEditorCellType.textViewCell, .title: "additions", .content: password!.getAdditionsPlainText()]], + ] + sectionHeaderTitles = ["name", "password", "additions"].map {$0.uppercased()} + super.viewDidLoad() + } + + override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { + if identifier == "saveEditPasswordSegue" { + let nameCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! ContentTableViewCell + if nameCell.getContent() != password?.name { + let alertMessage = "Editing name is not supported." + let alert = UIAlertController(title: "Cannot Save Edit", message: alertMessage, preferredStyle: UIAlertControllerStyle.alert) + alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) + self.present(alert, animated: true) { + nameCell.setContent(content: self.password!.name) + } + return false + } + } + return true + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + let cells = tableView.visibleCells + var cellContents = [String: String]() + for cell in cells { + let indexPath = tableView.indexPath(for: cell)! + let contentCell = cell as! ContentTableViewCell + let cellTitle = tableData[indexPath.section][indexPath.row][.title] as! String + cellContents[cellTitle] = contentCell.getContent()! + } + password!.updatePassword(name: cellContents["name"]!, plainText: "\(cellContents["password"]!)\n\(cellContents["additions"]!)") + } + +} diff --git a/pass/Controllers/PasswordDetailTableViewController.swift b/pass/Controllers/PasswordDetailTableViewController.swift index 999c261..7d21ccc 100644 --- a/pass/Controllers/PasswordDetailTableViewController.swift +++ b/pass/Controllers/PasswordDetailTableViewController.swift @@ -64,14 +64,13 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni indicator.startAnimating() tableView.addSubview(indicator) tableView.addSubview(indicatorLable) + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(pressEdit(_:))) if let imageData = passwordEntity?.image { let image = UIImage(data: imageData as Data) passwordImage = image } - tableData.append(TableSection(title: "", item: [])) - tableData[0].item.append(TableCell()) DispatchQueue.global(qos: .userInitiated).async { do { @@ -84,21 +83,23 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni self.present(alert, animated: true, completion: nil) } - var tableDataIndex = 1 - self.tableData.append(TableSection(title: "", item: [])) +// var tableDataIndex = 1 +// self.tableData.append(TableSection(title: "", item: [])) +// let password = self.password! +// if let username = password.getUsername() { +// self.tableData[tableDataIndex].item.append(TableCell(title: "username", content: username)) +// } +// self.tableData[tableDataIndex].item.append(TableCell(title: "password", content: password.password)) +// if password.additions.count > 0 { +// self.tableData.append(TableSection(title: "additions", item: [])) +// tableDataIndex += 1 +// for additionKey in password.additionKeys { +// self.tableData[tableDataIndex].item.append(TableCell(title: additionKey, content: password.additions[additionKey]!)) +// +// } +// } let password = self.password! - if let username = password.getUsername() { - self.tableData[tableDataIndex].item.append(TableCell(title: "username", content: username)) - } - self.tableData[tableDataIndex].item.append(TableCell(title: "password", content: password.password)) - if password.additions.count > 0 { - self.tableData.append(TableSection(title: "additions", item: [])) - tableDataIndex += 1 - for additionKey in password.additionKeys { - self.tableData[tableDataIndex].item.append(TableCell(title: additionKey, content: password.additions[additionKey]!)) - - } - } + self.setTableData() DispatchQueue.main.async { [weak self] in self?.tableView.reloadData() indicator.stopAnimating() @@ -112,6 +113,56 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni } } + func pressEdit(_ sender: Any?) { + performSegue(withIdentifier: "editPasswordSegue", sender: self) + } + + @IBAction func cancelEditPassword(segue: UIStoryboardSegue) { + + } + + @IBAction func saveEditPassword(segue: UIStoryboardSegue) { + if password!.changed { + PasswordStore.shared.update(passwordEntity: passwordEntity!, password: password!, progressBlock: { progress in + + }) + NotificationCenter.default.post(Notification(name: Notification.Name("passwordUpdated"))) + setTableData() + tableView.reloadData() + } + } + + func setTableData() { + self.tableData = Array() + tableData.append(TableSection(title: "", item: [])) + tableData[0].item.append(TableCell()) + var tableDataIndex = 1 + self.tableData.append(TableSection(title: "", item: [])) + let password = self.password! + if let username = password.getUsername() { + self.tableData[tableDataIndex].item.append(TableCell(title: "username", content: username)) + } + self.tableData[tableDataIndex].item.append(TableCell(title: "password", content: password.password)) + if password.additions.count > 0 { + self.tableData.append(TableSection(title: "additions", item: [])) + tableDataIndex += 1 + for additionKey in password.additionKeys { + self.tableData[tableDataIndex].item.append(TableCell(title: additionKey, content: password.additions[additionKey]!)) + + } + } + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if segue.identifier == "editPasswordSegue" { + if let controller = segue.destination as? UINavigationController { + if let editController = controller.viewControllers.first as? EditPasswordTableViewController { + editController.password = password + } + } + } + } + func updatePasswordImage(url: String) { do { try FavIcon.downloadPreferred(url) { [weak self] result in diff --git a/pass/Controllers/PasswordEditorTableViewController.swift b/pass/Controllers/PasswordEditorTableViewController.swift new file mode 100644 index 0000000..bdd5b7b --- /dev/null +++ b/pass/Controllers/PasswordEditorTableViewController.swift @@ -0,0 +1,77 @@ +// +// PasswordEditorTableViewController.swift +// pass +// +// Created by Mingshen Sun on 12/2/2017. +// Copyright © 2017 Bob Sun. All rights reserved. +// + +import UIKit +enum PasswordEditorCellType { + case textFieldCell, textViewCell, fillPasswordCell +} + +enum PasswordEditorCellKey { + case type, title, content, placeholders +} + +class PasswordEditorTableViewController: UITableViewController { + var navigationItemTitle: String? + var tableData = [ + [Dictionary] + ]() + var sectionHeaderTitles = [String]() + + override func viewDidLoad() { + super.viewDidLoad() + navigationItem.title = navigationItemTitle + tableView.register(UINib(nibName: "TextFieldTableViewCell", bundle: nil), forCellReuseIdentifier: "textFieldCell") + tableView.register(UINib(nibName: "TextViewTableViewCell", bundle: nil), forCellReuseIdentifier: "textViewCell") + tableView.register(UINib(nibName: "FillPasswordTableViewCell", bundle: nil), forCellReuseIdentifier: "fillPasswordCell") + + + tableView.rowHeight = UITableViewAutomaticDimension + tableView.estimatedRowHeight = 48 + tableView.allowsSelection = false + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cellData = tableData[indexPath.section][indexPath.row] + var cell = ContentTableViewCell() + + switch cellData[PasswordEditorCellKey.type] as! PasswordEditorCellType { + case .textViewCell: + cell = tableView.dequeueReusableCell(withIdentifier: "textViewCell", for: indexPath) as! ContentTableViewCell + case .fillPasswordCell: + cell = tableView.dequeueReusableCell(withIdentifier: "fillPasswordCell", for: indexPath) as! ContentTableViewCell + default: + cell = tableView.dequeueReusableCell(withIdentifier: "textFieldCell", for: indexPath) as! ContentTableViewCell + } + if let content = cellData[PasswordEditorCellKey.content] as? String { + cell.setContent(content: content) + } + return cell + } + + override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return 44 + } + + override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 0.1 + } + + override func numberOfSections(in tableView: UITableView) -> Int { + return tableData.count + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return tableData[section].count + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return sectionHeaderTitles[section] + } + + +} diff --git a/pass/Controllers/PasswordsViewController.swift b/pass/Controllers/PasswordsViewController.swift index 1b0f65b..7062f7c 100644 --- a/pass/Controllers/PasswordsViewController.swift +++ b/pass/Controllers/PasswordsViewController.swift @@ -67,6 +67,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV } }) } + PasswordStore.shared.updatePasswordEntityCoreData() DispatchQueue.main.async { self.passwordEntities = PasswordStore.shared.fetchPasswordEntityCoreData() self.reloadTableView(data: self.passwordEntities!) diff --git a/pass/Models/Password.swift b/pass/Models/Password.swift index 2e5c9a6..a4453b8 100644 --- a/pass/Models/Password.swift +++ b/pass/Models/Password.swift @@ -19,43 +19,34 @@ class Password { var password = "" var additions = [String: String]() var additionKeys = [String]() + var plainText = "" + var changed = false - convenience init(name: String, plainText: String) { - var i = 0 - var additionFieldsArray = [AdditionField]() - var password = "" - var unkownIndex = 0 - plainText.enumerateLines() { line, _ in - if i == 0 { - password = line - } else { - let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: true).map(String.init) - var key = "" - var value = "" - if items.count == 1 { - unkownIndex += 1 - key = "unkown \(unkownIndex)" - value = items[0] - } else { - key = items[0] - value = items[1].trimmingCharacters(in: .whitespaces) - } - additionFieldsArray.append(AdditionField(title: key, content: value)) - } - i += 1 - } - self.init(name: name, password: password, additionsArray: additionFieldsArray) - } - - init(name: String, password: String, additionsArray: [AdditionField]) { + init(name: String, plainText: String) { + let plainTextSplit = plainText.characters.split(maxSplits: 1, omittingEmptySubsequences: false) { + $0 == "\n" || $0 == "\r\n" + }.map(String.init) + let password = plainTextSplit[0] + let additionFieldsArray = Password.getAdditionFields(from: plainTextSplit[1]) +// self.init(name: name, password: password, additionsArray: additionFieldsArray) self.name = name self.password = password - for additionField in additionsArray { + self.plainText = plainText + for additionField in additionFieldsArray { self.additions[additionField.title] = additionField.content self.additionKeys.append(additionField.title) } } +// private convenience init(name: String, password: String, additionsArray: [AdditionField]) { +// self.name = name +// self.password = password +// for additionField in additionsArray { +// self.additions[additionField.title] = additionField.content +// self.additionKeys.append(additionField.title) +// } +// } + func getUsername() -> String? { return getAdditionValue(withKey: "Username") ?? getAdditionValue(withKey: "username") } @@ -64,9 +55,53 @@ class Password { return getAdditionValue(withKey: "URL") ?? getAdditionValue(withKey: "url") ?? getAdditionValue(withKey: "Url") } - func getPlainText() -> String { + static func getAdditionFields(from additionFieldsPlainText: String) -> [AdditionField]{ + var additionFieldsArray = [AdditionField]() + var unkownIndex = 0 + + additionFieldsPlainText.enumerateLines() { line, _ in + let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: true).map(String.init) + var key = "" + var value = "" + if items.count == 1 { + unkownIndex += 1 + key = "unkown \(unkownIndex)" + value = items[0] + } else { + key = items[0] + value = items[1].trimmingCharacters(in: .whitespaces) + } + additionFieldsArray.append(AdditionField(title: key, content: value)) + } + return additionFieldsArray + } + + func updatePassword(name: String, plainText: String) { + self.name = name + if self.plainText != plainText { + let plainTextSplit = plainText.characters.split(maxSplits: 1, omittingEmptySubsequences: false) { + $0 == "\n" || $0 == "\r\n" + }.map(String.init) + let password = plainTextSplit[0] + let additionFieldsArray = Password.getAdditionFields(from: plainTextSplit[1]) + self.password = password + self.additions = [String: String]() + self.additionKeys = [] + for additionField in additionFieldsArray { + self.additions[additionField.title] = additionField.content + self.additionKeys.append(additionField.title) + } + changed = true + } + } + + func getAdditionsPlainText() -> String { let plainAdditionsText = self.additionKeys.map { "\($0): \(self.additions[$0]!)" }.joined(separator: "\n") - return "\(self.password)\n\(plainAdditionsText)" + return plainAdditionsText + } + + func getPlainText() -> String { + return "\(self.password)\n\(getAdditionsPlainText())" } func getPlainData() -> Data { diff --git a/pass/Models/PasswordEntity.swift b/pass/Models/PasswordEntity.swift index df7cf14..c99bc51 100644 --- a/pass/Models/PasswordEntity.swift +++ b/pass/Models/PasswordEntity.swift @@ -22,7 +22,6 @@ extension PasswordEntity { func encrypt(password: Password) throws -> Data { name = password.name - rawPath = "" let plainData = password.getPlainData() let pgp = PasswordStore.shared.pgp let encryptedData = try pgp.encryptData(plainData, usingPublicKey: pgp.getKeysOf(.public)[0], armored: false) diff --git a/pass/Models/PasswordStore.swift b/pass/Models/PasswordStore.swift index a64a43d..74fc0f5 100644 --- a/pass/Models/PasswordStore.swift +++ b/pass/Models/PasswordStore.swift @@ -124,7 +124,7 @@ class PasswordStore { ] let remote = try GTRemote(name: "origin", in: storeRepository!) try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock) - updatePasswordEntityCoreData() +// updatePasswordEntityCoreData() } func updatePasswordEntityCoreData() { @@ -214,7 +214,8 @@ class PasswordStore { func updateRemoteRepo() { } - func createCommitInRepository(message: String, fileData: Data, filename: String, progressBlock: (_ progress: Float) -> Void) -> GTCommit? { + + func addEntryToGTTree(fileData: Data, filename: String) -> GTTree { do { let head = try storeRepository!.headReference() let branch = GTBranch(reference: head, repository: storeRepository!) @@ -224,6 +225,50 @@ class PasswordStore { try treeBulider.addEntry(with: fileData, fileName: filename, fileMode: GTFileMode.blob) let newTree = try treeBulider.writeTree() + return newTree + } catch { + fatalError("Failed to add entries to GTTree: \(error)") + + } + } + + func removeEntryFromGTTree(filename: String) -> GTTree { + do { + let head = try storeRepository!.headReference() + let branch = GTBranch(reference: head, repository: storeRepository!) + let headCommit = try branch?.targetCommit() + + let treeBulider = try GTTreeBuilder(tree: headCommit?.tree, repository: storeRepository!) + try treeBulider.removeEntry(withFileName: filename) + + let newTree = try treeBulider.writeTree() + return newTree + } catch { + fatalError("Failed to remove entries to GTTree: \(error)") + + } + } + + func createAddCommitInRepository(message: String, fileData: Data, filename: String, progressBlock: (_ progress: Float) -> Void) -> GTCommit? { + do { + let newTree = addEntryToGTTree(fileData: fileData, filename: filename) + let headReference = try storeRepository!.headReference() + let commitEnum = try GTEnumerator(repository: storeRepository!) + try commitEnum.pushSHA(headReference.targetOID.sha) + let parent = commitEnum.nextObject() as! GTCommit + progressBlock(0.5) + let commit = try storeRepository!.createCommit(with: newTree, message: message, parents: [parent], updatingReferenceNamed: headReference.name) + progressBlock(0.7) + return commit + } catch { + print(error) + } + return nil + } + + func createRemoveCommitInRepository(message: String, filename: String, progressBlock: (_ progress: Float) -> Void) -> GTCommit? { + do { + let newTree = removeEntryFromGTTree(filename: filename) let headReference = try storeRepository!.headReference() let commitEnum = try GTEnumerator(repository: storeRepository!) try commitEnum.pushSHA(headReference.targetOID.sha) @@ -272,13 +317,26 @@ class PasswordStore { passwordEntity.synced = false try context.save() print(saveURL.path) - let _ = createCommitInRepository(message: "Add new password by pass for iOS", fileData: encryptedData, filename: saveURL.lastPathComponent, progressBlock: progressBlock) + let _ = createAddCommitInRepository(message: "Add new password by pass for iOS", fileData: encryptedData, filename: saveURL.lastPathComponent, progressBlock: progressBlock) progressBlock(1.0) } catch { print(error) } } + func update(passwordEntity: PasswordEntity, password: Password, progressBlock: (_ progress: Float) -> Void) { + do { + let encryptedData = try passwordEntity.encrypt(password: password) + let saveURL = storeURL.appendingPathComponent(passwordEntity.rawPath!) + try encryptedData.write(to: saveURL) + passwordEntity.synced = false + let _ = createAddCommitInRepository(message: "Update password by pass for iOS", fileData: encryptedData, filename: saveURL.lastPathComponent, progressBlock: progressBlock) + try context.save() + } catch { + fatalError("Failed to fetch employees: \(error)") + } + } + func deleteCoreData(entityName: String) { let deleteFetchRequest = NSFetchRequest(entityName: entityName) let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetchRequest) diff --git a/pass/Views/ContentTableViewCell.swift b/pass/Views/ContentTableViewCell.swift new file mode 100644 index 0000000..a434dd2 --- /dev/null +++ b/pass/Views/ContentTableViewCell.swift @@ -0,0 +1,28 @@ +// +// ContentTableViewCell.swift +// pass +// +// Created by Mingshen Sun on 12/2/2017. +// Copyright © 2017 Bob Sun. All rights reserved. +// + +import UIKit + +class ContentTableViewCell: UITableViewCell { + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + } + + func getContent() -> String? { + return nil + } + + func setContent(content: String) { } + +} diff --git a/pass/Views/FillPasswordTableViewCell.swift b/pass/Views/FillPasswordTableViewCell.swift index e1ede54..fdf8bd4 100644 --- a/pass/Views/FillPasswordTableViewCell.swift +++ b/pass/Views/FillPasswordTableViewCell.swift @@ -8,7 +8,7 @@ import UIKit -class FillPasswordTableViewCell: UITableViewCell { +class FillPasswordTableViewCell: ContentTableViewCell { @IBOutlet weak var contentTextField: UITextField! override func awakeFromNib() { @@ -25,4 +25,12 @@ class FillPasswordTableViewCell: UITableViewCell { @IBAction func generatePassword(_ sender: UIButton) { contentTextField.text = Utils.randomString(length: 16) } + + override func getContent() -> String? { + return contentTextField.text + } + + override func setContent(content: String) { + contentTextField.text = content + } } diff --git a/pass/Views/TextFieldTableViewCell.swift b/pass/Views/TextFieldTableViewCell.swift index c134740..d558abf 100644 --- a/pass/Views/TextFieldTableViewCell.swift +++ b/pass/Views/TextFieldTableViewCell.swift @@ -8,7 +8,7 @@ import UIKit -class TextFieldTableViewCell: UITableViewCell { +class TextFieldTableViewCell: ContentTableViewCell { @IBOutlet weak var contentTextField: UITextField! @@ -20,4 +20,10 @@ class TextFieldTableViewCell: UITableViewCell { super.setSelected(selected, animated: animated) } + override func getContent() -> String? { + return contentTextField.text + } + override func setContent(content: String) { + contentTextField.text = content + } } diff --git a/pass/Views/TextViewTableViewCell.swift b/pass/Views/TextViewTableViewCell.swift index 899bf99..bd54287 100644 --- a/pass/Views/TextViewTableViewCell.swift +++ b/pass/Views/TextViewTableViewCell.swift @@ -8,7 +8,7 @@ import UIKit -class TextViewTableViewCell: UITableViewCell { +class TextViewTableViewCell: ContentTableViewCell { @IBOutlet weak var contentTextView: UITextView! override func awakeFromNib() { @@ -18,4 +18,11 @@ class TextViewTableViewCell: UITableViewCell { super.setSelected(selected, animated: animated) } + override func getContent() -> String? { + return contentTextView.text + } + + override func setContent(content: String) { + contentTextView.text = content + } } diff --git a/pass/Views/TextViewTableViewCell.xib b/pass/Views/TextViewTableViewCell.xib index 1089f3c..dccde09 100644 --- a/pass/Views/TextViewTableViewCell.xib +++ b/pass/Views/TextViewTableViewCell.xib @@ -12,20 +12,19 @@ - - + + - + - + - + - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. @@ -40,7 +39,7 @@ - +