Skip to content

Commit

Permalink
- Fixes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
glushchenko committed May 7, 2023
1 parent a801a99 commit ef82804
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 46 deletions.
108 changes: 87 additions & 21 deletions FSNotes iOS/Settings/GitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class GitViewController: UITableViewController {
changePrivateKey(tableView: tableView, indexPath: indexPath)
}

if indexPath.section == GitSection.credentials.rawValue && indexPath.row == 1 {
changePublicKey(tableView: tableView, indexPath: indexPath)
}

tableView.deselectRow(at: indexPath, animated: false)
}

Expand Down Expand Up @@ -125,7 +129,7 @@ class GitViewController: UITableViewController {
}

// Passphrase and origin textfields
if indexPath.section == GitSection.credentials.rawValue && indexPath.row == 1 || (
if indexPath.section == GitSection.credentials.rawValue && indexPath.row == 2 || (
indexPath.section == GitSection.origin.rawValue && indexPath.row == 0 ||
indexPath.section == GitSection.logs.rawValue && indexPath.row == 0
) {
Expand All @@ -135,7 +139,7 @@ class GitViewController: UITableViewController {
textField.mixedTextColor = MixedColor(normal: 0x000000, night: 0xffffff)

// Passphrase
if indexPath.section == GitSection.credentials.rawValue && indexPath.row == 1 {
if indexPath.section == GitSection.credentials.rawValue && indexPath.row == 2 {
cell.textLabel?.text = NSLocalizedString("Passphrase", comment: "")
textField.isSecureTextEntry = true
textField.addTarget(self, action: #selector(passphraseDidChange), for: .editingChanged)
Expand Down Expand Up @@ -214,6 +218,28 @@ class GitViewController: UITableViewController {
cell.accessoryView = accessoryButton
}
}

// Public key
if indexPath.section == GitSection.credentials.rawValue && indexPath.row == 1 {
cell.textLabel?.text = NSLocalizedString("Public key (optional)", comment: "")
cell.detailTextLabel?.text = NSLocalizedString("...", comment: "")

if project.settings.gitPublicKey != nil {
cell.detailTextLabel?.text = NSLocalizedString("✅ - ", comment: "")

let accessoryButton = UIButton(type: .custom)
accessoryButton.addTarget(self, action: #selector(deletePublicKey(sender:)), for: .touchUpInside)

let light = UIImage(named: "trash")!
let night = UIImage(named: "trash")!.withTintColor(.white)
let mixedImage = MixedImage(normal: light, night: night)
accessoryButton.setMixedImage(mixedImage, forState: .normal)

accessoryButton.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
accessoryButton.contentMode = .scaleAspectFit
cell.accessoryView = accessoryButton
}
}

return cell
}
Expand All @@ -227,7 +253,11 @@ class GitViewController: UITableViewController {
return 1
}

if section == 1 || section == 2 {
if section == 1 {
return 3
}

if section == 2 {
return 2
}

Expand All @@ -239,31 +269,67 @@ class GitViewController: UITableViewController {
cell.textLabel?.mixedTextColor = MixedColor(normal: 0x000000, night: 0xffffff)
}

private func changePrivateKey(tableView: UITableView, indexPath: IndexPath) {
private lazy var documentPickerPrivateKey: UIDocumentPickerViewController = {
let types: [String] = ["public.data"]
let documentPicker = UIDocumentPickerViewController(documentTypes: types, in: .import)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = false
documentPicker.modalPresentationStyle = .formSheet
self.present(documentPicker, animated: true, completion: nil)
return documentPicker
}()

private lazy var documentPickerPublicKey: UIDocumentPickerViewController = {
let types: [String] = ["public.data"]
let documentPicker = UIDocumentPickerViewController(documentTypes: types, in: .import)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = false
documentPicker.modalPresentationStyle = .formSheet
return documentPicker
}()

private func changePrivateKey(tableView: UITableView, indexPath: IndexPath) {
present(documentPickerPrivateKey, animated: true, completion: nil)
}

private func changePublicKey(tableView: UITableView, indexPath: IndexPath) {
present(documentPickerPublicKey, animated: true, completion: nil)
}

@objc func deletePrivateKey(sender: UIButton) {
guard let project = project else { return }

project.settings.gitPrivateKey = nil
project.saveSettings()

if let rsaURL = GitViewController.getRsaUrl() {
try? FileManager.default.removeItem(at: rsaURL)

if let privateUrl = project.getSSHKeyUrl(),
FileManager.default.fileExists(atPath: privateUrl.path) {
try? FileManager.default.removeItem(at: privateUrl)
}

guard let cell = sender.superview as? UITableViewCell,
let tableView = cell.superview as? UITableView,
let indexPath = tableView.indexPath(for: cell) else { return }

tableView.reloadRows(at: [indexPath], with: .none)
}

@objc func deletePublicKey(sender: UIButton) {
guard let project = project else { return }

project.settings.gitPublicKey = nil
project.saveSettings()

if let pubUrl = project.getSSHKeyUrl()?.appendingPathExtension("pub"),
FileManager.default.fileExists(atPath: pubUrl.path) {
try? FileManager.default.removeItem(at: pubUrl)
}

guard let cell = sender.superview as? UITableViewCell,
let tableView = cell.superview as? UITableView,
let indexPath = tableView.indexPath(for: cell) else { return }

tableView.reloadRows(at: [indexPath], with: .none)
}

@objc func passphraseDidChange(sender: UITextField) {
guard let text = sender.text else { return }
Expand Down Expand Up @@ -314,7 +380,8 @@ class GitViewController: UITableViewController {
DispatchQueue.main.async {
self.errorAlert(title: "git error", message: message)

if action == .pullPush {
// Refresh local files
if action == .pullPush && !UserDefaultsManagement.iCloudDrive {
UIApplication.getVC().checkNew()
}
}
Expand All @@ -332,15 +399,7 @@ class GitViewController: UITableViewController {
self.present(alertController, animated: true, completion: nil)
}
}

public static func getRsaUrl() -> URL? {
let documentDir = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first
if let rsaKey = documentDir?.appendingPathComponent("id_rsa", isDirectory: false) {
return rsaKey
}
return nil
}


public func updateButtons(isActive: Bool? = nil) {
guard let project = project else { return }

Expand Down Expand Up @@ -375,8 +434,15 @@ extension GitViewController: UIDocumentPickerDelegate, UINavigationControllerDel
guard let url = urls.first else { return }
guard let data = try? Data(contentsOf: url) else { return }
guard let project = project else { return }

project.settings.gitPrivateKey = data

if controller == documentPickerPrivateKey {
project.settings.gitPrivateKey = data
}

if controller == documentPickerPublicKey {
project.settings.gitPublicKey = data
}

project.saveSettings()

tableView.reloadData()
Expand Down
2 changes: 1 addition & 1 deletion FSNotes iOS/Settings/SecurityViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class SecurityViewController: UITableViewController {
let item = KeychainPasswordItem(service: KeychainConfiguration.serviceName, account: "Master Password")
let oldPassword = try? item.readPassword()

if text.count > 0, text == verifyPasswordTextField.text, text != oldPassword {
if text.count > 0, text == verifyPasswordTextField.text {
do {
try item.savePassword(text)
} catch {
Expand Down
5 changes: 4 additions & 1 deletion FSNotes iOS/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,10 @@ class ViewController: UIViewController, UISearchBarDelegate, UIGestureRecognizer

viewController.gitQueue.addOperation({
Storage.shared().pullAll(force: force)
self.checkNew()

if !UserDefaultsManagement.iCloudDrive {
self.checkNew()
}

// if viewController.gitQueueState.operationCount == 0 {
// viewController.gitQueueState.addOperation {
Expand Down
8 changes: 4 additions & 4 deletions FSNotes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -5077,7 +5077,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 253;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 866P6MTE92;
INFOPLIST_FILE = "FSNotes iOS Share/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
Expand Down Expand Up @@ -5106,7 +5106,7 @@
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 253;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 866P6MTE92;
ENABLE_NS_ASSERTIONS = NO;
INFOPLIST_FILE = "FSNotes iOS Share/Info.plist";
Expand Down Expand Up @@ -5140,7 +5140,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 253;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 866P6MTE92;
INFOPLIST_FILE = "FSNotes iOS/Info.plist";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity";
Expand Down Expand Up @@ -5175,7 +5175,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 253;
CURRENT_PROJECT_VERSION = 254;
DEVELOPMENT_TEAM = 866P6MTE92;
ENABLE_NS_ASSERTIONS = NO;
INFOPLIST_FILE = "FSNotes iOS/Info.plist";
Expand Down
9 changes: 9 additions & 0 deletions FSNotes/Business/ProjectSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class ProjectSettings: NSObject, NSSecureCoding {
public var gitAutoPull: Bool = false
public var gitOrigin: String?
public var gitPrivateKey: Data?
public var gitPublicKey: Data?
public var gitPrivateKeyPassphrase: String?

public override init() {/*_*/}
Expand Down Expand Up @@ -53,6 +54,10 @@ public class ProjectSettings: NSObject, NSSecureCoding {
gitPrivateKey = value
}

if let value = aDecoder.decodeObject(of: NSData.self, forKey: "gitPublicKey") as? Data {
gitPublicKey = value
}

if let value = aDecoder.decodeObject(of: NSString.self, forKey: "gitPrivateKeyPassphrase") as? String {
gitPrivateKeyPassphrase = value
}
Expand All @@ -79,6 +84,10 @@ public class ProjectSettings: NSObject, NSSecureCoding {
if let gitPrivateKey = gitPrivateKey {
aCoder.encode(gitPrivateKey, forKey: "gitPrivateKey")
}

if let gitPublicKey = gitPublicKey {
aCoder.encode(gitPublicKey, forKey: "gitPublicKey")
}

if let gitPrivateKeyPassphrase = gitPrivateKeyPassphrase {
aCoder.encode(gitPrivateKeyPassphrase, forKey: "gitPrivateKeyPassphrase")
Expand Down
12 changes: 10 additions & 2 deletions FSNotes/Git/authentication/KeyAuthentication.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,22 @@ public protocol SshKeyData {
var passphrase : String? {
get
}

var publicKey : URL? {
get
}
}

public struct RawSshKeyData : SshKeyData {
public let username : String?
public let privateKey : URL
public let publicKey : URL?
public let passphrase : String?

public init(username : String?, privateKey : URL, passphrase : String? = nil) {
public init(username : String?, privateKey : URL, publicKey: URL? = nil, passphrase : String? = nil) {
self.username = username
self.privateKey = privateKey
self.publicKey = publicKey
self.passphrase = passphrase
}
}
Expand Down Expand Up @@ -85,10 +91,12 @@ public class SshKeyHandler : AuthenticationHandler {
// User name
let optionalUsername = sshKeyData.username
let optionalPassPhrase = sshKeyData.passphrase

let publicKey = sshKeyData.publicKey != nil ? sshKeyData.publicKey!.path : nil

return git_cred_ssh_key_new(out,
optionalUsername == nil ? "" : optionalUsername!,
nil,
publicKey,
privateKey,
optionalPassPhrase == nil ? "" : optionalPassPhrase!)
}
Expand Down
10 changes: 8 additions & 2 deletions FSNotes/Git/commons/StaticSshKeyDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ import Foundation

class StaticSshKeyDelegate : SshKeyDelegate {
let privateUrl: URL
let publicUrl: URL?
let passphrase: String

init(privateUrl: URL, passphrase: String) {
init(privateUrl: URL, passphrase: String, publicUrl: URL? = nil) {
self.privateUrl = privateUrl
self.publicUrl = publicUrl
self.passphrase = passphrase
}

public func get(username: String?, url: URL?) -> SshKeyData {
return RawSshKeyData(username: username, privateKey: privateUrl, passphrase: passphrase)
if let publicUrl = self.publicUrl {
return RawSshKeyData(username: username, privateKey: privateUrl, publicKey: publicUrl, passphrase: passphrase)
}

return RawSshKeyData(username: username, privateKey: privateUrl, publicKey: nil, passphrase: passphrase)
}
}
22 changes: 7 additions & 15 deletions FSNotesCore/Shared/Extensions/Project+Git.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,32 +162,25 @@ extension Project {
.appendingPathComponent(keyName)
}

public func isSSHKeyExist() -> Bool {
guard let sshKey = getSSHKeyUrl() else { return false }

if FileManager.default.fileExists(atPath: sshKey.path) {
return false
}

return true
}

public func removeSSHKey() {
guard let url = getSSHKeyUrl() else { return }

try? FileManager.default.removeItem(at: url)
try? FileManager.default.removeItem(at: url.appendingPathExtension("pub"))
}

public func installSSHKey() -> URL? {
guard let url = getSSHKeyUrl() else { return nil }

if FileManager.default.fileExists(atPath: url.path) {
return url
}

if let key = settings.gitPrivateKey {
do {
try key.write(to: url)

if let publicKey = settings.gitPublicKey {
let publicKeyUrl = url.appendingPathExtension("pub")
try publicKey.write(to: publicKeyUrl)
}

return url
} catch {/*_*/}
}
Expand All @@ -201,7 +194,6 @@ extension Project {

public func commit(message: String? = nil, progress: GitProgress? = nil) throws {
let repository = try getRepository()
let statuses = Statuses(repository: repository)
let lastCommit = try? repository.head().targetCommit()

// Add all and save index
Expand Down
4 changes: 4 additions & 0 deletions FSNotesCore/Shared/Note+History.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ extension Note {

let relative = url.path.replacingOccurrences(of: project.url.path, with: "")

if !UserDefaultsManagement.iCloudDrive && relative.startsWith(string: "/private/") {
return relative.replacingOccurrences(of: "/private/", with: "")
}

if relative.first == "/" {
return String(relative.dropFirst())
}
Expand Down

0 comments on commit ef82804

Please sign in to comment.