2017-01-19 21:15:47 +08:00
//
// S e t t i n g s T a b l e V i e w C o n t r o l l e r . s w i f t
// p a s s
//
// C r e a t e d b y M i n g s h e n S u n o n 1 8 / 1 / 2 0 1 7 .
// C o p y r i g h t © 2 0 1 7 B o b S u n . A l l r i g h t s r e s e r v e d .
//
import UIKit
import SVProgressHUD
import CoreData
2017-06-13 11:42:49 +08:00
import passKit
2017-01-19 21:15:47 +08:00
2018-01-16 20:26:41 -08:00
class SettingsTableViewController : UITableViewController , UITabBarControllerDelegate {
2017-01-22 01:42:36 +08:00
@IBOutlet weak var pgpKeyTableViewCell : UITableViewCell !
2017-02-07 17:56:31 +08:00
@IBOutlet weak var passcodeTableViewCell : UITableViewCell !
2017-02-21 13:07:14 +08:00
@IBOutlet weak var passwordRepositoryTableViewCell : UITableViewCell !
2018-01-29 03:23:34 +08:00
var setPasscodeLockAlert : UIAlertController ?
2018-12-09 16:59:07 -08:00
2017-03-16 22:39:03 -07:00
let passwordStore = PasswordStore . shared
2018-01-29 03:23:34 +08:00
var passcodeLock = PasscodeLock . shared
2018-12-09 16:59:07 -08:00
2018-01-16 20:26:41 -08:00
func tabBarController ( _ tabBarController : UITabBarController , didSelect viewController : UIViewController ) {
navigationController ? . popViewController ( animated : true )
}
2018-12-09 16:59:07 -08:00
2017-02-17 13:44:25 +08:00
@IBAction func savePGPKey ( segue : UIStoryboardSegue ) {
2017-02-09 21:45:31 +08:00
if let controller = segue . source as ? PGPKeySettingTableViewController {
2018-11-13 23:54:53 +01:00
SharedDefaults [ . pgpPrivateKeyURL ] = URL ( string : controller . pgpPrivateKeyURLTextField . text ! . trimmed )
SharedDefaults [ . pgpPublicKeyURL ] = URL ( string : controller . pgpPublicKeyURLTextField . text ! . trimmed )
2017-10-08 21:37:58 +08:00
if SharedDefaults [ . isRememberPGPPassphraseOn ] {
2017-04-25 20:13:59 -07:00
self . passwordStore . pgpKeyPassphrase = controller . pgpPassphrase
}
2017-06-13 11:42:49 +08:00
SharedDefaults [ . pgpKeySource ] = " url "
2018-12-09 16:59:07 -08:00
2017-02-17 14:58:27 +08:00
SVProgressHUD . setDefaultMaskType ( . black )
SVProgressHUD . setDefaultStyle ( . light )
SVProgressHUD . show ( withStatus : " Fetching PGP Key " )
DispatchQueue . global ( qos : . userInitiated ) . async { [ unowned self ] in
do {
2017-06-13 11:42:49 +08:00
try self . passwordStore . initPGPKey ( from : SharedDefaults [ . pgpPublicKeyURL ] ! , keyType : . public )
try self . passwordStore . initPGPKey ( from : SharedDefaults [ . pgpPrivateKeyURL ] ! , keyType : . secret )
2017-02-17 14:58:27 +08:00
DispatchQueue . main . async {
2017-03-16 22:39:03 -07:00
self . pgpKeyTableViewCell . detailTextLabel ? . text = self . passwordStore . pgpKeyID
2017-02-20 22:02:49 +08:00
SVProgressHUD . showSuccess ( withStatus : " Success " )
2017-02-17 14:58:27 +08:00
SVProgressHUD . dismiss ( withDelay : 1 )
2017-04-23 10:23:54 -07:00
Utils . alert ( title : " Remember to Remove the Key " , message : " Remember to remove the key from the server. " , controller : self , completion : nil )
2017-02-17 14:58:27 +08:00
}
} catch {
DispatchQueue . main . async {
self . pgpKeyTableViewCell . detailTextLabel ? . text = " Not Set "
2017-03-16 23:12:31 -07:00
Utils . alert ( title : " Error " , message : error . localizedDescription , controller : self , completion : nil )
2017-01-22 01:42:36 +08:00
}
}
2017-02-17 14:58:27 +08:00
}
2018-12-09 16:59:07 -08:00
2017-02-17 13:44:25 +08:00
} else if let controller = segue . source as ? PGPKeyArmorSettingTableViewController {
2017-06-13 11:42:49 +08:00
SharedDefaults [ . pgpKeySource ] = " armor "
2017-10-08 21:37:58 +08:00
if SharedDefaults [ . isRememberPGPPassphraseOn ] {
2017-04-25 20:13:59 -07:00
self . passwordStore . pgpKeyPassphrase = controller . pgpPassphrase
2017-02-28 12:25:52 +08:00
}
2017-02-19 22:10:36 +08:00
2017-06-13 11:42:49 +08:00
SharedDefaults [ . pgpPublicKeyArmor ] = controller . armorPublicKeyTextView . text !
SharedDefaults [ . pgpPrivateKeyArmor ] = controller . armorPrivateKeyTextView . text !
2018-12-09 16:59:07 -08:00
2017-02-17 13:44:25 +08:00
SVProgressHUD . setDefaultMaskType ( . black )
SVProgressHUD . setDefaultStyle ( . light )
SVProgressHUD . show ( withStatus : " Fetching PGP Key " )
DispatchQueue . global ( qos : . userInitiated ) . async { [ unowned self ] in
do {
2018-04-12 00:06:49 +08:00
try self . passwordStore . initPGPKey ( with : SharedDefaults [ . pgpPublicKeyArmor ] ? ? " " , keyType : . public )
try self . passwordStore . initPGPKey ( with : SharedDefaults [ . pgpPrivateKeyArmor ] ? ? " " , keyType : . secret )
2017-02-17 13:44:25 +08:00
DispatchQueue . main . async {
2017-03-16 22:39:03 -07:00
self . pgpKeyTableViewCell . detailTextLabel ? . text = self . passwordStore . pgpKeyID
2017-02-20 22:02:49 +08:00
SVProgressHUD . showSuccess ( withStatus : " Success " )
2017-02-17 13:44:25 +08:00
SVProgressHUD . dismiss ( withDelay : 1 )
}
} catch {
DispatchQueue . main . async {
self . pgpKeyTableViewCell . detailTextLabel ? . text = " Not Set "
2017-03-16 23:12:31 -07:00
Utils . alert ( title : " Error " , message : error . localizedDescription , controller : self , completion : nil )
2017-02-17 13:44:25 +08:00
}
}
}
2017-01-19 21:15:47 +08:00
}
}
2018-12-09 16:59:07 -08:00
2017-06-07 21:11:01 +08:00
private func saveImportedPGPKey ( ) {
// l o a d k e y s
2017-06-13 11:42:49 +08:00
SharedDefaults [ . pgpKeySource ] = " file "
2017-06-07 21:11:01 +08:00
SVProgressHUD . setDefaultMaskType ( . black )
SVProgressHUD . setDefaultStyle ( . light )
SVProgressHUD . show ( withStatus : " Fetching PGP Key " )
DispatchQueue . global ( qos : . userInitiated ) . async { [ unowned self ] in
do {
2018-11-17 21:41:28 -08:00
try self . passwordStore . pgpKeyImportFromFileSharing ( )
2017-06-07 21:11:01 +08:00
try self . passwordStore . initPGPKeys ( )
DispatchQueue . main . async {
self . pgpKeyTableViewCell . detailTextLabel ? . text = self . passwordStore . pgpKeyID
2017-06-14 20:22:15 +08:00
SVProgressHUD . showSuccess ( withStatus : " Imported " )
2017-06-07 21:11:01 +08:00
SVProgressHUD . dismiss ( withDelay : 1 )
}
} catch {
DispatchQueue . main . async {
self . pgpKeyTableViewCell . detailTextLabel ? . text = " Not Set "
Utils . alert ( title : " Error " , message : error . localizedDescription , controller : self , completion : nil )
}
}
}
}
2018-12-09 16:59:07 -08:00
2017-02-21 13:07:14 +08:00
@IBAction func saveGitServerSetting ( segue : UIStoryboardSegue ) {
2017-06-13 11:42:49 +08:00
self . passwordRepositoryTableViewCell . detailTextLabel ? . text = SharedDefaults [ . gitURL ] ? . host
2017-02-21 13:07:14 +08:00
}
2018-12-09 16:59:07 -08:00
2017-05-26 09:25:36 -07:00
override func tableView ( _ tableView : UITableView , numberOfRowsInSection section : Int ) -> Int {
return super . tableView ( tableView , numberOfRowsInSection : section )
}
2017-01-19 21:15:47 +08:00
override func viewDidLoad ( ) {
super . viewDidLoad ( )
2017-03-18 00:18:55 +08:00
NotificationCenter . default . addObserver ( self , selector : #selector ( SettingsTableViewController . actOnPasswordStoreErasedNotification ) , name : . passwordStoreErased , object : nil )
2017-06-13 11:42:49 +08:00
self . passwordRepositoryTableViewCell . detailTextLabel ? . text = SharedDefaults [ . gitURL ] ? . host
2017-02-26 20:59:27 +08:00
setPGPKeyTableViewCellDetailText ( )
setPasswordRepositoryTableViewCellDetailText ( )
2018-01-29 03:23:34 +08:00
setPasscodeLockCell ( )
2017-02-26 20:59:27 +08:00
}
2018-12-09 16:59:07 -08:00
2018-01-16 21:54:00 -08:00
override func viewWillAppear ( _ animated : Bool ) {
super . viewWillAppear ( true )
tabBarController ! . delegate = self
}
2018-12-09 16:59:07 -08:00
2018-01-29 03:23:34 +08:00
private func setPasscodeLockCell ( ) {
if passcodeLock . hasPasscode {
2017-02-26 20:59:27 +08:00
self . passcodeTableViewCell . detailTextLabel ? . text = " On "
} else {
self . passcodeTableViewCell . detailTextLabel ? . text = " Off "
}
}
2018-12-09 16:59:07 -08:00
2017-02-26 20:59:27 +08:00
private func setPGPKeyTableViewCellDetailText ( ) {
2017-03-16 22:39:03 -07:00
if let pgpKeyID = self . passwordStore . pgpKeyID {
2017-03-16 22:06:39 -07:00
pgpKeyTableViewCell . detailTextLabel ? . text = pgpKeyID
2017-02-09 11:31:49 +08:00
} else {
2017-03-16 22:06:39 -07:00
pgpKeyTableViewCell . detailTextLabel ? . text = " Not Set "
2017-02-09 11:31:49 +08:00
}
2017-02-26 20:59:27 +08:00
}
2018-12-09 16:59:07 -08:00
2017-02-26 20:59:27 +08:00
private func setPasswordRepositoryTableViewCellDetailText ( ) {
2017-06-13 11:42:49 +08:00
if SharedDefaults [ . gitURL ] = = nil {
2017-02-26 20:59:27 +08:00
passwordRepositoryTableViewCell . detailTextLabel ? . text = " Not Set "
} else {
2017-06-13 11:42:49 +08:00
passwordRepositoryTableViewCell . detailTextLabel ? . text = SharedDefaults [ . gitURL ] ! . host
2017-02-26 20:59:27 +08:00
}
}
2018-12-09 16:59:07 -08:00
2017-09-23 16:29:03 +08:00
@objc func actOnPasswordStoreErasedNotification ( ) {
2017-02-26 20:59:27 +08:00
setPGPKeyTableViewCellDetailText ( )
setPasswordRepositoryTableViewCellDetailText ( )
2018-01-29 03:23:34 +08:00
setPasscodeLockCell ( )
2017-02-09 11:31:49 +08:00
}
2018-12-09 16:59:07 -08:00
2017-02-07 17:56:31 +08:00
override func tableView ( _ tableView : UITableView , didSelectRowAt indexPath : IndexPath ) {
if tableView . cellForRow ( at : indexPath ) = = passcodeTableViewCell {
2017-06-13 11:42:49 +08:00
if SharedDefaults [ . passcodeKey ] != nil {
2017-02-07 20:24:58 +08:00
showPasscodeActionSheet ( )
} else {
setPasscodeLock ( )
}
2017-02-17 13:44:25 +08:00
} else if tableView . cellForRow ( at : indexPath ) = = pgpKeyTableViewCell {
showPGPKeyActionSheet ( )
2017-02-07 17:56:31 +08:00
}
2017-02-17 13:44:25 +08:00
tableView . deselectRow ( at : indexPath , animated : true )
2017-02-07 16:45:14 +08:00
}
2018-12-09 16:59:07 -08:00
2017-02-17 13:44:25 +08:00
func showPGPKeyActionSheet ( ) {
let optionMenu = UIAlertController ( title : nil , message : nil , preferredStyle : . actionSheet )
var urlActionTitle = " Download from URL "
var armorActionTitle = " ASCII-Armor Encrypted Key "
2017-06-14 20:22:15 +08:00
var fileActionTitle = " iTunes File Sharing "
2018-12-09 16:59:07 -08:00
2017-06-13 11:42:49 +08:00
if SharedDefaults [ . pgpKeySource ] = = " url " {
2017-02-17 13:44:25 +08:00
urlActionTitle = " ✓ \( urlActionTitle ) "
2017-06-13 11:42:49 +08:00
} else if SharedDefaults [ . pgpKeySource ] = = " armor " {
2017-02-17 13:44:25 +08:00
armorActionTitle = " ✓ \( armorActionTitle ) "
2017-06-13 11:42:49 +08:00
} else if SharedDefaults [ . pgpKeySource ] = = " file " {
2017-02-24 17:59:04 +03:00
fileActionTitle = " ✓ \( fileActionTitle ) "
2017-02-17 13:44:25 +08:00
}
let urlAction = UIAlertAction ( title : urlActionTitle , style : . default ) { _ in
self . performSegue ( withIdentifier : " setPGPKeyByURLSegue " , sender : self )
}
let armorAction = UIAlertAction ( title : armorActionTitle , style : . default ) { _ in
self . performSegue ( withIdentifier : " setPGPKeyByASCIISegue " , sender : self )
}
let cancelAction = UIAlertAction ( title : " Cancel " , style : . cancel , handler : nil )
optionMenu . addAction ( urlAction )
optionMenu . addAction ( armorAction )
2017-02-24 17:59:04 +03:00
2017-06-14 20:22:15 +08:00
if passwordStore . pgpKeyExists ( inFileSharing : true ) {
fileActionTitle . append ( " (Import) " )
2017-02-24 17:59:04 +03:00
let fileAction = UIAlertAction ( title : fileActionTitle , style : . default ) { _ in
2017-06-07 21:11:01 +08:00
// p a s s p h r a s e r e l a t e d
let savePassphraseAlert = UIAlertController ( title : " Passphrase " , message : " Do you want to save the passphrase for later decryption? " , preferredStyle : UIAlertControllerStyle . alert )
// n o
savePassphraseAlert . addAction ( UIAlertAction ( title : " No " , style : UIAlertActionStyle . default ) { _ in
self . passwordStore . pgpKeyPassphrase = nil
2017-10-08 21:37:58 +08:00
SharedDefaults [ . isRememberPGPPassphraseOn ] = false
2017-06-07 21:11:01 +08:00
self . saveImportedPGPKey ( )
} )
// y e s
savePassphraseAlert . addAction ( UIAlertAction ( title : " Yes " , style : UIAlertActionStyle . destructive ) { _ in
// a s k f o r t h e p a s s p h r a s e
let alert = UIAlertController ( title : " Passphrase " , message : " Please fill in the passphrase of your PGP secret key. " , preferredStyle : UIAlertControllerStyle . alert )
alert . addAction ( UIAlertAction ( title : " OK " , style : UIAlertActionStyle . default , handler : { _ in
self . passwordStore . pgpKeyPassphrase = alert . textFields ? . first ? . text
2017-10-08 21:37:58 +08:00
SharedDefaults [ . isRememberPGPPassphraseOn ] = true
2017-06-07 21:11:01 +08:00
self . saveImportedPGPKey ( )
} ) )
alert . addTextField ( configurationHandler : { ( textField : UITextField ! ) in
textField . text = " "
textField . isSecureTextEntry = true
} )
self . present ( alert , animated : true , completion : nil )
} )
self . present ( savePassphraseAlert , animated : true , completion : nil )
2017-02-24 17:59:04 +03:00
}
2017-06-07 16:54:54 +08:00
optionMenu . addAction ( fileAction )
} else {
2017-06-14 20:22:15 +08:00
fileActionTitle . append ( " (Tips) " )
let fileAction = UIAlertAction ( title : fileActionTitle , style : . default ) { _ in
let title = " Tips "
2018-09-30 23:11:48 +08:00
let message = " Copy your ASCII-armored public and private keys to Pass with names \" gpg_key.pub \" and \" gpg_key \" (without quotes) via iTunes. Then come back and click \" iTunes File Sharing \" to finish. "
2017-06-07 16:54:54 +08:00
Utils . alert ( title : title , message : message , controller : self )
}
2017-02-24 17:59:04 +03:00
optionMenu . addAction ( fileAction )
}
2018-12-09 16:59:07 -08:00
2017-06-13 11:42:49 +08:00
if SharedDefaults [ . pgpKeySource ] != nil {
2017-02-17 13:44:25 +08:00
let deleteAction = UIAlertAction ( title : " Remove PGP Keys " , style : . destructive ) { _ in
2017-06-03 18:12:33 -07:00
self . passwordStore . removePGPKeys ( )
2017-02-17 13:44:25 +08:00
self . pgpKeyTableViewCell . detailTextLabel ? . text = " Not Set "
}
optionMenu . addAction ( deleteAction )
}
optionMenu . addAction ( cancelAction )
2017-02-22 18:18:59 +08:00
optionMenu . popoverPresentationController ? . sourceView = pgpKeyTableViewCell
optionMenu . popoverPresentationController ? . sourceRect = pgpKeyTableViewCell . bounds
2017-02-17 13:44:25 +08:00
self . present ( optionMenu , animated : true , completion : nil )
}
2018-12-09 16:59:07 -08:00
2017-02-07 17:56:31 +08:00
func showPasscodeActionSheet ( ) {
let optionMenu = UIAlertController ( title : nil , message : nil , preferredStyle : . actionSheet )
2018-01-29 03:23:34 +08:00
let passcodeRemoveViewController = PasscodeLockViewController ( )
2018-12-09 16:59:07 -08:00
2017-02-10 00:56:12 +08:00
let removePasscodeAction = UIAlertAction ( title : " Remove Passcode " , style : . destructive ) { [ weak self ] _ in
2018-01-29 03:23:34 +08:00
passcodeRemoveViewController . successCallback = {
self ? . passcodeLock . delete ( )
self ? . setPasscodeLockCell ( )
2017-02-07 20:24:58 +08:00
}
2017-02-10 00:56:12 +08:00
self ? . present ( passcodeRemoveViewController , animated : true , completion : nil )
2017-02-07 20:24:58 +08:00
}
2018-12-09 16:59:07 -08:00
2017-02-10 00:56:12 +08:00
let changePasscodeAction = UIAlertAction ( title : " Change Passcode " , style : . default ) { [ weak self ] _ in
2018-01-29 03:23:34 +08:00
self ? . setPasscodeLock ( )
2017-02-07 20:24:58 +08:00
}
2018-12-09 16:59:07 -08:00
2017-02-07 17:56:31 +08:00
let cancelAction = UIAlertAction ( title : " Cancel " , style : . cancel , handler : nil )
optionMenu . addAction ( removePasscodeAction )
optionMenu . addAction ( changePasscodeAction )
optionMenu . addAction ( cancelAction )
2017-02-22 18:18:59 +08:00
optionMenu . popoverPresentationController ? . sourceView = passcodeTableViewCell
optionMenu . popoverPresentationController ? . sourceRect = passcodeTableViewCell . bounds
2017-02-07 17:56:31 +08:00
self . present ( optionMenu , animated : true , completion : nil )
}
2018-01-29 03:23:34 +08:00
@objc func alertTextFieldDidChange ( _ sender : UITextField ) {
// c h e c k w h e t h e r w e s h o u l d e n a b l e t h e S a v e b u t t o n i n s e t P a s s c o d e L o c k A l e r t
if let setPasscodeLockAlert = self . setPasscodeLockAlert ,
let setPasscodeLockAlertTextFields0 = setPasscodeLockAlert . textFields ? [ 0 ] ,
let setPasscodeLockAlertTextFields1 = setPasscodeLockAlert . textFields ? [ 1 ] {
if sender = = setPasscodeLockAlertTextFields0 || sender = = setPasscodeLockAlertTextFields1 {
// t w o p a s s w o r d s s h o u l d b e t h e s a m e , a n d l e n g t h > = 4
let passcodeText = setPasscodeLockAlertTextFields0 . text !
let passcodeConfirmationText = setPasscodeLockAlertTextFields1 . text !
setPasscodeLockAlert . actions [ 0 ] . isEnabled = passcodeText = = passcodeConfirmationText && passcodeText . count >= 4
}
}
}
2018-12-09 16:59:07 -08:00
2017-02-07 20:24:58 +08:00
func setPasscodeLock ( ) {
2018-01-29 03:23:34 +08:00
// p r e p a r e t h e a l e r t f o r s e t t i n g t h e p a s s c o d e
setPasscodeLockAlert = UIAlertController ( title : " Set passcode " , message : " Fill in your passcode for Pass (at least 4 characters) " , preferredStyle : . alert )
setPasscodeLockAlert ? . addTextField ( configurationHandler : { ( _ textField : UITextField ) -> Void in
textField . placeholder = " Password "
textField . isSecureTextEntry = true
textField . addTarget ( self , action : #selector ( self . alertTextFieldDidChange ( _ : ) ) , for : UIControlEvents . editingChanged )
} )
setPasscodeLockAlert ? . addTextField ( configurationHandler : { ( _ textField : UITextField ) -> Void in
textField . placeholder = " Password Confirmation "
textField . isSecureTextEntry = true
textField . addTarget ( self , action : #selector ( self . alertTextFieldDidChange ( _ : ) ) , for : UIControlEvents . editingChanged )
} )
2018-12-09 16:59:07 -08:00
2018-01-29 03:23:34 +08:00
// s a v e a c t i o n
let saveAction = UIAlertAction ( title : " Save " , style : . default ) { ( action : UIAlertAction ) -> Void in
let passcode : String = self . setPasscodeLockAlert ! . textFields ! [ 0 ] . text !
self . passcodeLock . save ( passcode : passcode )
// r e f r e s h t h e p a s s c o d e l o c k c e l l ( " O n " )
self . setPasscodeLockCell ( )
2017-02-07 20:24:58 +08:00
}
2018-01-29 03:23:34 +08:00
saveAction . isEnabled = false // d i s a b l e t h e S a v e b u t t o n b y d e f a u l t
2018-12-09 16:59:07 -08:00
2018-01-29 03:23:34 +08:00
// c a n c e l a c t i o n
let cancelAction = UIAlertAction ( title : " Cancel " , style : . cancel , handler : nil )
2018-12-09 16:59:07 -08:00
2018-01-29 03:23:34 +08:00
// p r e s e n t
setPasscodeLockAlert ? . addAction ( saveAction )
setPasscodeLockAlert ? . addAction ( cancelAction )
self . present ( setPasscodeLockAlert ! , animated : true , completion : nil )
2017-02-07 20:24:58 +08:00
}
2017-01-19 21:15:47 +08:00
}