// ============================================================================= // Accounts Scripts // (c) Mathigon // ============================================================================= import {$, CustomElementView, FormView, InputView, observe, register, Router} from '@mathigon/boost'; import './main'; // ----------------------------------------------------------------------------- // Password Component const combinations = ['abcdefghijklmnopqrstuvwxyz', 'qwertyuiopasdfghjklzxcvbnm', '01234567890']; for (let i = 0; i < 2; ++i) combinations.push(combinations[i].toUpperCase()); for (let i = 0; i < 5; ++i) { combinations.push(combinations[i].split('').reverse().join('')); } function passwordStrength(q = '') { if (q.length < 5) return 'Too Short'; let p = q.replace(/(.)\1*/, function(x, y) { return y; }); // repetitions p = p.replace(/password/gi, 'p').replace(/mathigon/gi, 'm'); for (const s of combinations) { for (let i = 0; i < s.length - 1; ++i) { for (let j = Math.min(p.length, s.length - i); j > 2; --j) { const sub = s.substr(i, j); p = p.replace(sub, sub[0] + sub[1]); } } } let space = 0; if (q.match(/[0-9]/)) space += 10; if (q.match(/[a-z]/)) space += 26; if (q.match(/[A-Z]/)) space += 26; if (q.match(/[^0-9a-zA-Z]/)) space += 10; const score = p.length * Math.log(space); if (score < 30) return 'Weak'; if (score < 50) return 'OK'; return 'Strong'; } const template = ` Password (\${strength})
`; @register('x-password', {template}) export class Password extends CustomElementView { ready() { this.bindModel(observe({strength: '', reveal: false})); this.$('.toggle')!.on('click', () => this.model.reveal = !this.model.reveal); this.$('input')!.change((value) => { this.model.strength = value ? passwordStrength(value) : ''; this.$('input')!.setValidity(value.length < 5 ? 'Please pick a longer password.' : ''); }); } } // ----------------------------------------------------------------------------- // Routes Router.setup({ $viewport: $('main')!, preloaded: true, click: true, history: true, initialise: ($el) => { for (const $form of $el.$$('form') as FormView[]) { $form.on('submit', (e: Event) => { if (!$form.isValid) { e.preventDefault(); return false; } }); } for (const $i of $el.$$('.form-field input')) { $i.on('blur invalid valid', () => $i.addClass('dirty')); } for (const $a of $el.$$('.alert')) { $a.$('.close')!.on('click', () => $a.remove()); } } }); Router.view('/signup', { enter($el) { const $bday = $el.$('input[name="birthday"]') as InputView; $bday.change((date) => { const age = (Date.now() - (+new Date(date))) / (1000 * 60 * 60 * 24 * 365); if (age < 0 || age > 100) return $bday.setValidity('Please enter a valid date of birth.'); if (age < 13) return $bday.setValidity('You have to be at least 13 years old to create an account.'); $bday.setValidity(''); }); } }); Router.paths('/login', '/forgot', '/reset', '/reset/:token', '/profile');