Introduce enum for password generator flavour
This commit is contained in:
parent
1f57305203
commit
3cd8df310c
10 changed files with 102 additions and 47 deletions
|
|
@ -16,6 +16,8 @@
|
|||
301F646D216166AA0071A4CE /* AdditionFieldTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 301F646C216166AA0071A4CE /* AdditionFieldTest.swift */; };
|
||||
302E85612125ECC70031BA64 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E85602125ECC70031BA64 /* Parser.swift */; };
|
||||
302E85632125EE550031BA64 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 302E85622125EE550031BA64 /* Constants.swift */; };
|
||||
30A1D29C21AF451E00E2D1F7 /* PasswordGeneratorFlavourTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A1D29B21AF451E00E2D1F7 /* PasswordGeneratorFlavourTest.swift */; };
|
||||
30A1D29E21AF468F00E2D1F7 /* PasswordGeneratorFlavour.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A1D29D21AF468E00E2D1F7 /* PasswordGeneratorFlavour.swift */; };
|
||||
30AAC05321989DCE00F656CE /* PasswordHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AAC05221989DCE00F656CE /* PasswordHelpers.swift */; };
|
||||
30B04860209A5141001013CA /* PasswordTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B0485F209A5141001013CA /* PasswordTest.swift */; };
|
||||
30FD2F78214D9E0E005E0A92 /* ParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30FD2F77214D9E0E005E0A92 /* ParserTest.swift */; };
|
||||
|
|
@ -190,6 +192,8 @@
|
|||
301F646C216166AA0071A4CE /* AdditionFieldTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionFieldTest.swift; sourceTree = "<group>"; };
|
||||
302E85602125ECC70031BA64 /* Parser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
|
||||
302E85622125EE550031BA64 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
30A1D29B21AF451E00E2D1F7 /* PasswordGeneratorFlavourTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordGeneratorFlavourTest.swift; sourceTree = "<group>"; };
|
||||
30A1D29D21AF468E00E2D1F7 /* PasswordGeneratorFlavour.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasswordGeneratorFlavour.swift; path = Helpers/PasswordGeneratorFlavour.swift; sourceTree = "<group>"; };
|
||||
30AAC05221989DCE00F656CE /* PasswordHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasswordHelpers.swift; path = Helpers/PasswordHelpers.swift; sourceTree = "<group>"; };
|
||||
30B0485F209A5141001013CA /* PasswordTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordTest.swift; sourceTree = "<group>"; };
|
||||
30FD2F77214D9E0E005E0A92 /* ParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParserTest.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -382,6 +386,7 @@
|
|||
children = (
|
||||
301F6465216164830071A4CE /* PasswordHelpersTest.swift */,
|
||||
301F6469216166000071A4CE /* StringExtensionTest.swift */,
|
||||
30A1D29B21AF451E00E2D1F7 /* PasswordGeneratorFlavourTest.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -528,6 +533,7 @@
|
|||
A239F5202157B75E00576CBF /* FileManagerExtension.swift */,
|
||||
A2F4E21A1EED80160011986E /* Globals.swift */,
|
||||
A2F4E21B1EED80160011986E /* NotificationNames.swift */,
|
||||
30A1D29D21AF468E00E2D1F7 /* PasswordGeneratorFlavour.swift */,
|
||||
30AAC05221989DCE00F656CE /* PasswordHelpers.swift */,
|
||||
A239F51E2157B72700576CBF /* StringExtension.swift */,
|
||||
A2F4E21C1EED80160011986E /* UITextFieldExtension.swift */,
|
||||
|
|
@ -1149,6 +1155,7 @@
|
|||
A2C532BB201E5A9600DB9F53 /* PasscodeLock.swift in Sources */,
|
||||
A2F4E2151EED800F0011986E /* Password.swift in Sources */,
|
||||
A26075AD1EEC7125005DB03E /* pass.xcdatamodeld in Sources */,
|
||||
30A1D29E21AF468F00E2D1F7 /* PasswordGeneratorFlavour.swift in Sources */,
|
||||
A239F51F2157B72700576CBF /* StringExtension.swift in Sources */,
|
||||
A239F5212157B75E00576CBF /* FileManagerExtension.swift in Sources */,
|
||||
A2F4E21E1EED80160011986E /* AppError.swift in Sources */,
|
||||
|
|
@ -1177,6 +1184,7 @@
|
|||
30FD2F78214D9E0E005E0A92 /* ParserTest.swift in Sources */,
|
||||
30B04860209A5141001013CA /* PasswordTest.swift in Sources */,
|
||||
301F6468216165290071A4CE /* ConstantsTest.swift in Sources */,
|
||||
30A1D29C21AF451E00E2D1F7 /* PasswordGeneratorFlavourTest.swift in Sources */,
|
||||
A26075881EEC6F34005DB03E /* passKitTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
self.perform(#selector(postSearchNotification), with: nil, afterDelay: 0.4)
|
||||
}
|
||||
}
|
||||
Utils.initDefaultKeys()
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
|
|||
[[.type: PasswordEditorCellType.additionsCell, .title: "additions"]],
|
||||
[[.type: PasswordEditorCellType.scanQRCodeCell]]
|
||||
]
|
||||
if let lengthSetting = Globals.passwordDefaultLength[SharedDefaults[.passwordGeneratorFlavor]],
|
||||
lengthSetting.max > lengthSetting.min {
|
||||
if PasswordGeneratorFlavour.from(SharedDefaults[.passwordGeneratorFlavor]) == PasswordGeneratorFlavour.RANDOM {
|
||||
tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"])
|
||||
}
|
||||
tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell])
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ class EditPasswordTableViewController: PasswordEditorTableViewController {
|
|||
[[.type: PasswordEditorCellType.scanQRCodeCell],
|
||||
[.type: PasswordEditorCellType.deletePasswordCell]]
|
||||
]
|
||||
if let lengthSetting = Globals.passwordDefaultLength[SharedDefaults[.passwordGeneratorFlavor]],
|
||||
lengthSetting.max > lengthSetting.min {
|
||||
if PasswordGeneratorFlavour.from(SharedDefaults[.passwordGeneratorFlavor]) == PasswordGeneratorFlavour.RANDOM {
|
||||
tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"])
|
||||
}
|
||||
tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell])
|
||||
|
|
|
|||
|
|
@ -104,11 +104,10 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
|||
return fillPasswordCell!
|
||||
case .passwordLengthCell:
|
||||
passwordLengthCell = tableView.dequeueReusableCell(withIdentifier: "passwordLengthCell", for: indexPath) as? SliderTableViewCell
|
||||
let lengthSetting = Globals.passwordDefaultLength[SharedDefaults[.passwordGeneratorFlavor]] ??
|
||||
Globals.passwordDefaultLength["Random"]
|
||||
let minimumLength = lengthSetting?.min ?? 0
|
||||
let maximumLength = lengthSetting?.max ?? 0
|
||||
var defaultLength = lengthSetting?.def ?? 0
|
||||
let lengthSetting = PasswordGeneratorFlavour.from(SharedDefaults[.passwordGeneratorFlavor]).defaultLength
|
||||
let minimumLength = lengthSetting.min
|
||||
let maximumLength = lengthSetting.max
|
||||
var defaultLength = lengthSetting.def
|
||||
if let currentPasswordLength = (tableData[passwordSection][0][PasswordEditorCellKey.content] as? String)?.count,
|
||||
currentPasswordLength >= minimumLength,
|
||||
currentPasswordLength <= maximumLength {
|
||||
|
|
@ -203,7 +202,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
|||
showPasswordSettings()
|
||||
|
||||
let length = passwordLengthCell?.roundedValue ?? 0
|
||||
let plainPassword = Password.generatePassword(length: length)
|
||||
let plainPassword = PasswordGeneratorFlavour.from(SharedDefaults[.passwordGeneratorFlavor]).generatePassword(length: length)
|
||||
SecurePasteboard.shared.copy(textToCopy: plainPassword)
|
||||
|
||||
// update tableData so to make sure reloadData() works correctly
|
||||
|
|
|
|||
|
|
@ -39,9 +39,6 @@ public class Globals {
|
|||
public static let iTunesFileSharingPGPPrivate = iTunesFileSharingPath + "/gpg_key"
|
||||
public static let iTunesFileSharingSSHPrivate = iTunesFileSharingPath + "/ssh_key"
|
||||
|
||||
public static let passwordDefaultLength = ["Random": (min: 4, max: 64, def: 16),
|
||||
"Apple": (min: 15, max: 15, def: 15)]
|
||||
|
||||
public static let gitSignatureDefaultName = "Pass for iOS"
|
||||
public static let gitSignatureDefaultEmail = "user@passforios"
|
||||
|
||||
|
|
|
|||
44
passKit/Helpers/PasswordGeneratorFlavour.swift
Normal file
44
passKit/Helpers/PasswordGeneratorFlavour.swift
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// 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 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 {}
|
||||
|
|
@ -53,11 +53,6 @@ public class Utils {
|
|||
}
|
||||
return attributedPassword
|
||||
}
|
||||
public static func initDefaultKeys() {
|
||||
if SharedDefaults[.passwordGeneratorFlavor] == "" {
|
||||
SharedDefaults[.passwordGeneratorFlavor] = "Random"
|
||||
}
|
||||
}
|
||||
|
||||
public static func alert(title: String, message: String, controller: UIViewController, handler: ((UIAlertAction) -> Void)? = nil, completion: (() -> Void)? = nil) {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
import SwiftyUserDefaults
|
||||
import OneTimePassword
|
||||
import Base32
|
||||
import KeychainAccess
|
||||
|
||||
public class Password {
|
||||
|
||||
|
|
@ -276,31 +275,4 @@ public class Password {
|
|||
// get and return the password
|
||||
return self.otpToken?.currentPassword
|
||||
}
|
||||
|
||||
public static func generatePassword(length: Int) -> String{
|
||||
switch SharedDefaults[.passwordGeneratorFlavor] {
|
||||
case "Random":
|
||||
return randomString(length: length)
|
||||
case "Apple":
|
||||
return Keychain.generatePassword()
|
||||
default:
|
||||
return randomString(length: length)
|
||||
}
|
||||
}
|
||||
|
||||
private static func randomString(length: Int) -> String {
|
||||
|
||||
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*_+-="
|
||||
let len = UInt32(letters.length)
|
||||
|
||||
var randomString = ""
|
||||
|
||||
for _ in 0 ..< length {
|
||||
let rand = arc4random_uniform(len)
|
||||
var nextChar = letters.character(at: Int(rand))
|
||||
randomString += NSString(characters: &nextChar, length: 1) as String
|
||||
}
|
||||
|
||||
return randomString
|
||||
}
|
||||
}
|
||||
|
|
|
|||
43
passKitTests/Helpers/PasswordGeneratorFlavourTest.swift
Normal file
43
passKitTests/Helpers/PasswordGeneratorFlavourTest.swift
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// PasswordGeneratorFlavourTest.swift
|
||||
// passKitTests
|
||||
//
|
||||
// Created by Danny Moesch on 28.11.18.
|
||||
// Copyright © 2018 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import KeychainAccess
|
||||
import XCTest
|
||||
|
||||
@testable import passKit
|
||||
|
||||
class PasswordGeneratorFlavourTest: 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 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
|
||||
XCTAssertLessThanOrEqual(defaultLength.min, defaultLength.max)
|
||||
XCTAssertLessThanOrEqual(defaultLength.def, defaultLength.max)
|
||||
XCTAssertGreaterThanOrEqual(defaultLength.def, defaultLength.min)
|
||||
}
|
||||
}
|
||||
|
||||
func testGeneratePassword() {
|
||||
let apple = PasswordGeneratorFlavour.APPLE
|
||||
let random = PasswordGeneratorFlavour.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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue