diff --git a/Cartfile b/Cartfile index f4c5aa1..5aaf479 100644 --- a/Cartfile +++ b/Cartfile @@ -1,3 +1,4 @@ github "SVProgressHUD/SVProgressHUD" github "radex/SwiftyUserDefaults" github "libgit2/objective-git" +github "zahlz/SwiftPasscodeLock" diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 75e0b00..89a46f0 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -10,6 +10,9 @@ 94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADCE7A5C3CCC67D7D21BB3C4 /* libPods-pass.a */; }; DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1208571E35EBE60042942E /* ObjectiveGit.framework */; }; 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 */; }; DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914981E434600007FF592 /* PasswordDetailTableViewController.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 = ""; }; DC1208571E35EBE60042942E /* ObjectiveGit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectiveGit.framework; path = Carthage/Build/iOS/ObjectiveGit.framework; sourceTree = ""; }; DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsTableViewController.swift; sourceTree = ""; }; + DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PasscodeLock.framework; path = Carthage/Build/iOS/PasscodeLock.framework; sourceTree = ""; }; + DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockRepository.swift; sourceTree = ""; }; + DC193FFF1E49E1A60077E0A3 /* PasscodeLockConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockConfiguration.swift; sourceTree = ""; }; DC4914941E434301007FF592 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = ""; }; DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordDetailTableViewController.swift; sourceTree = ""; }; DC4A746D1E30FBDE00E8EB18 /* Objective-CBridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Objective-CBridgingHeader.h"; sourceTree = ""; }; @@ -76,6 +82,7 @@ files = ( DC917BEF1E2F38C5000FDF54 /* Result.framework in Frameworks */, DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */, + DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */, DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */, DCA049961E3357E000522E8F /* SwiftyUserDefaults.framework in Frameworks */, 94BA784B85E071D25EE89B59 /* libPods-pass.a in Frameworks */, @@ -115,6 +122,8 @@ DC917BD51E2E8231000FDF54 /* pass */ = { isa = PBXGroup; children = ( + DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */, + DC193FFF1E49E1A60077E0A3 /* PasscodeLockConfiguration.swift */, DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */, DC4A746D1E30FBDE00E8EB18 /* Objective-CBridgingHeader.h */, DC917BE21E2E8231000FDF54 /* Info.plist */, @@ -145,6 +154,7 @@ DC917BED1E2F38C4000FDF54 /* Frameworks */ = { isa = PBXGroup; children = ( + DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */, DC1208571E35EBE60042942E /* ObjectiveGit.framework */, DCA049951E3357E000522E8F /* SwiftyUserDefaults.framework */, DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */, @@ -284,6 +294,7 @@ "$(SRCROOT)/Carthage/Build/iOS/SVProgressHUD.framework", "$(SRCROOT)/Carthage/Build/iOS/SwiftyUserDefaults.framework", "$(SRCROOT)/Carthage/Build/iOS/ObjectiveGit.framework", + "$(SRCROOT)/Carthage/Build/iOS/PasscodeLock.framework", ); outputPaths = ( ); @@ -311,7 +322,9 @@ DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */, DC5734AE1E439AD400D09270 /* PasswordsViewController.swift in Sources */, DC8963BE1E38AD8300828B09 /* GitRepositoryAuthenticationSettingTableViewController.swift in Sources */, + DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */, DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */, + DC193FFE1E49E0760077E0A3 /* PasscodeLockRepository.swift in Sources */, DCA049981E33586A00522E8F /* DefaultKeys.swift in Sources */, DCA0499E1E33BAC100522E8F /* Globals.swift in Sources */, ); diff --git a/pass/AppDelegate.swift b/pass/AppDelegate.swift index c18364f..d5ec4bd 100644 --- a/pass/AppDelegate.swift +++ b/pass/AppDelegate.swift @@ -8,6 +8,7 @@ import UIKit import CoreData +import PasscodeLock @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -23,6 +24,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { 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. // 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) { diff --git a/pass/DefaultKeys.swift b/pass/DefaultKeys.swift index f24ed37..ca33f2a 100644 --- a/pass/DefaultKeys.swift +++ b/pass/DefaultKeys.swift @@ -25,6 +25,6 @@ extension DefaultsKeys { static let gitRepositorySSHPrivateKeyPassphrase = DefaultsKey("gitRepositorySSHPrivateKeyPassphrase") static let lastUpdatedTime = DefaultsKey("lasteUpdatedTime") - static let isPasscodeOn = DefaultsKey("isPasscodeOn") static let isTouchIDOn = DefaultsKey("isTouchIDOn") + static let passcodeKey = DefaultsKey("passcodeKey") } diff --git a/pass/Globals.swift b/pass/Globals.swift index 36ee341..302fafc 100644 --- a/pass/Globals.swift +++ b/pass/Globals.swift @@ -14,5 +14,6 @@ class Globals { let secringPath = "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/secring.gpg" let sshPublicKeyPath = URL(fileURLWithPath: "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/ssh_key.pub") let sshPrivateKeyPath = URL(fileURLWithPath: "\(NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])/ssh_key") + var passcodeConfiguration = PasscodeLockConfiguration() private init() { } } diff --git a/pass/PasscodeLockConfiguration.swift b/pass/PasscodeLockConfiguration.swift new file mode 100644 index 0000000..99079d4 --- /dev/null +++ b/pass/PasscodeLockConfiguration.swift @@ -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() + } +} diff --git a/pass/PasscodeLockRepository.swift b/pass/PasscodeLockRepository.swift new file mode 100644 index 0000000..dd59c9e --- /dev/null +++ b/pass/PasscodeLockRepository.swift @@ -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") + } +} diff --git a/pass/SettingsTableViewController.swift b/pass/SettingsTableViewController.swift index 47722b5..46225fd 100644 --- a/pass/SettingsTableViewController.swift +++ b/pass/SettingsTableViewController.swift @@ -10,9 +10,11 @@ import UIKit import SVProgressHUD import CoreData import SwiftyUserDefaults +import PasscodeLock class SettingsTableViewController: UITableViewController { - + + let repository = PasscodeLockRepository() @IBOutlet weak var pgpKeyTableViewCell: UITableViewCell! @IBOutlet weak var touchIDTableViewCell: UITableViewCell! @IBOutlet weak var passcodeTableViewCell: UITableViewCell! @@ -108,13 +110,27 @@ class SettingsTableViewController: UITableViewController { super.viewDidLoad() let touchIDSwitch = UISwitch(frame: CGRect.zero) touchIDTableViewCell.accessoryView = touchIDSwitch - touchIDSwitch.isOn = false 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) { if tableView.cellForRow(at: indexPath) == passcodeTableViewCell { - showPasscodeActionSheet() + if Defaults[.passcodeKey] != nil{ + showPasscodeActionSheet() + } else { + setPasscodeLock() + } tableView.deselectRow(at: indexPath, animated: true) } } @@ -130,20 +146,40 @@ class SettingsTableViewController: UITableViewController { func touchIDSwitchAction(uiSwitch: UISwitch) { if uiSwitch.isOn { - print("UISwitch is ON") + Globals.shared.passcodeConfiguration.isTouchIDAllowed = true } else { - print("UISwitch is OFF") + Globals.shared.passcodeConfiguration.isTouchIDAllowed = false } } 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 removePasscodeAction = UIAlertAction(title: "Remove Passcode", style: .destructive, handler: nil) - let changePasscodeAction = UIAlertAction(title: "Change Passcode", style: .default, handler: nil) + let removePasscodeAction = UIAlertAction(title: "Remove Passcode", style: .destructive) { [unowned self] _ in + 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) optionMenu.addAction(removePasscodeAction) optionMenu.addAction(changePasscodeAction) optionMenu.addAction(cancelAction) 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) + } }