passforios/pass/Controllers/SettingsTableViewController.swift

291 lines
12 KiB
Swift
Raw Normal View History

2017-01-19 21:15:47 +08:00
//
// SettingsTableViewController.swift
// pass
//
// Created by Mingshen Sun on 18/1/2017.
// Copyright © 2017 Bob Sun. All rights reserved.
//
import CoreData
import passKit
import SVProgressHUD
import UIKit
2017-01-19 21:15:47 +08:00
2018-01-16 20:26:41 -08:00
class SettingsTableViewController: UITableViewController, UITabBarControllerDelegate {
@IBOutlet var pgpKeyTableViewCell: UITableViewCell!
@IBOutlet var passcodeTableViewCell: UITableViewCell!
@IBOutlet var passwordRepositoryTableViewCell: UITableViewCell!
var setPasscodeLockAlert: UIAlertController?
2018-12-09 16:59:07 -08:00
let passwordStore = PasswordStore.shared
let keychain = AppKeychain.shared
var passcodeLock = PasscodeLock.shared
2018-12-09 16:59:07 -08:00
func tabBarController(_: UITabBarController, didSelect _: UIViewController) {
2018-01-16 20:26:41 -08:00
navigationController?.popViewController(animated: true)
}
2018-12-09 16:59:07 -08:00
@IBAction
private func savePGPKey(segue: UIStoryboardSegue) {
guard let sourceController = segue.source as? PGPKeyImporter, sourceController.isReadyToUse() else {
return
2017-01-19 21:15:47 +08:00
}
savePGPKey(using: sourceController)
2017-01-19 21:15:47 +08:00
}
2018-12-09 16:59:07 -08:00
private func savePGPKey(using keyImporter: PGPKeyImporter) {
SVProgressHUD.setDefaultMaskType(.black)
SVProgressHUD.setDefaultStyle(.light)
2019-01-14 20:57:45 +01:00
SVProgressHUD.show(withStatus: "FetchingPgpKey".localize())
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
Defaults.pgpKeySource = type(of: keyImporter).keySource
do {
2020-04-14 11:55:18 -07:00
// Remove exiting passphrase
AppKeychain.shared.removeAllContent(withPrefix: Globals.pgpKeyPassphrase)
try keyImporter.importKeys()
try PGPAgent.shared.initKeys()
DispatchQueue.main.async {
2019-10-01 01:19:41 +08:00
self.setPGPKeyTableViewCellDetailText()
SVProgressHUD.showSuccess(withStatus: "Success".localize())
SVProgressHUD.dismiss(withDelay: 1)
keyImporter.doAfterImport()
}
} catch {
DispatchQueue.main.async {
2019-01-14 20:57:45 +01:00
self.pgpKeyTableViewCell.detailTextLabel?.text = "NotSet".localize()
Utils.alert(title: "Error".localize(), message: error.localizedDescription, controller: self, completion: nil)
}
}
}
}
2018-12-09 16:59:07 -08:00
@IBAction
private func saveGitServerSetting(segue _: UIStoryboardSegue) {
passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults.gitURL.host
2017-02-21 13:07:14 +08:00
}
2018-12-09 16:59:07 -08:00
2017-01-19 21:15:47 +08:00
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(SettingsTableViewController.actOnPasswordStoreErasedNotification), name: .passwordStoreErased, object: nil)
passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults.gitURL.host
setPGPKeyTableViewCellDetailText()
setPasscodeLockCell()
}
2018-12-09 16:59:07 -08:00
override func viewWillAppear(_: Bool) {
super.viewWillAppear(true)
tabBarController!.delegate = self
setPasswordRepositoryTableViewCellDetailText()
}
2018-12-09 16:59:07 -08:00
private func setPasscodeLockCell() {
if passcodeLock.hasPasscode {
passcodeTableViewCell.detailTextLabel?.text = "On".localize()
} else {
passcodeTableViewCell.detailTextLabel?.text = "Off".localize()
}
}
2018-12-09 16:59:07 -08:00
private func setPGPKeyTableViewCellDetailText() {
var label = "NotSet".localize()
let keyID = (try? PGPAgent.shared.getShortKeyID()) ?? []
if keyID.count == 1 {
label = keyID.first ?? ""
} else if keyID.count > 1 {
label = "Multiple"
}
pgpKeyTableViewCell.detailTextLabel?.text = label
}
2018-12-09 16:59:07 -08:00
private func setPasswordRepositoryTableViewCellDetailText() {
let host: String? = {
let gitURL = Defaults.gitURL
if gitURL.scheme == nil {
return URL(string: "scheme://" + gitURL.absoluteString)?.host
} else {
return gitURL.host
}
}()
passwordRepositoryTableViewCell.detailTextLabel?.text = host
}
2018-12-09 16:59:07 -08:00
@objc
func actOnPasswordStoreErasedNotification() {
setPGPKeyTableViewCellDetailText()
setPasswordRepositoryTableViewCellDetailText()
setPasscodeLockCell()
}
2018-12-09 16:59:07 -08:00
2019-11-17 20:29:22 -08:00
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
cell.textLabel?.font = UIFont.preferredFont(forTextStyle: .body)
2019-11-18 18:13:48 -08:00
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body)
2019-11-17 20:29:22 -08:00
cell.textLabel?.adjustsFontForContentSizeCategory = true
cell.detailTextLabel?.adjustsFontForContentSizeCategory = true
return cell
}
2017-02-07 17:56:31 +08:00
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
if cell == passcodeTableViewCell {
if passcodeLock.hasPasscode {
2017-02-07 20:24:58 +08:00
showPasscodeActionSheet()
} else {
setPasscodeLock()
}
} else if cell == pgpKeyTableViewCell {
2017-02-17 13:44:25 +08:00
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
2021-01-05 23:27:35 -08:00
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
UITableView.automaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
UITableView.automaticDimension
}
2017-02-17 13:44:25 +08:00
func showPGPKeyActionSheet() {
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
optionMenu.addAction(
UIAlertAction(title: PGPKeyUrlImportTableViewController.menuLabel, style: .default) { _ in
self.performSegue(withIdentifier: "setPGPKeyByURLSegue", sender: self)
}
)
optionMenu.addAction(
UIAlertAction(title: PGPKeyArmorImportTableViewController.menuLabel, style: .default) { _ in
self.performSegue(withIdentifier: "setPGPKeyByASCIISegue", sender: self)
}
)
optionMenu.addAction(
UIAlertAction(title: PGPKeyFileImportTableViewController.menuLabel, style: .default) { _ in
self.performSegue(withIdentifier: "setPGPKeyByFileSegue", sender: self)
}
)
if isReadyToUse() {
optionMenu.addAction(
UIAlertAction(title: "\(Self.menuLabel) (\("Import".localize()))", style: .default) { _ in
self.saveImportedKeys()
}
)
} else {
optionMenu.addAction(
UIAlertAction(title: "\(Self.menuLabel) (\("Tips".localize()))", style: .default) { _ in
let title = "Tips".localize()
let message = "PgpCopyPublicAndPrivateKeyToPass.".localize()
Utils.alert(title: title, message: message, controller: self)
}
)
2017-02-24 17:59:04 +03:00
}
2018-12-09 16:59:07 -08:00
if Defaults.pgpKeySource != nil {
optionMenu.addAction(
UIAlertAction(title: "RemovePgpKeys".localize(), style: .destructive) { _ in
self.keychain.removeContent(for: PgpKey.PUBLIC.getKeychainKey())
self.keychain.removeContent(for: PgpKey.PRIVATE.getKeychainKey())
PGPAgent.shared.uninitKeys()
self.pgpKeyTableViewCell.detailTextLabel?.text = "NotSet".localize()
Defaults.pgpKeySource = nil
}
)
2017-02-17 13:44:25 +08:00
}
optionMenu.addAction(UIAlertAction.cancel())
optionMenu.popoverPresentationController?.sourceView = pgpKeyTableViewCell
optionMenu.popoverPresentationController?.sourceRect = pgpKeyTableViewCell.bounds
present(optionMenu, animated: true)
2017-02-17 13:44:25 +08:00
}
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)
let passcodeRemoveViewController = PasscodeLockViewController()
2018-12-09 16:59:07 -08:00
2019-01-14 20:57:45 +01:00
let removePasscodeAction = UIAlertAction(title: "RemovePasscode".localize(), style: .destructive) { [weak self] _ in
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
2019-01-14 20:57:45 +01:00
let changePasscodeAction = UIAlertAction(title: "ChangePasscode".localize(), style: .default) { [weak self] _ in
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
optionMenu.addAction(removePasscodeAction)
optionMenu.addAction(changePasscodeAction)
optionMenu.addAction(UIAlertAction.cancel())
optionMenu.popoverPresentationController?.sourceView = passcodeTableViewCell
optionMenu.popoverPresentationController?.sourceRect = passcodeTableViewCell.bounds
present(optionMenu, animated: true, completion: nil)
2017-02-07 17:56:31 +08:00
}
@objc
func alertTextFieldDidChange(_ sender: UITextField) {
// check whether we should enable the Save button in setPasscodeLockAlert
if let setPasscodeLockAlert = self.setPasscodeLockAlert,
2020-11-07 12:06:28 +01:00
let setPasscodeLockAlertTextFields0 = setPasscodeLockAlert.textFields?[0],
let setPasscodeLockAlertTextFields1 = setPasscodeLockAlert.textFields?[1] {
if sender == setPasscodeLockAlertTextFields0 || sender == setPasscodeLockAlertTextFields1 {
// two passwords should be the same, and length >= 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() {
// prepare the alert for setting the passcode
2019-01-14 20:57:45 +01:00
setPasscodeLockAlert = UIAlertController(title: "SetPasscode".localize(), message: "FillInAppPasscode.".localize(), preferredStyle: .alert)
setPasscodeLockAlert?.addTextField { textField -> Void in
2019-02-13 21:31:40 +01:00
textField.placeholder = "Passcode".localize()
textField.isSecureTextEntry = true
2019-05-01 17:49:27 +02:00
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
}
setPasscodeLockAlert?.addTextField { textField -> Void in
2019-01-14 20:57:45 +01:00
textField.placeholder = "PasswordConfirmation".localize()
textField.isSecureTextEntry = true
2019-05-01 17:49:27 +02:00
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
}
2018-12-09 16:59:07 -08:00
// save action
let saveAction = UIAlertAction(title: "Save".localize(), style: .default) { (_: UIAlertAction) -> Void in
let passcode: String = self.setPasscodeLockAlert!.textFields![0].text!
self.passcodeLock.save(passcode: passcode)
// refresh the passcode lock cell ("On")
self.setPasscodeLockCell()
2017-02-07 20:24:58 +08:00
}
saveAction.isEnabled = false // disable the Save button by default
2018-12-09 16:59:07 -08:00
// cancel action
let cancelAction = UIAlertAction.cancel()
2018-12-09 16:59:07 -08:00
// present
setPasscodeLockAlert?.addAction(saveAction)
setPasscodeLockAlert?.addAction(cancelAction)
present(setPasscodeLockAlert!, animated: true, completion: nil)
2017-02-07 20:24:58 +08:00
}
2017-01-19 21:15:47 +08:00
}
extension SettingsTableViewController: PGPKeyImporter {
static let keySource = KeySource.itunes
static let label = "ITunesFileSharing".localize()
func isReadyToUse() -> Bool {
KeyFileManager.PublicPgp.doesKeyFileExist() && KeyFileManager.PrivatePgp.doesKeyFileExist()
}
func importKeys() throws {
try KeyFileManager.PublicPgp.importKeyFromFileSharing()
try KeyFileManager.PrivatePgp.importKeyFromFileSharing()
}
func saveImportedKeys() {
savePGPKey(using: self)
}
}