Polish codes related to password generation

1. Polish codes in PasswordGeneratorFlavour
2. Polish related codes in view controllers
This commit is contained in:
Yishi Lin 2020-02-22 23:23:02 +08:00
parent ae94388ba4
commit 71c793029a
10 changed files with 108 additions and 127 deletions

View file

@ -26,7 +26,7 @@
30697C2A21F63C5A0064FCAC /* NotificationNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2321F63C580064FCAC /* NotificationNames.swift */; };
30697C2B21F63C5A0064FCAC /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2421F63C590064FCAC /* Globals.swift */; };
30697C2C21F63C5A0064FCAC /* FileManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2521F63C590064FCAC /* FileManagerExtension.swift */; };
30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavour.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2621F63C590064FCAC /* PasswordGeneratorFlavour.swift */; };
30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2621F63C590064FCAC /* PasswordGeneratorFlavor.swift */; };
30697C2E21F63C5A0064FCAC /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2721F63C590064FCAC /* Utils.swift */; };
30697C2F21F63C5A0064FCAC /* DefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2821F63C590064FCAC /* DefaultsKeys.swift */; };
30697C3021F63C5A0064FCAC /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2921F63C590064FCAC /* AppError.swift */; };
@ -249,7 +249,7 @@
30697C2321F63C580064FCAC /* NotificationNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationNames.swift; sourceTree = "<group>"; };
30697C2421F63C590064FCAC /* Globals.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = "<group>"; };
30697C2521F63C590064FCAC /* FileManagerExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileManagerExtension.swift; sourceTree = "<group>"; };
30697C2621F63C590064FCAC /* PasswordGeneratorFlavour.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGeneratorFlavour.swift; sourceTree = "<group>"; };
30697C2621F63C590064FCAC /* PasswordGeneratorFlavor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGeneratorFlavor.swift; sourceTree = "<group>"; };
30697C2721F63C590064FCAC /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
30697C2821F63C590064FCAC /* DefaultsKeys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultsKeys.swift; sourceTree = "<group>"; };
30697C2921F63C590064FCAC /* AppError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = "<group>"; };
@ -678,7 +678,7 @@
3032327322C7F710009EBD9C /* KeyFileManager.swift */,
30BAC8CC22E3BB9700438475 /* KeyStore.swift */,
30697C2321F63C580064FCAC /* NotificationNames.swift */,
30697C2621F63C590064FCAC /* PasswordGeneratorFlavour.swift */,
30697C2621F63C590064FCAC /* PasswordGeneratorFlavor.swift */,
302202EE222F14E400555236 /* SearchBarScope.swift */,
30697C2721F63C590064FCAC /* Utils.swift */,
);
@ -1305,7 +1305,7 @@
30697C2B21F63C5A0064FCAC /* Globals.swift in Sources */,
30697C4821F63CAB0064FCAC /* PasswordStore.swift in Sources */,
A26075AD1EEC7125005DB03E /* pass.xcdatamodeld in Sources */,
30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavour.swift in Sources */,
30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavor.swift in Sources */,
308C273A2279F9CB0016D0E2 /* SearchBarScope.swift in Sources */,
30697C2F21F63C5A0064FCAC /* DefaultsKeys.swift in Sources */,
30A1D2A821B2D53200E2D1F7 /* PasswordChange.swift in Sources */,

View file

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="YoR-iB-XAd">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="YoR-iB-XAd">
<device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -809,7 +809,7 @@
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="wRM-8V-raT">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections/>
<connections>
<outlet property="dataSource" destination="2RE-j0-dBT" id="SPm-AZ-299"/>
@ -1968,6 +1968,6 @@ Secret Question 1: What is your childhood best friend's most bizarre superhero f
<inferredMetricsTieBreakers>
<segue reference="wCk-aN-a4J"/>
<segue reference="oxP-I1-Mke"/>
<segue reference="yyD-4H-pLE"/>
<segue reference="UfP-k3-XeR"/>
</inferredMetricsTieBreakers>
</document>

View file

@ -10,22 +10,11 @@ import UIKit
import passKit
class AddPasswordTableViewController: PasswordEditorTableViewController {
let passwordStore = PasswordStore.shared
var defaultDirPrefix = ""
override func viewDidLoad() {
tableData = [
[[.type: PasswordEditorCellType.nameCell, .title: "name"]],
[[.type: PasswordEditorCellType.fillPasswordCell, .title: "password"]],
[[.type: PasswordEditorCellType.additionsCell, .title: "additions"]],
[[.type: PasswordEditorCellType.scanQRCodeCell]]
]
if PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor) == .RANDOM {
tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"])
}
tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell])
tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix
super.viewDidLoad()
tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
@ -39,7 +28,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
}
// check name
guard checkName() == true else {
guard checkName() else {
return false
}
}

View file

@ -10,25 +10,10 @@ import UIKit
import passKit
class EditPasswordTableViewController: PasswordEditorTableViewController {
override func viewDidLoad() {
tableData = [
[[.type: PasswordEditorCellType.nameCell, .title: "Name".localize(), .content: password!.namePath]],
[[.type: PasswordEditorCellType.fillPasswordCell, .title: "Password".localize(), .content: password!.password]],
[[.type: PasswordEditorCellType.additionsCell, .title: "Additions".localize(), .content: password!.additionsPlainText]],
[[.type: PasswordEditorCellType.scanQRCodeCell],
[.type: PasswordEditorCellType.deletePasswordCell]]
]
if PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor) == .RANDOM {
tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"])
}
tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell])
super.viewDidLoad()
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "saveEditPasswordSegue" {
// check name
guard checkName() == true else {
guard checkName() else {
return false
}
}

View file

@ -144,7 +144,7 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
hidePasswordImagesSwitch.isOn = Defaults.isHidePasswordImagesOn
case "PasswordGeneratorFlavor".localize():
cell.accessoryType = .disclosureIndicator
cell.detailTextLabel?.text = PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor).name
cell.detailTextLabel?.text = Defaults.passwordGeneratorFlavor.localized
default: break
}
return cell
@ -161,31 +161,26 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
func showPasswordGeneratorFlavorActionSheet(sourceCell: UITableViewCell) {
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
var randomFlavorActionTitle = ""
var appleFlavorActionTitle = ""
if Defaults.passwordGeneratorFlavor == PasswordGeneratorFlavour.RANDOM.rawValue {
randomFlavorActionTitle = "" + "RandomString".localize()
appleFlavorActionTitle = "ApplesKeychainStyle".localize()
} else {
randomFlavorActionTitle = "RandomString".localize()
appleFlavorActionTitle = "" + "ApplesKeychainStyle".localize()
}
let randomFlavorAction = UIAlertAction(title: randomFlavorActionTitle, style: .default) { _ in
Defaults.passwordGeneratorFlavor = PasswordGeneratorFlavour.RANDOM.rawValue
sourceCell.detailTextLabel?.text = PasswordGeneratorFlavour.RANDOM.name
}
let appleFlavorAction = UIAlertAction(title: appleFlavorActionTitle, style: .default) { _ in
Defaults.passwordGeneratorFlavor = PasswordGeneratorFlavour.APPLE.rawValue
sourceCell.detailTextLabel?.text = PasswordGeneratorFlavour.APPLE.name
PasswordGeneratorFlavor.allCases.forEach { flavor in
let actionTitlePrefix = Defaults.passwordGeneratorFlavor
var actionTitle = flavor.longNameLocalized
if Defaults.passwordGeneratorFlavor == flavor {
actionTitle = "" + actionTitle
}
let action = UIAlertAction(title: actionTitle, style: .default) { _ in
Defaults.passwordGeneratorFlavor = flavor
sourceCell.detailTextLabel?.text = Defaults.passwordGeneratorFlavor.localized
}
optionMenu.addAction(action)
}
let cancelAction = UIAlertAction(title: "Cancel".localize(), style: .cancel, handler: nil)
optionMenu.addAction(randomFlavorAction)
optionMenu.addAction(appleFlavorAction)
optionMenu.addAction(cancelAction)
optionMenu.popoverPresentationController?.sourceView = sourceCell
optionMenu.popoverPresentationController?.sourceRect = sourceCell.bounds
self.present(optionMenu, animated: true, completion: nil)
}

View file

@ -89,9 +89,22 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 48
self.tableView.sectionFooterHeight = UITableView.automaticDimension;
self.tableView.estimatedSectionFooterHeight = 0;
self.tableView.sectionFooterHeight = UITableView.automaticDimension
self.tableView.estimatedSectionFooterHeight = 0
tableData = [
[[.type: PasswordEditorCellType.nameCell, .title: "Name".localize(), .content: password?.namePath ?? ""]],
[[.type: PasswordEditorCellType.fillPasswordCell, .title: "Password".localize(), .content: password?.password ?? ""]],
[[.type: PasswordEditorCellType.additionsCell, .title: "Additions".localize(), .content: password?.additionsPlainText ?? ""]],
[[.type: PasswordEditorCellType.scanQRCodeCell],
[.type: PasswordEditorCellType.deletePasswordCell]]
]
if Defaults.passwordGeneratorFlavor == .random {
tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"])
}
tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell])
}
override func viewDidLayoutSubviews() {
additionsCell?.contentTextView.setContentOffset(.zero, animated: false)
}
@ -116,7 +129,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
return fillPasswordCell!
case .passwordLengthCell:
passwordLengthCell = tableView.dequeueReusableCell(withIdentifier: "passwordLengthCell", for: indexPath) as? SliderTableViewCell
let lengthSetting = PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor).defaultLength
let lengthSetting = Defaults.passwordGeneratorFlavor.defaultLength
let minimumLength = lengthSetting.min
let maximumLength = lengthSetting.max
var defaultLength = lengthSetting.def
@ -215,7 +228,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
showPasswordSettings()
let length = passwordLengthCell?.roundedValue ?? 0
let plainPassword = PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor).generatePassword(length: length)
let plainPassword = Defaults.passwordGeneratorFlavor.generate(length: length)
// update tableData so to make sure reloadData() works correctly
tableData[passwordSection][0][PasswordEditorCellKey.content] = plainPassword

View file

@ -19,6 +19,8 @@ public enum GitAuthenticationMethod: String, DefaultsSerializable {
case password, key
}
extension PasswordGeneratorFlavor: DefaultsSerializable {}
public extension DefaultsKeys {
var pgpKeySource: DefaultsKey<KeySource?> { .init("pgpKeySource") }
var pgpPublicKeyURL: DefaultsKey<URL?> { .init("pgpPublicKeyURL") }
@ -50,7 +52,7 @@ public extension DefaultsKeys {
var isShowFolderOn: DefaultsKey<Bool> { .init("isShowFolderOn", defaultValue: true) }
var isHidePasswordImagesOn: DefaultsKey<Bool> { .init("isHidePasswordImagesOn", defaultValue: false) }
var searchDefault: DefaultsKey<SearchBarScope?> { .init("searchDefault", defaultValue: .all) }
var passwordGeneratorFlavor: DefaultsKey<String> { .init("passwordGeneratorFlavor", defaultValue: "Apple") }
var passwordGeneratorFlavor: DefaultsKey<PasswordGeneratorFlavor> { .init("passwordGeneratorFlavor", defaultValue: .apple) }
var encryptInArmored: DefaultsKey<Bool> { .init("encryptInArmored", defaultValue: false) }
}

View file

@ -0,0 +1,52 @@
//
// PasswordGeneratorFlavour.swift
// passKit
//
// Created by Danny Moesch on 28.11.18.
// Copyright © 2018 Bob Sun. All rights reserved.
//
import KeychainAccess
public enum PasswordGeneratorFlavor: String {
case apple = "Apple"
case random = "Random"
public var localized: String {
return rawValue.localize()
}
public var longNameLocalized: String {
switch self {
case .apple:
return "ApplesKeychainStyle".localize()
case .random:
return "RandomString".localize()
}
}
public var defaultLength: (min: Int, max: Int, def: Int) {
switch self {
case .apple:
return (15, 15, 15)
case .random:
return (4, 64, 16)
}
}
public func generate(length: Int) -> String {
switch self {
case .apple:
return Keychain.generatePassword()
case .random:
return PasswordGeneratorFlavor.generateRandom(length: length)
}
}
private static func generateRandom(length: Int) -> String {
let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*_+-="
return String((0..<length).map { _ in chars.randomElement()! })
}
}
extension PasswordGeneratorFlavor: CaseIterable {}

View file

@ -1,48 +0,0 @@
//
// PasswordGeneratorFlavour.swift
// passKit
//
// Created by Danny Moesch on 28.11.18.
// Copyright © 2018 Bob Sun. All rights reserved.
//
import KeychainAccess
public enum PasswordGeneratorFlavour: String {
case APPLE = "Apple"
case RANDOM = "Random"
private static let ALLOWED_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*_+-="
public static func from(_ option: String) -> PasswordGeneratorFlavour {
return PasswordGeneratorFlavour(rawValue: option) ?? PasswordGeneratorFlavour.RANDOM
}
public var name: String {
return rawValue.localize()
}
public var defaultLength: (min: Int, max: Int, def: Int) {
switch self {
case .APPLE:
return (15, 15, 15)
default:
return (4, 64, 16)
}
}
public func generatePassword(length: Int) -> String {
switch self {
case .APPLE:
return Keychain.generatePassword()
default:
return PasswordGeneratorFlavour.randomString(length: length)
}
}
private static func randomString(length: Int) -> String {
return String((0..<length).map { _ in ALLOWED_CHARACTERS.randomElement()! })
}
}
extension PasswordGeneratorFlavour: CaseIterable {}

View file

@ -1,5 +1,5 @@
//
// PasswordGeneratorFlavourTest.swift
// PasswordGeneratorFlavorTest.swift
// passKitTests
//
// Created by Danny Moesch on 28.11.18.
@ -11,25 +11,18 @@ import XCTest
@testable import passKit
class PasswordGeneratorFlavourTest: XCTestCase {
class PasswordGeneratorFlavorTest: XCTestCase {
private let KEYCHAIN_PASSWORD_LENGTH = Keychain.generatePassword().count
func testFrom() {
XCTAssertEqual(PasswordGeneratorFlavour.from("Apple"), PasswordGeneratorFlavour.APPLE)
XCTAssertEqual(PasswordGeneratorFlavour.from("Random"), PasswordGeneratorFlavour.RANDOM)
XCTAssertEqual(PasswordGeneratorFlavour.from("Something"), PasswordGeneratorFlavour.RANDOM)
XCTAssertEqual(PasswordGeneratorFlavour.from(""), PasswordGeneratorFlavour.RANDOM)
}
func testLocalizedName() {
XCTAssertEqual(PasswordGeneratorFlavour.APPLE.name, "Apple".localize())
XCTAssertEqual(PasswordGeneratorFlavour.RANDOM.name, "Random".localize())
XCTAssertEqual(PasswordGeneratorFlavor.apple.localized, "Apple".localize())
XCTAssertEqual(PasswordGeneratorFlavor.random.localized, "Random".localize())
}
func testDefaultLength() {
// Ensure properly chosen default length values. So this check no longer needs to be performed in the code.
PasswordGeneratorFlavour.allCases.map { $0.defaultLength }.forEach { defaultLength in
PasswordGeneratorFlavor.allCases.map { $0.defaultLength }.forEach { defaultLength in
XCTAssertLessThanOrEqual(defaultLength.min, defaultLength.max)
XCTAssertLessThanOrEqual(defaultLength.def, defaultLength.max)
XCTAssertGreaterThanOrEqual(defaultLength.def, defaultLength.min)
@ -37,12 +30,12 @@ class PasswordGeneratorFlavourTest: XCTestCase {
}
func testGeneratePassword() {
let apple = PasswordGeneratorFlavour.APPLE
let random = PasswordGeneratorFlavour.RANDOM
let apple = PasswordGeneratorFlavor.apple
let random = PasswordGeneratorFlavor.random
XCTAssertEqual(apple.generatePassword(length: 4).count, KEYCHAIN_PASSWORD_LENGTH)
XCTAssertEqual(random.generatePassword(length: 0).count, 0)
XCTAssertEqual(random.generatePassword(length: 4).count, 4)
XCTAssertEqual(random.generatePassword(length: 100).count, 100)
XCTAssertEqual(apple.generate(length: 4).count, KEYCHAIN_PASSWORD_LENGTH)
XCTAssertEqual(random.generate(length: 0).count, 0)
XCTAssertEqual(random.generate(length: 4).count, 4)
XCTAssertEqual(random.generate(length: 100).count, 100)
}
}