Struggling to generate new password when user clicks on button.

Hi everyone! I have my code running properly, but I'm stuck on how to generate a NEW password when once the user clicks generate password the second time. Currently everytime a user clicks generate password it increments each times and messes up the format. I'm missing the next step of the logic to correct this. https://codepen.io/ezekielswanson/pen/ExegrxB
10 Replies
aevitas
aevitas•2y ago
const resetPassword = () => {
if (passwordOne.length !== 0 || passwordTwo.length !== 0) {
passwordOne = '';
passwordTwo = '';
}
}

generator.addEventListener('click', function() {
resetPassword();
generatePassword();
});
const resetPassword = () => {
if (passwordOne.length !== 0 || passwordTwo.length !== 0) {
passwordOne = '';
passwordTwo = '';
}
}

generator.addEventListener('click', function() {
resetPassword();
generatePassword();
});
Something like this? Should probably reset both the variables before generating again Actually above supplied code works in the codepen (I am surprised, I am no wizard in JS)
generator.addEventListener('click', function() {
if (passwordOne.length !== 0 || passwordTwo.length !== 0) {
passwordOne = '';
passwordTwo = '';
}
generatePassword()

});
generator.addEventListener('click', function() {
if (passwordOne.length !== 0 || passwordTwo.length !== 0) {
passwordOne = '';
passwordTwo = '';
}
generatePassword()

});
This works too, but I usually try to keep eventListeners with only functions
zekeswanson
zekeswansonOP•2y ago
Thank you so much for taking time out to answer my question 🙂 This was really helpful!
aevitas
aevitas•2y ago
No worries , glad I could help!
13eck
13eck•2y ago
Here's my take on it:
// have the length be passed into the function
// so you don't need to have a global variable
function generatePassword(pwLen = 15) {
// We're creating a new array each time with
// the provided length, then mapping over it
// to fill it with random characters. The `.join("")
// method is making it a string

const passwordOne = Array.from({length: pwLen }).map(() => randomCharacters()).join("");
const passwordTwo = Array.from({length: pwLen }).map(() => randomCharacters()).join("");

// here we simply set the content
passwordDisplayOne.textContent = passwordOne;
passwordDisplayTwo.textContent = passwordTwo;
}
// have the length be passed into the function
// so you don't need to have a global variable
function generatePassword(pwLen = 15) {
// We're creating a new array each time with
// the provided length, then mapping over it
// to fill it with random characters. The `.join("")
// method is making it a string

const passwordOne = Array.from({length: pwLen }).map(() => randomCharacters()).join("");
const passwordTwo = Array.from({length: pwLen }).map(() => randomCharacters()).join("");

// here we simply set the content
passwordDisplayOne.textContent = passwordOne;
passwordDisplayTwo.textContent = passwordTwo;
}
With this method there is no reused string so you don't have to worry about ever-increasing length or about resetting since it's all encapsulated in the function.
aevitas
aevitas•2y ago
And this is the kind of answer I wouldn't be able to think of 😄
13eck
13eck•2y ago
Also, I hope that this is just a fun hobby thing for you and you don't expect to actually use it to generate passwords. Math.random() is not cryptographically secure. If you want cryptographically secure random numbers you'll want to use crypto.getRandomValues(). Even then, .getRandomValues() only works on integers and not floats so you'll need to do some maths to convert the int to a float. For example, to get 5 cryptographically secure random numbers [0..1):
Array.from(crypto.getRandomValues(new Uint32Array(5))).map( n => n / Math.pow(2,32));
Array.from(crypto.getRandomValues(new Uint32Array(5))).map( n => n / Math.pow(2,32));
This creates a Uint32Array and fills it with cryptographically secure random numbers (but it's an unsigned int, so [0..2^32 -1] ). I then divided it by the max of a uint32, which gives us a rang of zero to not one
aevitas
aevitas•2y ago
At least I felt smart for a few minutes 😉 Interesting, I did not know that.
13eck
13eck•2y ago
Math.random() is designed to be fast, not secure. Hell, when Math.random() was designed web browsers couldn't do cryptographically secure numbers If you're building a dice roller or other random generators for a game it's fine. But if you want to do secure numbers, you need to use crypto If you want to actually build something like this for production, I'd do some internet searching to find some open source and reviewed examples and check out their code
aevitas
aevitas•2y ago
Until now I didn't know crypto exists, will certainly look into it. Thanks for the info (i'm sure it'll help op as well)
13eck
13eck•2y ago
Also, I'm a newb when it comes to cryptographically secure random numbers. I believe my above formula works (the base is a secure random number so it should) but it's best to consult with real crypto people to verify. That all being said, here's a quick change to your code to use the cryptographically secure number:
function randomCharacters() {
const rand = crypto.getRandomValues(new Uint32Array(1))[0] / Math.pow(2,32);
const randomPassword = Math.floor( rand * characters.length);
return characters[randomPassword];
}
function randomCharacters() {
const rand = crypto.getRandomValues(new Uint32Array(1))[0] / Math.pow(2,32);
const randomPassword = Math.floor( rand * characters.length);
return characters[randomPassword];
}
You might see some noticeable performance slowdown with larger passwords as that's creating a new random number each time. If that's the case, doing a refactor where it gets all the random numbers it needs at once should show a noticeable improvement as it's only making one call to the browser's secure crypto source instead of 15+ calls. But performance optimizations can wait until they're needed :p
Want results from more Discord servers?
Add your server