DEV Community

Cover image for Problems Making A Password Generator
Danny
Danny

Posted on

Problems Making A Password Generator

27/09/2020

Introduction

This is just a quick post about a few of the problems I faced when I was making a password generator for my own records. You probably won’t find it helpful unless you’re making a password generator too.

The First Array

First things first, we’re going to need an array of letters for our password generator to select from. Let’s type that out:

const alphabet = ['a','b','c','d','e','f']
Enter fullscreen mode Exit fullscreen mode

...You gotta be kidding me. We’re about to die from boredom. We’ve typed 25 characters just to get 6 letters in our array. There’s got to be a better way than this. A quick Google search takes us to StackOverflow.com with this solution:

alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
Enter fullscreen mode Exit fullscreen mode

Let’s do console.log(alphabet) to see if it works:

Array(26) [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",  ] 
Enter fullscreen mode Exit fullscreen mode

Good stuff!

Debugging

Sometimes the generated password does not match the password length that the user entered. Here is a screenshot where the user asked for a password 6 characters long but the password generator only created one that was 3 characters long.

Screenshot showing incorrect password length

Why would it do that? How could our precious code that we gave life to, betray us and stab us in the back like that???

I wish I could say I was a genius that was able to find this bug instantly but I’m not. I did manage to narrow it down and discovered it was only happening when the user selected the “Include special characters” checkbox.

So out of desperation I started removing characters one by one from the special characters array, saving it, and generating a few passwords to see if it had magically fixed itself. And at one point it was magically fixed. Then it hit me. The ‘<’ and ‘>’ characters.

output.innerHTML = hereIsYourPassword;
Enter fullscreen mode Exit fullscreen mode

The password is displayed in a div called output using inner.HTML. This meant that if the password included those special characters, part of the password was being turned into HTML tags which would not be displayed in the output. Rookie mistake.

Refactoring 100 Million Else If Statements

The password generator ended up with 4 checkboxes. One for lower case letters, one for upper case letters, one for numbers and one for special characters. This resulted in approximately 100 million else if statements to cover every combination of checkbox that could be checked. Shown below:

function chooseFunction() {
  if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === false &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === false &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateBasicPassword();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === true &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateBasicPasswordWithSpecialSymbols();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === false &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateBasicPasswordWithNumbers();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === false &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateBasicPasswordWithUpperCase();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === true &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateBasicPasswordWithSpecialSymbolsAndNumbers();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === true &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateBasicPasswordWithSpecialSymbolsAndUpperCase();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === false &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateBasicPasswordWithNumbersAndUpperCase();
  } else if (
    includeLowerCase.checked === true &&
    includeSymbols.checked === true &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateBasicPasswordWithAllOptions();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === true &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateSpecialCharactersOnly();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === false &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateNumbersOnly();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === false &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateUpperCaseOnly();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === true &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === false
  ) {
    checkPasswordInput();
    generateSpecialSymbolsWithNumbers();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === true &&
    includeNumbers.checked === false &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateSpecialSymbolsWithUpperCase();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === true &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateSymbolsPasswordWithNumbersAndUpperCase();
  } else if (
    includeLowerCase.checked === false &&
    includeSymbols.checked === false &&
    includeNumbers.checked === true &&
    includeUpperCase.checked === true
  ) {
    checkPasswordInput();
    generateNumbersPasswordWithUpperCase();
  }
}
Enter fullscreen mode Exit fullscreen mode

The aspiring developer inside me was smart enough to realise “Hey! I don’t think this counts as good code man. Maybe you should ask someone that actually knows what they’re doing for help?”

So I asked for help on DThompsonDev’s Discord channel called Commit Your Code. The reply was to use 4 if statements and concatenate the arrays as needed. This changed the 100 million else if statements above to this:

function generateAllPasswords() {
  let finalArray = [];

  if (includeLowerCase.checked === true) {
    finalArray = finalArray.concat(alphabetLowerCase);
  }

  if (includeSymbols.checked === true) {
    finalArray = finalArray.concat(specialCharacters);
  }

  if (includeNumbers.checked === true) {
    finalArray = finalArray.concat(numbers);
  }

  if (includeUpperCase.checked === true) {
    finalArray = finalArray.concat(alphabetUpperCase);
  }

  checkPasswordInput();
  getCharacters(finalArray);
}
Enter fullscreen mode Exit fullscreen mode

I’ve never seen multiple if statements used in such a way one after the other. I've only ever seen 1 if statement or many else if statements. This refactoring also meant I could remove all the separate functions I had declared for each combination of checkbox and reduced it to a single function. The overall result was going from 605 lines of JavaScript down to 158.

Conclusion

Make sure you ask for help when needed. Going through every combination of checkbox took me ages. Then another person looked at the code for a few minutes and said “Try it this way.”

Well that’s about all of the problems I can remember since it’s been a couple of weeks since I made the password generator. Bye-bye.

Top comments (1)

Collapse
 
jamesbond96691 profile image
james bond

GENERA's 35 years of experience feriados en chilein the industry speaks to its deep understanding of the challenges faced by businesses when it comes to managing their workforce effectively.