From 942634542cd02aa360a83d396c417019dffa02d8 Mon Sep 17 00:00:00 2001 From: Andrej Kolar Date: Wed, 8 Jun 2022 17:07:38 +0200 Subject: [PATCH] SwiftPM project --- .gitignore | 7 + Package.swift | 22 +++ README.md | 3 + Sources/PassGen/PasswordGenerator.swift | 92 +++++++++++ Sources/PassGen/main.swift | 8 + Tests/PassGenTests/PassGenTests.swift | 47 ++++++ .../PassGenTests/PasswordGeneratorTests.swift | 143 ++++++++++++++++++ 7 files changed, 322 insertions(+) create mode 100644 .gitignore create mode 100644 Package.swift create mode 100644 README.md create mode 100644 Sources/PassGen/PasswordGenerator.swift create mode 100644 Sources/PassGen/main.swift create mode 100644 Tests/PassGenTests/PassGenTests.swift create mode 100644 Tests/PassGenTests/PasswordGeneratorTests.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb460e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..566efe5 --- /dev/null +++ b/Package.swift @@ -0,0 +1,22 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "PassGen", + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .executableTarget( + name: "PassGen", + dependencies: []), + .testTarget( + name: "PassGenTests", + dependencies: ["PassGen"]), + ] +) diff --git a/README.md b/README.md new file mode 100644 index 0000000..144bb72 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# PassGen + +A description of this package. diff --git a/Sources/PassGen/PasswordGenerator.swift b/Sources/PassGen/PasswordGenerator.swift new file mode 100644 index 0000000..62c03f4 --- /dev/null +++ b/Sources/PassGen/PasswordGenerator.swift @@ -0,0 +1,92 @@ +// +// PasswordGenerator.swift +// +// +// Created by Andrej Kolar on 6/8/22. +// + +import Foundation + +struct PasswordGenerator { + public struct Defaults { + static let length = 16 + static let wordLength = 8 + static let wordCount = 4 + static let type: PasswordType = .normal(Defaults.length) + static let characters: Set = [ + .uppercase, + .lowercase, + .numbers, + .symbols + ] + static let separator: SeparatorType = .space + } + + enum PasswordType { + case normal(Int) + case separated(Int, Int, SeparatorType) + } + + enum CharacterType: String { + case uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + case lowercase = "abcdefghijklmnopqrstuvwxyz" + case numbers = "0123456789" + case symbols = "!@#$%^&*()+_-=}{[]|:;\"/?.><,`~" + } + + enum SeparatorType: String { + case hyphen = "-" + case underscore = "_" + case space = " " + case slash = "/" + case verticalBar = "|" + } + + public func generate( + type: PasswordType? = nil, + characters: Set? = nil + ) -> String { + + var passwordLength = Defaults.length + + var separatorIndices: [Int] = [] + var separatorCharacter = Defaults.separator.rawValue + + let typeOption = type ?? Defaults.type + switch typeOption { + case .normal(let length): + passwordLength = length + + case .separated(let wordLength, let wordCount, let separator): + let separatorCount = wordCount - 1 + passwordLength = (wordLength * wordCount) + (separatorCount) + + separatorIndices = (0.. Bool { + let typeCharacterSet = CharacterSet(charactersIn: type.rawValue) + let passwordCharacterSet = CharacterSet(charactersIn: password) + return passwordCharacterSet.isSubset(of: typeCharacterSet) + + } + + private func lengthWithSeparator(wordLength: Int, wordCount: Int) -> Int { + (wordLength * wordCount) + (wordCount - 1) + } + + private func checkIfSeparator(_ password: String, index: Int, separator: Character) -> Bool { + let char = password[password.index(password.startIndex, offsetBy: index)] + return char == separator + } +}