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

View file

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"/> <device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <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"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <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"> <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"/> <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections/> <sections/>
<connections> <connections>
<outlet property="dataSource" destination="2RE-j0-dBT" id="SPm-AZ-299"/> <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> <inferredMetricsTieBreakers>
<segue reference="wCk-aN-a4J"/> <segue reference="wCk-aN-a4J"/>
<segue reference="oxP-I1-Mke"/> <segue reference="oxP-I1-Mke"/>
<segue reference="yyD-4H-pLE"/> <segue reference="UfP-k3-XeR"/>
</inferredMetricsTieBreakers> </inferredMetricsTieBreakers>
</document> </document>

View file

@ -10,22 +10,11 @@ import UIKit
import passKit import passKit
class AddPasswordTableViewController: PasswordEditorTableViewController { class AddPasswordTableViewController: PasswordEditorTableViewController {
let passwordStore = PasswordStore.shared
var defaultDirPrefix = "" var defaultDirPrefix = ""
override func viewDidLoad() { 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() super.viewDidLoad()
tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix
} }
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
@ -39,7 +28,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
} }
// check name // check name
guard checkName() == true else { guard checkName() else {
return false return false
} }
} }

View file

@ -10,25 +10,10 @@ import UIKit
import passKit import passKit
class EditPasswordTableViewController: PasswordEditorTableViewController { 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 { override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "saveEditPasswordSegue" { if identifier == "saveEditPasswordSegue" {
// check name // check name
guard checkName() == true else { guard checkName() else {
return false return false
} }
} }

View file

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

View file

@ -89,9 +89,22 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
tableView.rowHeight = UITableView.automaticDimension tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 48 tableView.estimatedRowHeight = 48
self.tableView.sectionFooterHeight = UITableView.automaticDimension; self.tableView.sectionFooterHeight = UITableView.automaticDimension
self.tableView.estimatedSectionFooterHeight = 0; 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() { override func viewDidLayoutSubviews() {
additionsCell?.contentTextView.setContentOffset(.zero, animated: false) additionsCell?.contentTextView.setContentOffset(.zero, animated: false)
} }
@ -116,7 +129,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
return fillPasswordCell! return fillPasswordCell!
case .passwordLengthCell: case .passwordLengthCell:
passwordLengthCell = tableView.dequeueReusableCell(withIdentifier: "passwordLengthCell", for: indexPath) as? SliderTableViewCell 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 minimumLength = lengthSetting.min
let maximumLength = lengthSetting.max let maximumLength = lengthSetting.max
var defaultLength = lengthSetting.def var defaultLength = lengthSetting.def
@ -215,7 +228,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
showPasswordSettings() showPasswordSettings()
let length = passwordLengthCell?.roundedValue ?? 0 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 // update tableData so to make sure reloadData() works correctly
tableData[passwordSection][0][PasswordEditorCellKey.content] = plainPassword tableData[passwordSection][0][PasswordEditorCellKey.content] = plainPassword

View file

@ -19,6 +19,8 @@ public enum GitAuthenticationMethod: String, DefaultsSerializable {
case password, key case password, key
} }
extension PasswordGeneratorFlavor: DefaultsSerializable {}
public extension DefaultsKeys { public extension DefaultsKeys {
var pgpKeySource: DefaultsKey<KeySource?> { .init("pgpKeySource") } var pgpKeySource: DefaultsKey<KeySource?> { .init("pgpKeySource") }
var pgpPublicKeyURL: DefaultsKey<URL?> { .init("pgpPublicKeyURL") } var pgpPublicKeyURL: DefaultsKey<URL?> { .init("pgpPublicKeyURL") }
@ -50,7 +52,7 @@ public extension DefaultsKeys {
var isShowFolderOn: DefaultsKey<Bool> { .init("isShowFolderOn", defaultValue: true) } var isShowFolderOn: DefaultsKey<Bool> { .init("isShowFolderOn", defaultValue: true) }
var isHidePasswordImagesOn: DefaultsKey<Bool> { .init("isHidePasswordImagesOn", defaultValue: false) } var isHidePasswordImagesOn: DefaultsKey<Bool> { .init("isHidePasswordImagesOn", defaultValue: false) }
var searchDefault: DefaultsKey<SearchBarScope?> { .init("searchDefault", defaultValue: .all) } 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) } 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 // passKitTests
// //
// Created by Danny Moesch on 28.11.18. // Created by Danny Moesch on 28.11.18.
@ -11,25 +11,18 @@ import XCTest
@testable import passKit @testable import passKit
class PasswordGeneratorFlavourTest: XCTestCase { class PasswordGeneratorFlavorTest: XCTestCase {
private let KEYCHAIN_PASSWORD_LENGTH = Keychain.generatePassword().count 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() { func testLocalizedName() {
XCTAssertEqual(PasswordGeneratorFlavour.APPLE.name, "Apple".localize()) XCTAssertEqual(PasswordGeneratorFlavor.apple.localized, "Apple".localize())
XCTAssertEqual(PasswordGeneratorFlavour.RANDOM.name, "Random".localize()) XCTAssertEqual(PasswordGeneratorFlavor.random.localized, "Random".localize())
} }
func testDefaultLength() { func testDefaultLength() {
// Ensure properly chosen default length values. So this check no longer needs to be performed in the code. // 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.min, defaultLength.max)
XCTAssertLessThanOrEqual(defaultLength.def, defaultLength.max) XCTAssertLessThanOrEqual(defaultLength.def, defaultLength.max)
XCTAssertGreaterThanOrEqual(defaultLength.def, defaultLength.min) XCTAssertGreaterThanOrEqual(defaultLength.def, defaultLength.min)
@ -37,12 +30,12 @@ class PasswordGeneratorFlavourTest: XCTestCase {
} }
func testGeneratePassword() { func testGeneratePassword() {
let apple = PasswordGeneratorFlavour.APPLE let apple = PasswordGeneratorFlavor.apple
let random = PasswordGeneratorFlavour.RANDOM let random = PasswordGeneratorFlavor.random
XCTAssertEqual(apple.generatePassword(length: 4).count, KEYCHAIN_PASSWORD_LENGTH) XCTAssertEqual(apple.generate(length: 4).count, KEYCHAIN_PASSWORD_LENGTH)
XCTAssertEqual(random.generatePassword(length: 0).count, 0) XCTAssertEqual(random.generate(length: 0).count, 0)
XCTAssertEqual(random.generatePassword(length: 4).count, 4) XCTAssertEqual(random.generate(length: 4).count, 4)
XCTAssertEqual(random.generatePassword(length: 100).count, 100) XCTAssertEqual(random.generate(length: 100).count, 100)
} }
} }