add passcode and touch ID

This commit is contained in:
Bob Sun 2017-02-07 20:24:58 +08:00
parent b022612e83
commit a31e9776fe
No known key found for this signature in database
GPG key ID: 1F86BA2052FED3B4
8 changed files with 133 additions and 8 deletions

View file

@ -1,3 +1,4 @@
github "SVProgressHUD/SVProgressHUD" github "SVProgressHUD/SVProgressHUD"
github "radex/SwiftyUserDefaults" github "radex/SwiftyUserDefaults"
github "libgit2/objective-git" github "libgit2/objective-git"
github "zahlz/SwiftPasscodeLock"

View file

@ -10,6 +10,9 @@
94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADCE7A5C3CCC67D7D21BB3C4 /* libPods-pass.a */; }; 94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADCE7A5C3CCC67D7D21BB3C4 /* libPods-pass.a */; };
DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1208571E35EBE60042942E /* ObjectiveGit.framework */; }; DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1208571E35EBE60042942E /* ObjectiveGit.framework */; };
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */; }; DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */; };
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */; };
DC193FFE1E49E0760077E0A3 /* PasscodeLockRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */; };
DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FFF1E49E1A60077E0A3 /* PasscodeLockConfiguration.swift */; };
DC4914961E434301007FF592 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914941E434301007FF592 /* LabelTableViewCell.swift */; }; DC4914961E434301007FF592 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914941E434301007FF592 /* LabelTableViewCell.swift */; };
DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */; }; DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */; };
DC5734AE1E439AD400D09270 /* PasswordsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */; }; DC5734AE1E439AD400D09270 /* PasswordsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */; };
@ -41,6 +44,9 @@
AEAD6B31EAF5D061447A68CC /* Pods-pass.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pass.release.xcconfig"; path = "Pods/Target Support Files/Pods-pass/Pods-pass.release.xcconfig"; sourceTree = "<group>"; }; AEAD6B31EAF5D061447A68CC /* Pods-pass.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pass.release.xcconfig"; path = "Pods/Target Support Files/Pods-pass/Pods-pass.release.xcconfig"; sourceTree = "<group>"; };
DC1208571E35EBE60042942E /* ObjectiveGit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectiveGit.framework; path = Carthage/Build/iOS/ObjectiveGit.framework; sourceTree = "<group>"; }; DC1208571E35EBE60042942E /* ObjectiveGit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectiveGit.framework; path = Carthage/Build/iOS/ObjectiveGit.framework; sourceTree = "<group>"; };
DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsTableViewController.swift; sourceTree = "<group>"; }; DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsTableViewController.swift; sourceTree = "<group>"; };
DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PasscodeLock.framework; path = Carthage/Build/iOS/PasscodeLock.framework; sourceTree = "<group>"; };
DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockRepository.swift; sourceTree = "<group>"; };
DC193FFF1E49E1A60077E0A3 /* PasscodeLockConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockConfiguration.swift; sourceTree = "<group>"; };
DC4914941E434301007FF592 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = "<group>"; }; DC4914941E434301007FF592 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = "<group>"; };
DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordDetailTableViewController.swift; sourceTree = "<group>"; }; DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordDetailTableViewController.swift; sourceTree = "<group>"; };
DC4A746D1E30FBDE00E8EB18 /* Objective-CBridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Objective-CBridgingHeader.h"; sourceTree = "<group>"; }; DC4A746D1E30FBDE00E8EB18 /* Objective-CBridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Objective-CBridgingHeader.h"; sourceTree = "<group>"; };
@ -76,6 +82,7 @@
files = ( files = (
DC917BEF1E2F38C5000FDF54 /* Result.framework in Frameworks */, DC917BEF1E2F38C5000FDF54 /* Result.framework in Frameworks */,
DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */, DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */,
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */,
DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */, DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */,
DCA049961E3357E000522E8F /* SwiftyUserDefaults.framework in Frameworks */, DCA049961E3357E000522E8F /* SwiftyUserDefaults.framework in Frameworks */,
94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */, 94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */,
@ -115,6 +122,8 @@
DC917BD51E2E8231000FDF54 /* pass */ = { DC917BD51E2E8231000FDF54 /* pass */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */,
DC193FFF1E49E1A60077E0A3 /* PasscodeLockConfiguration.swift */,
DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */, DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */,
DC4A746D1E30FBDE00E8EB18 /* Objective-CBridgingHeader.h */, DC4A746D1E30FBDE00E8EB18 /* Objective-CBridgingHeader.h */,
DC917BE21E2E8231000FDF54 /* Info.plist */, DC917BE21E2E8231000FDF54 /* Info.plist */,
@ -145,6 +154,7 @@
DC917BED1E2F38C4000FDF54 /* Frameworks */ = { DC917BED1E2F38C4000FDF54 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */,
DC1208571E35EBE60042942E /* ObjectiveGit.framework */, DC1208571E35EBE60042942E /* ObjectiveGit.framework */,
DCA049951E3357E000522E8F /* SwiftyUserDefaults.framework */, DCA049951E3357E000522E8F /* SwiftyUserDefaults.framework */,
DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */, DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */,
@ -284,6 +294,7 @@
"$(SRCROOT)/Carthage/Build/iOS/SVProgressHUD.framework", "$(SRCROOT)/Carthage/Build/iOS/SVProgressHUD.framework",
"$(SRCROOT)/Carthage/Build/iOS/SwiftyUserDefaults.framework", "$(SRCROOT)/Carthage/Build/iOS/SwiftyUserDefaults.framework",
"$(SRCROOT)/Carthage/Build/iOS/ObjectiveGit.framework", "$(SRCROOT)/Carthage/Build/iOS/ObjectiveGit.framework",
"$(SRCROOT)/Carthage/Build/iOS/PasscodeLock.framework",
); );
outputPaths = ( outputPaths = (
); );
@ -311,7 +322,9 @@
DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */, DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */,
DC5734AE1E439AD400D09270 /* PasswordsViewController.swift in Sources */, DC5734AE1E439AD400D09270 /* PasswordsViewController.swift in Sources */,
DC8963BE1E38AD8300828B09 /* GitRepositoryAuthenticationSettingTableViewController.swift in Sources */, DC8963BE1E38AD8300828B09 /* GitRepositoryAuthenticationSettingTableViewController.swift in Sources */,
DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */,
DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */, DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */,
DC193FFE1E49E0760077E0A3 /* PasscodeLockRepository.swift in Sources */,
DCA049981E33586A00522E8F /* DefaultKeys.swift in Sources */, DCA049981E33586A00522E8F /* DefaultKeys.swift in Sources */,
DCA0499E1E33BAC100522E8F /* Globals.swift in Sources */, DCA0499E1E33BAC100522E8F /* Globals.swift in Sources */,
); );

View file

@ -8,6 +8,7 @@
import UIKit import UIKit
import CoreData import CoreData
import PasscodeLock
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
@ -23,6 +24,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationWillResignActive(_ application: UIApplication) { func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
let passcodeEnterViewController = PasscodeLockViewController(state: .enter, configuration: Globals.shared.passcodeConfiguration)
UIApplication.shared.keyWindow?.rootViewController?.present(passcodeEnterViewController, animated: true, completion: nil)
} }
func applicationDidEnterBackground(_ application: UIApplication) { func applicationDidEnterBackground(_ application: UIApplication) {

View file

@ -25,6 +25,6 @@ extension DefaultsKeys {
static let gitRepositorySSHPrivateKeyPassphrase = DefaultsKey<String?>("gitRepositorySSHPrivateKeyPassphrase") static let gitRepositorySSHPrivateKeyPassphrase = DefaultsKey<String?>("gitRepositorySSHPrivateKeyPassphrase")
static let lastUpdatedTime = DefaultsKey<Date?>("lasteUpdatedTime") static let lastUpdatedTime = DefaultsKey<Date?>("lasteUpdatedTime")
static let isPasscodeOn = DefaultsKey<Bool>("isPasscodeOn")
static let isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn") static let isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn")
static let passcodeKey = DefaultsKey<String?>("passcodeKey")
} }

View file

@ -14,5 +14,6 @@ class Globals {
let secringPath = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/secring.gpg" let secringPath = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/secring.gpg"
let sshPublicKeyPath = URL(fileURLWithPath: "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/ssh_key.pub") let sshPublicKeyPath = URL(fileURLWithPath: "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/ssh_key.pub")
let sshPrivateKeyPath = URL(fileURLWithPath: "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/ssh_key") let sshPrivateKeyPath = URL(fileURLWithPath: "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/ssh_key")
var passcodeConfiguration = PasscodeLockConfiguration()
private init() { } private init() { }
} }

View file

@ -0,0 +1,29 @@
//
// PasscodeLockConfiguration.swift
// pass
//
// Created by Mingshen Sun on 7/2/2017.
// Copyright © 2017 Bob Sun. All rights reserved.
//
import Foundation
import PasscodeLock
struct PasscodeLockConfiguration: PasscodeLockConfigurationType {
let repository: PasscodeRepositoryType
let passcodeLength = 4
var isTouchIDAllowed = false
let shouldRequestTouchIDImmediately = true
let maximumInccorectPasscodeAttempts = 3
init(repository: PasscodeRepositoryType) {
self.repository = repository
}
init() {
self.repository = PasscodeLockRepository()
}
}

View file

@ -0,0 +1,42 @@
//
// PasscodeRepository.swift
// pass
//
// Created by Mingshen Sun on 7/2/2017.
// Copyright © 2017 Bob Sun. All rights reserved.
//
import Foundation
import PasscodeLock
import SwiftyUserDefaults
public class PasscodeLockRepository: PasscodeRepositoryType {
private let passcodeKey = "passcode.lock.passcode"
public var hasPasscode: Bool {
if passcode != nil {
return true
}
return false
}
private var passcode: String? {
return Defaults[.passcodeKey]
}
public func save(passcode: String) {
Defaults[.passcodeKey] = passcode
print(passcode)
}
public func check(passcode: String) -> Bool {
return self.passcode == passcode
}
public func delete() {
Defaults[.passcodeKey] = nil
print("delete")
}
}

View file

@ -10,9 +10,11 @@ import UIKit
import SVProgressHUD import SVProgressHUD
import CoreData import CoreData
import SwiftyUserDefaults import SwiftyUserDefaults
import PasscodeLock
class SettingsTableViewController: UITableViewController { class SettingsTableViewController: UITableViewController {
let repository = PasscodeLockRepository()
@IBOutlet weak var pgpKeyTableViewCell: UITableViewCell! @IBOutlet weak var pgpKeyTableViewCell: UITableViewCell!
@IBOutlet weak var touchIDTableViewCell: UITableViewCell! @IBOutlet weak var touchIDTableViewCell: UITableViewCell!
@IBOutlet weak var passcodeTableViewCell: UITableViewCell! @IBOutlet weak var passcodeTableViewCell: UITableViewCell!
@ -108,13 +110,27 @@ class SettingsTableViewController: UITableViewController {
super.viewDidLoad() super.viewDidLoad()
let touchIDSwitch = UISwitch(frame: CGRect.zero) let touchIDSwitch = UISwitch(frame: CGRect.zero)
touchIDTableViewCell.accessoryView = touchIDSwitch touchIDTableViewCell.accessoryView = touchIDSwitch
touchIDSwitch.isOn = false
touchIDSwitch.addTarget(self, action: #selector(touchIDSwitchAction), for: UIControlEvents.valueChanged) touchIDSwitch.addTarget(self, action: #selector(touchIDSwitchAction), for: UIControlEvents.valueChanged)
if Defaults[.isTouchIDOn] {
touchIDSwitch.isOn = true
} else {
touchIDSwitch.isOn = false
}
if repository.hasPasscode {
self.passcodeTableViewCell.detailTextLabel?.text = "On"
print(Defaults[.passcodeKey]!)
} else {
self.passcodeTableViewCell.detailTextLabel?.text = "Off"
}
} }
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath) == passcodeTableViewCell { if tableView.cellForRow(at: indexPath) == passcodeTableViewCell {
if Defaults[.passcodeKey] != nil{
showPasscodeActionSheet() showPasscodeActionSheet()
} else {
setPasscodeLock()
}
tableView.deselectRow(at: indexPath, animated: true) tableView.deselectRow(at: indexPath, animated: true)
} }
} }
@ -130,20 +146,40 @@ class SettingsTableViewController: UITableViewController {
func touchIDSwitchAction(uiSwitch: UISwitch) { func touchIDSwitchAction(uiSwitch: UISwitch) {
if uiSwitch.isOn { if uiSwitch.isOn {
print("UISwitch is ON") Globals.shared.passcodeConfiguration.isTouchIDAllowed = true
} else { } else {
print("UISwitch is OFF") Globals.shared.passcodeConfiguration.isTouchIDAllowed = false
} }
} }
func showPasscodeActionSheet() { func showPasscodeActionSheet() {
let passcodeChangeViewController = PasscodeLockViewController(state: .change, configuration: Globals.shared.passcodeConfiguration)
let passcodeRemoveViewController = PasscodeLockViewController(state: .remove, configuration: Globals.shared.passcodeConfiguration)
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let removePasscodeAction = UIAlertAction(title: "Remove Passcode", style: .destructive, handler: nil) let removePasscodeAction = UIAlertAction(title: "Remove Passcode", style: .destructive) { [unowned self] _ in
let changePasscodeAction = UIAlertAction(title: "Change Passcode", style: .default, handler: nil) passcodeRemoveViewController.successCallback = { _ in
self.passcodeTableViewCell.detailTextLabel?.text = "Off"
}
self.present(passcodeRemoveViewController, animated: true, completion: nil)
}
let changePasscodeAction = UIAlertAction(title: "Change Passcode", style: .default) { [unowned self] _ in
self.present(passcodeChangeViewController, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
optionMenu.addAction(removePasscodeAction) optionMenu.addAction(removePasscodeAction)
optionMenu.addAction(changePasscodeAction) optionMenu.addAction(changePasscodeAction)
optionMenu.addAction(cancelAction) optionMenu.addAction(cancelAction)
self.present(optionMenu, animated: true, completion: nil) self.present(optionMenu, animated: true, completion: nil)
} }
func setPasscodeLock() {
let passcodeSetViewController = PasscodeLockViewController(state: .set, configuration: Globals.shared.passcodeConfiguration)
passcodeSetViewController.successCallback = { _ in
self.passcodeTableViewCell.detailTextLabel?.text = "On"
}
present(passcodeSetViewController, animated: true, completion: nil)
}
} }