Compare commits

..

7 commits

Author SHA1 Message Date
3b1ce9009a
Merge pull request #56 from wneessen/goreport_cleanup
GoReportCard cleanup
2024-03-14 23:00:32 +01:00
89a2a349ef
Fixed missing gofumpt for apg.go 2024-03-14 22:57:07 +01:00
4ee6b6651b
Refactor character counting logic in password validation
The repetitive code used for password character counting in different scenarios has been consolidated into a single function, matchesMinimumAmount(). This extraction simplifies the main function and makes the code more maintainable, while maintaining the functionality of checking whether the password meets certain character count criteria.
2024-03-14 22:54:36 +01:00
cc45ec1119
Reduce complexity in main() function 2024-03-14 22:45:20 +01:00
f153754dc4
Correct typo in test error message
The error message within the test case had a typographical error. The word "length" was incorrectly spelled as "lenght". This has been fixed to enhance the readability of the code.
2024-03-14 22:28:35 +01:00
da910fde14
Merge pull request #55 from wneessen/more_testcoverage
Add test for excluded characters in config
2024-03-14 21:46:48 +01:00
9bb78748be
Add test for excluded characters in config
A new unit test has been added to verify GetCharRangeFromConfig() function. The test ensures that the function properly excludes configured characters from the generated range.
2024-03-14 21:39:48 +01:00
3 changed files with 78 additions and 55 deletions

View file

@ -65,26 +65,8 @@ func main() {
}
// Old style character modes
if humanReadable {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeHumanReadable)
}
if lowerCase {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeLowerCase)
}
if upperCase {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeUpperCase)
}
if numeric {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeNumeric)
}
if special {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeSpecial)
}
if complexPass {
config.Mode = apg.MaskSetMode(config.Mode, apg.ModeLowerCase|apg.ModeNumeric|
apg.ModeSpecial|apg.ModeUpperCase)
config.Mode = apg.MaskClearMode(config.Mode, apg.ModeHumanReadable)
}
configOldStyle(config, humanReadable, lowerCase, upperCase, numeric,
special, complexPass)
// New style character modes (has higher priority than the old style modes)
if modeString != "" {
@ -93,6 +75,21 @@ func main() {
// For the "minimum amount of" modes we need to imply at the type
// of character mode is set
configMinRequirement(config)
// Check if algorithm is supported
config.Algorithm = apg.IntToAlgo(algorithm)
if config.Algorithm == apg.AlgoUnsupported {
_, _ = fmt.Fprintf(os.Stderr, "unsupported algorithm value: %d\n", algorithm)
os.Exit(1)
}
// Generate the password based on the given flags and print it to stdout
generate(config)
}
// configMinRequirement configures the "minimum amount" feature
func configMinRequirement(config *apg.Config) {
if config.MinLowerCase > 0 {
if float64(config.MinLength)/2 < float64(config.MinNumeric) {
_, _ = os.Stderr.WriteString(MinimumAmountTooHigh)
@ -117,15 +114,35 @@ func main() {
}
config.Mode = apg.MaskSetMode(config.Mode, apg.ModeUpperCase)
}
}
// Check if algorithm is supported
config.Algorithm = apg.IntToAlgo(algorithm)
if config.Algorithm == apg.AlgoUnsupported {
_, _ = fmt.Fprintf(os.Stderr, "unsupported algorithm value: %d\n", algorithm)
os.Exit(1)
// configOldStyle configures the old style character modes
func configOldStyle(config *apg.Config, humanReadable, lowerCase, upperCase,
numeric, special, complexPass bool,
) {
if humanReadable {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeHumanReadable)
}
if lowerCase {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeLowerCase)
}
if upperCase {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeUpperCase)
}
if numeric {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeNumeric)
}
if special {
config.Mode = apg.MaskToggleMode(config.Mode, apg.ModeSpecial)
}
if complexPass {
config.Mode = apg.MaskSetMode(config.Mode, apg.ModeLowerCase|apg.ModeNumeric|
apg.ModeSpecial|apg.ModeUpperCase)
config.Mode = apg.MaskClearMode(config.Mode, apg.ModeHumanReadable)
}
}
// Generate the password based on the given flags
func generate(config *apg.Config) {
generator := apg.New(config)
for i := int64(0); i < config.NumberPass; i++ {
password, err := generator.Generate()

View file

@ -229,13 +229,7 @@ func (g *Generator) checkMinimumRequirements(password string) bool {
charRange = CharRangeAlphaLower
}
count := 0
for _, char := range charRange {
count += strings.Count(password, string(char))
}
if int64(count) < g.config.MinLowerCase {
ok = false
}
matchesMinimumAmount(charRange, password, g.config.MinLowerCase, &ok)
}
if g.config.MinNumeric > 0 {
var charRange string
@ -246,13 +240,7 @@ func (g *Generator) checkMinimumRequirements(password string) bool {
charRange = CharRangeNumeric
}
count := 0
for _, char := range charRange {
count += strings.Count(password, string(char))
}
if int64(count) < g.config.MinNumeric {
ok = false
}
matchesMinimumAmount(charRange, password, g.config.MinNumeric, &ok)
}
if g.config.MinSpecial > 0 {
var charRange string
@ -263,13 +251,7 @@ func (g *Generator) checkMinimumRequirements(password string) bool {
charRange = CharRangeSpecial
}
count := 0
for _, char := range charRange {
count += strings.Count(password, string(char))
}
if int64(count) < g.config.MinSpecial {
ok = false
}
matchesMinimumAmount(charRange, password, g.config.MinSpecial, &ok)
}
if g.config.MinUpperCase > 0 {
var charRange string
@ -280,13 +262,7 @@ func (g *Generator) checkMinimumRequirements(password string) bool {
charRange = CharRangeAlphaUpper
}
count := 0
for _, char := range charRange {
count += strings.Count(password, string(char))
}
if int64(count) < g.config.MinUpperCase {
ok = false
}
matchesMinimumAmount(charRange, password, g.config.MinUpperCase, &ok)
}
return ok
}
@ -359,3 +335,16 @@ func (g *Generator) generateRandom() (string, error) {
return password, nil
}
// matchesMinimumAmount checks if the number of occurrences of characters in
// charRange in the password is less than minAmount and updates the
// value of ok accordingly.
func matchesMinimumAmount(charRange, password string, minAmount int64, ok *bool) {
count := 0
for _, char := range charRange {
count += strings.Count(password, string(char))
}
if int64(count) < minAmount {
*ok = false
}
}

View file

@ -98,7 +98,7 @@ func TestGenerator_RandomBytes(t *testing.T) {
}
bl := len(rb)
if int64(bl) != tc.l {
t.Errorf("lenght of provided bytes does not match requested length: got: %d, expected: %d",
t.Errorf("length of provided bytes does not match requested length: got: %d, expected: %d",
bl, tc.l)
}
if bytes.Equal(rb, make([]byte, tc.l)) {
@ -220,6 +220,23 @@ func TestGetCharRangeFromConfig(t *testing.T) {
}
}
func TestGetCharRangeFromConfig_ExcludeChar(t *testing.T) {
defaultConf := NewConfig()
defaultGen := New(defaultConf)
defaultRange := defaultGen.GetCharRangeFromConfig()
defaultRange = strings.ReplaceAll(defaultRange, "a", "")
defaultRange = strings.ReplaceAll(defaultRange, "b", "")
config := NewConfig(WithExcludeChars("ab"))
generator := New(config)
excludeRange := generator.GetCharRangeFromConfig()
if excludeRange != defaultRange {
t.Errorf("GetCharRangeFromConfig(WithExcludeChars()) failed. Expected"+
"char range: %s, got: %s", defaultRange, excludeRange)
}
}
func TestGetPasswordLength(t *testing.T) {
config := NewConfig()
generator := New(config)