Problems Making A Password Generator
Published: 2020-09-27 16:09:47

**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:

```javascript
const alphabet = ['a','b','c','d','e','f']
```

...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:

```javascript
alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
```

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

```javascript
Array(26) [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", … ] 
```

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](https://pbs.twimg.com/media/EhgM_ThX0AMyILk?format=png&name=900x900)

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. 

```javascript
output.innerHTML = hereIsYourPassword;
```

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:

```javascript
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();
  }
}
```

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:

```javascript
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);
}
```

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.