diff --git a/README.md b/README.md index d8d9547..326d4a5 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,15 @@ string password = generator.Generate(16); Console.WriteLine(password); // Example output: kAj79uV@E?m7_8eS ``` +### Using WithDefaults +Quickly generate a password using default pools: +```csharp +PasswordSettings settings = PasswordSettings.WithDefaults(minLower: 2, minUpper: 2, minDigits: 2, minSpecial: 1); +PasswordGenerator generator = new(settings); + +string password = generator.Generate(12); +``` + ## Additional Methods ### `GenerateRandomLength(int minPasswordLength, int maxPasswordLength)` diff --git a/src/KPasswordGenerator.Tests/PasswordSettingsTests.cs b/src/KPasswordGenerator.Tests/PasswordSettingsTests.cs new file mode 100644 index 0000000..506c87b --- /dev/null +++ b/src/KPasswordGenerator.Tests/PasswordSettingsTests.cs @@ -0,0 +1,46 @@ +namespace KPasswordGenerator.Tests; + +public class PasswordSettingsTests +{ + [Fact] + public void WithDefaults_UsesExpectedDefaults() + { + var settings = PasswordSettings.WithDefaults(); + + Assert.Equal(4, settings.CharacterRequirements.Count); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == 1 && r.CharacterPool == CharacterPools.LowerCase); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == 1 && r.CharacterPool == CharacterPools.UpperCase); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == 1 && r.CharacterPool == CharacterPools.Digits); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == 1 && r.CharacterPool == CharacterPools.Special); + } + + [Fact] + public void WithDefaults_AllZero_ReturnsEmptyRequirements() + { + var settings = PasswordSettings.WithDefaults(0, 0, 0, 0); + + Assert.Empty(settings.CharacterRequirements); + } + + [Fact] + public void WithDefaults_CreatesRequirementsWithCorrectValues() + { + int lower = 2, upper = 3, digits = 4, special = 5; + + var settings = PasswordSettings.WithDefaults(lower, upper, digits, special); + + Assert.Equal(4, settings.CharacterRequirements.Count); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == lower && r.CharacterPool == CharacterPools.LowerCase); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == upper && r.CharacterPool == CharacterPools.UpperCase); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == digits && r.CharacterPool == CharacterPools.Digits); + Assert.Contains(settings.CharacterRequirements, r => + r.MinRequired == special && r.CharacterPool == CharacterPools.Special); + } +} \ No newline at end of file diff --git a/src/KPasswordGenerator/CharacterPools.cs b/src/KPasswordGenerator/CharacterPools.cs index afcb516..5413055 100644 --- a/src/KPasswordGenerator/CharacterPools.cs +++ b/src/KPasswordGenerator/CharacterPools.cs @@ -6,5 +6,7 @@ public static class CharacterPools public const string UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public const string Digits = "0123456789"; + public const string Special = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; } \ No newline at end of file diff --git a/src/KPasswordGenerator/PasswordGenerator.cs b/src/KPasswordGenerator/PasswordGenerator.cs index 0feb73c..1fb80b8 100644 --- a/src/KPasswordGenerator/PasswordGenerator.cs +++ b/src/KPasswordGenerator/PasswordGenerator.cs @@ -1,4 +1,4 @@ -using System.Security.Cryptography; +using System.Security.Cryptography; namespace KPasswordGenerator; @@ -53,9 +53,17 @@ public bool Validate(string password) foreach (var requirement in _passwordSettings.CharacterRequirements) { - int count = password.Count(requirement.CharacterPool.Contains); + int count = 0; - if (count < requirement.MinRequired) return false; + for (int i = 0; i < password.Length && count < requirement.MinRequired; i++) + { + if (requirement.CharacterPool.Contains(password[i])) + { + count++; + } + } + + if (count != requirement.MinRequired) return false; } return true; diff --git a/src/KPasswordGenerator/PasswordSettings.cs b/src/KPasswordGenerator/PasswordSettings.cs index 8a26fc1..5c0fc5f 100644 --- a/src/KPasswordGenerator/PasswordSettings.cs +++ b/src/KPasswordGenerator/PasswordSettings.cs @@ -16,4 +16,23 @@ public PasswordSettings(ICollection characterRequirements) } public ICollection CharacterRequirements { get; } + + public static PasswordSettings WithDefaults(int minLower = 1, int minUpper = 1, int minDigits = 1, int minSpecial = 1) + { + List requirements = []; + + if (minLower > 0) + requirements.Add(new CharacterRequirement(minLower, CharacterPools.LowerCase)); + + if (minUpper > 0) + requirements.Add(new CharacterRequirement(minUpper, CharacterPools.UpperCase)); + + if (minDigits > 0) + requirements.Add(new CharacterRequirement(minDigits, CharacterPools.Digits)); + + if (minSpecial > 0) + requirements.Add(new CharacterRequirement(minSpecial, CharacterPools.Special)); + + return new PasswordSettings(requirements); + } } \ No newline at end of file