|
536 | 536 | let result = await simplyDataApi.deleteAccount(deleteAccountParams); |
537 | 537 | return result; |
538 | 538 | }, |
| 539 | + "getPasswordEntropy" : function(password) { |
| 540 | + let base = simplyApp.actions.getPasswordEntropyBase(password); |
| 541 | + let length = simplyApp.actions.getPasswordEntropyLength(password); |
| 542 | + let decimalPlaces = 2; |
| 543 | + return Math.log(Math.pow(base, length)).toFixed(decimalPlaces); |
| 544 | + }, |
| 545 | + "getPasswordEntropyBase" : function(password) { |
| 546 | + /** |
| 547 | + * Get the base amount of characters from the characters used in the password. |
| 548 | + * This is the number of possible characters to pick from in the used character sets |
| 549 | + * i.e. 26 for only lower case passwords |
| 550 | + */ |
| 551 | + let specialCharacters = ' !"#$%&\'()*+,-./:;<=>?@[\]^_{|}~'; |
| 552 | + let lowerCharacters = 'abcdefghijklmnopqrstuvwxyz'; |
| 553 | + let upperCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
| 554 | + let digitCharacters = '0123456789'; |
| 555 | + |
| 556 | + let hasSpecial = false; |
| 557 | + let hasLower = false; |
| 558 | + let hasUpper = false; |
| 559 | + let hasDigits = false; |
| 560 | + |
| 561 | + let base = 0; |
| 562 | + for (let i=0; i<password.length; i++) { |
| 563 | + if (!hasSpecial && (specialCharacters.indexOf(password[i]) !== -1)) { |
| 564 | + hasSpecial = true; |
| 565 | + base += specialCharacters.length; |
| 566 | + } |
| 567 | + if (!hasLower && (lowerCharacters.indexOf(password[i]) !== -1)) { |
| 568 | + hasLower = true; |
| 569 | + base += lowerCharacters.length; |
| 570 | + } |
| 571 | + if (!hasUpper && (upperCharacters.indexOf(password[i]) !== -1)) { |
| 572 | + hasUpper = true; |
| 573 | + base += upperCharacters.length; |
| 574 | + } |
| 575 | + if (!hasDigits && (digitCharacters.indexOf(password[i]) !== -1)) { |
| 576 | + hasDigits = true; |
| 577 | + base += digitCharacters.length; |
| 578 | + } |
| 579 | + if ( |
| 580 | + (specialCharacters.indexOf(password[i]) === -1) && |
| 581 | + (lowerCharacters.indexOf(password[i]) === -1) && |
| 582 | + (upperCharacters.indexOf(password[i]) === -1) && |
| 583 | + (digitCharacters.indexOf(password[i]) === -1) |
| 584 | + ) { |
| 585 | + base++; |
| 586 | + } |
| 587 | + } |
| 588 | + return base; |
| 589 | + }, |
| 590 | + "getPasswordEntropyLength" : function (password) { |
| 591 | + /** |
| 592 | + * Check the length of the password based on known rules |
| 593 | + * Characters will only be counted a maximum of 2 times e.g. aaa has length 2 |
| 594 | + */ |
| 595 | + let maxOccurances = 2; |
| 596 | + let usedCharacters = {}; |
| 597 | + let length = 0; |
| 598 | + |
| 599 | + for (let i=0; i<password.length; i++) { |
| 600 | + if (typeof (usedCharacters[password[i]]) === 'undefined') { |
| 601 | + length++; |
| 602 | + usedCharacters[password[i]] = 1; |
| 603 | + } else if (usedCharacters[password[i]] < maxOccurances) { |
| 604 | + length++; |
| 605 | + usedCharacters[password[i]]++; |
| 606 | + } |
| 607 | + } |
| 608 | + return length; |
| 609 | + }, |
| 610 | + "validatePasswordEntropy" : function(password) { |
| 611 | + let minimumEntropy = 30; |
| 612 | + return simplyApp.actions.getPasswordEntropy(password) > minimumEntropy; |
| 613 | + }, |
539 | 614 | "register" : async function() { |
540 | 615 | let registerParams = editor.pageData.register; |
541 | 616 | registerParams['repeat_password'] = registerParams['password']; |
|
612 | 687 | simplyApp.commands.autofocus(); |
613 | 688 | }, |
614 | 689 | "registerVerify" : function(el) { |
| 690 | + let password = el.querySelector("input[type=password]"); |
| 691 | + let entropyValid = simplyApp.actions.validatePasswordEntropy(password.value); |
| 692 | + if (!entropyValid) { |
| 693 | + return; |
| 694 | + } |
615 | 695 | simplyApp.actions.verifyEmail() |
616 | 696 | .then(function() { |
617 | 697 | document.location.hash="#register-verify"; |
@@ -915,7 +995,7 @@ <h1>Registreren</h1> |
915 | 995 | <form class="solid-form" data-simply-command="registerVerify" action="#"> |
916 | 996 | <p>Kies je wachtwoord</p> |
917 | 997 | <input type="hidden" data-simply-field="register.email"> |
918 | | - <input autofocus class="solid-input" data-simply-field="register.password" type="password" placeholder="Wachtwoord" required> |
| 998 | + <input data-simply-transformer="validateEntropy" autofocus class="solid-input" data-simply-field="register.password" type="password" placeholder="Wachtwoord" required> |
919 | 999 | <button class="solid-button solid-button-primary">Opslaan</button> |
920 | 1000 | </form> |
921 | 1001 | </section> |
@@ -1190,6 +1270,24 @@ <h1>Je bent uitgelogd.</h1> |
1190 | 1270 | <script> |
1191 | 1271 | /* Transformers */ |
1192 | 1272 | editor.transformers = { |
| 1273 | + "validateEntropy" : { |
| 1274 | + render : function(data) { |
| 1275 | + if (!this.entropyChecker) { |
| 1276 | + this.entropyChecker = this.addEventListener("input", function() { |
| 1277 | + let entropyValid = simplyApp.actions.validatePasswordEntropy(this.value); |
| 1278 | + if (!entropyValid) { |
| 1279 | + this.setCustomValidity("Maak een sterk wachtwoord. Gebruik meer verschillende en speciale tekens."); |
| 1280 | + } else { |
| 1281 | + this.setCustomValidity(""); |
| 1282 | + } |
| 1283 | + }); |
| 1284 | + } |
| 1285 | + return data; |
| 1286 | + }, |
| 1287 | + extract : function(data) { |
| 1288 | + return data; |
| 1289 | + } |
| 1290 | + }, |
1193 | 1291 | "appOrigin" : { |
1194 | 1292 | render : function(data) { |
1195 | 1293 | this.originalData = data; |
|
0 commit comments