2021-05-03 09:25:42 +01:00
|
|
|
import { CopyableInputBox } from "../elements/CopyableInputBox.js";
|
2021-05-07 15:11:10 +01:00
|
|
|
import { Margin } from "../elements/Margin.js";
|
2021-04-15 13:01:58 +01:00
|
|
|
import { Page } from "../types/Page.js";
|
|
|
|
import { makeElement } from "../htmlUtils.js";
|
2021-05-03 09:25:42 +01:00
|
|
|
import { setPageContent } from "../pageUtils.js";
|
2021-04-20 20:19:34 +01:00
|
|
|
import i18next from 'i18next';
|
|
|
|
|
2021-05-07 15:11:10 +01:00
|
|
|
const passwordLengthMin = 1;
|
|
|
|
const passwordLengthMax = 64;
|
|
|
|
const passwordLengthDefault = 24;
|
2021-04-15 13:01:58 +01:00
|
|
|
|
2021-05-07 15:11:10 +01:00
|
|
|
function random() {
|
|
|
|
if (typeof window.crypto?.getRandomValues === 'function' && typeof window.Uint32Array === 'function') {
|
2021-04-15 15:37:52 +01:00
|
|
|
return window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295;
|
|
|
|
}
|
2021-04-15 13:01:58 +01:00
|
|
|
|
2021-04-15 15:37:52 +01:00
|
|
|
return Math.random();
|
2021-04-15 13:01:58 +01:00
|
|
|
}
|
|
|
|
|
2021-05-07 15:47:13 +01:00
|
|
|
const lowerCase = 'abcdefghijklmnopqrstuvwxyz';
|
|
|
|
const upperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
|
|
const numbers = '1234567890';
|
|
|
|
const special = '!#$%&()*+,-./:;<=>?@[]^_{|}~';
|
|
|
|
|
|
|
|
const alphabets = {
|
|
|
|
SECURE: lowerCase + upperCase + numbers + special,
|
|
|
|
SMOL: lowerCase + numbers,
|
|
|
|
HEX: '123456789ABCDEF',
|
|
|
|
}
|
|
|
|
|
2021-05-07 15:11:10 +01:00
|
|
|
const passwordOptionsDefault = {
|
2021-05-07 15:47:13 +01:00
|
|
|
length: passwordLengthDefault,
|
|
|
|
alphabet: alphabets.SECURE,
|
2021-05-07 15:11:10 +01:00
|
|
|
}
|
2021-04-15 13:01:58 +01:00
|
|
|
|
2021-05-07 15:11:10 +01:00
|
|
|
function genPassword(options = passwordOptionsDefault) {
|
2021-04-15 15:37:52 +01:00
|
|
|
let pw = "";
|
2021-05-07 15:47:13 +01:00
|
|
|
options = {...passwordOptionsDefault, ...options}
|
|
|
|
const pwArray = options.alphabet.split('');
|
2021-05-07 15:11:10 +01:00
|
|
|
for (let i = 0; i < options.length; i++) {
|
2021-04-15 15:37:52 +01:00
|
|
|
pw = pw.concat(pwArray[Math.floor(random() * pwArray.length)]);
|
|
|
|
}
|
|
|
|
return pw;
|
2021-04-15 13:01:58 +01:00
|
|
|
}
|
|
|
|
|
2021-05-07 15:47:13 +01:00
|
|
|
function Option(label, value) {
|
|
|
|
return makeElement({
|
|
|
|
tag: "option",
|
|
|
|
text: label,
|
|
|
|
attributes: {
|
|
|
|
label: label,
|
|
|
|
value: value,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-04-15 13:01:58 +01:00
|
|
|
|
|
|
|
export class PwGenPage extends Page {
|
2021-04-15 15:37:52 +01:00
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
}
|
2021-05-07 15:11:10 +01:00
|
|
|
|
|
|
|
|
2021-04-15 15:37:52 +01:00
|
|
|
async render() {
|
2021-05-07 15:58:45 +01:00
|
|
|
setPageContent("");
|
2021-05-07 15:11:10 +01:00
|
|
|
this.passwordBox = CopyableInputBox(genPassword(passwordOptionsDefault));
|
|
|
|
|
|
|
|
this.passwordLengthTitle = makeElement({
|
|
|
|
tag: "h4",
|
|
|
|
text: this.getPasswordLengthText()
|
|
|
|
})
|
|
|
|
|
|
|
|
this.passwordLengthRange = makeElement({
|
|
|
|
tag: "input",
|
|
|
|
name: "length",
|
2021-05-07 15:47:13 +01:00
|
|
|
class: ["uk-range", "uk-width-1-2"],
|
2021-05-07 15:11:10 +01:00
|
|
|
attributes: {
|
|
|
|
type: "range",
|
|
|
|
value: passwordLengthDefault,
|
|
|
|
max: passwordLengthMax,
|
|
|
|
min: passwordLengthMin,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
this.passwordLengthRange.addEventListener('input', this.updatePassword.bind(this));
|
|
|
|
|
2021-05-07 15:47:13 +01:00
|
|
|
this.passwordAlphabet = makeElement({
|
|
|
|
tag: "select",
|
|
|
|
class: ["uk-select", "uk-width-1-2"],
|
|
|
|
children: [
|
|
|
|
Option("a-z a-Z 0-9 specials", alphabets.SECURE),
|
|
|
|
Option("a-z 0-9", alphabets.SMOL),
|
|
|
|
Option("A-F 1-9", alphabets.HEX),
|
|
|
|
]
|
|
|
|
})
|
|
|
|
|
2021-05-07 15:11:10 +01:00
|
|
|
this.passwordForm = makeElement({
|
|
|
|
tag: "form",
|
2021-04-15 15:37:52 +01:00
|
|
|
children: [
|
2021-05-07 15:11:10 +01:00
|
|
|
this.passwordLengthTitle,
|
2021-05-07 15:47:13 +01:00
|
|
|
Margin(this.passwordLengthRange),
|
|
|
|
Margin(this.passwordAlphabet),
|
|
|
|
Margin(this.passwordBox),
|
2021-05-07 15:11:10 +01:00
|
|
|
Margin(makeElement({
|
2021-04-15 15:37:52 +01:00
|
|
|
tag: "button",
|
2021-04-20 20:19:34 +01:00
|
|
|
text: i18next.t("gen_password_btn"),
|
2021-04-15 15:37:52 +01:00
|
|
|
class: ["uk-button", "uk-button-primary", "uk-margin-bottom"],
|
2021-05-07 15:11:10 +01:00
|
|
|
attributes: {type: "submit"},
|
|
|
|
}))
|
2021-04-15 15:37:52 +01:00
|
|
|
]
|
2021-05-07 15:11:10 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
this.passwordForm.addEventListener("submit", (e) => this.formEvent(e));
|
|
|
|
setPageContent(this.passwordForm);
|
|
|
|
}
|
|
|
|
|
|
|
|
getPasswordLengthText() {
|
|
|
|
return i18next.t("password_length_title", {
|
|
|
|
min: this?.passwordLengthRange?.value || 24,
|
|
|
|
max: passwordLengthMax
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
formEvent(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.updatePassword();
|
|
|
|
}
|
|
|
|
|
|
|
|
updatePassword() {
|
|
|
|
this.passwordLengthTitle.innerText = this.getPasswordLengthText();
|
2021-05-07 15:47:13 +01:00
|
|
|
this.passwordBox.setText(genPassword({
|
|
|
|
length: this.passwordLengthRange.value,
|
|
|
|
alphabet: this.passwordAlphabet.value,
|
|
|
|
}));
|
2021-04-15 15:37:52 +01:00
|
|
|
}
|
|
|
|
|
2021-05-07 15:58:45 +01:00
|
|
|
cleanup() {
|
|
|
|
this.passwordBox = undefined;
|
|
|
|
this.passwordLengthTitle = undefined;
|
|
|
|
this.passwordLengthRange = undefined;
|
|
|
|
this.passwordAlphabet = undefined;
|
|
|
|
this.passwordForm = undefined;
|
|
|
|
}
|
|
|
|
|
2021-04-15 15:37:52 +01:00
|
|
|
get name() {
|
2021-04-20 20:19:34 +01:00
|
|
|
return i18next.t("password_generator_title");
|
2021-04-15 15:37:52 +01:00
|
|
|
}
|
2021-04-15 13:01:58 +01:00
|
|
|
}
|