UNPKG

ngx-pwd-strength

Version:

Angular Package, that measure password strength and indicate how secure is it

260 lines (252 loc) 14.8 kB
import * as i0 from '@angular/core'; import { Injectable, Component, Input, HostBinding, Directive, HostListener, NgModule } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { zxcvbn } from 'zxcvbn3'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; class NgxPwdStrengthService { constructor() { this._options = { enableFeedback: true }; this.score = new BehaviorSubject(null); this.updatedScore$ = this.score.asObservable(); } updateScore(data) { this.score.next(data); } init(options) { this._options = options; } /** * Score: * 0 # too guessable: risky password. (guesses < 10^3) * 1 # very guessable: protection from throttled online attacks. (guesses < 10^6) * 2 # somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8) * 3 # safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10) * 4 # very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10) * @param password */ getScore(password) { const result = zxcvbn(password); return this._options.enableFeedback ? { score: result.score, feedback: result.feedback } : { score: result.score }; } } NgxPwdStrengthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); NgxPwdStrengthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthService, decorators: [{ type: Injectable }] }); class NgxPwdStrengthComponent { constructor(ngxPwdStrengthService, elementRef) { this.ngxPwdStrengthService = ngxPwdStrengthService; this.elementRef = elementRef; this.display = false; this.pwdScore = null; this.popupOffset = 5; this.popupPosition = "bottom"; } ngOnInit() { this.subscription = this.ngxPwdStrengthService.updatedScore$.subscribe(data => { this.pwdScore = data; }); } set show(value) { if (value) { this.setHostPosition(this.popupPosition); } this.display = value; } get show() { return this.display; } get element() { return this.data.element; } get elementPosition() { return this.data.elementPosition; } setHostPosition(position) { const isSvg = this.element instanceof SVGElement; const popup = this.elementRef.nativeElement; const isCustomPosition = !this.elementPosition.right; let elementHeight = isSvg ? this.element.getBoundingClientRect().height : this.element.offsetHeight; let elementWidth = isSvg ? this.element.getBoundingClientRect().width : this.element.offsetWidth; const popupHeight = popup.clientHeight; const popupWidth = popup.clientWidth; const scrollY = window.pageYOffset; if (isCustomPosition) { elementHeight = 0; elementWidth = 0; } let topStyle; let leftStyle; switch (position) { case "top": topStyle = (this.elementPosition.top + scrollY) - (popupHeight + this.popupOffset); leftStyle = this.elementPosition.left; break; case "bottom": topStyle = (this.elementPosition.top + scrollY) + elementHeight + this.popupOffset; leftStyle = this.elementPosition.left; break; case "left": leftStyle = this.elementPosition.left - popupWidth - this.popupOffset; topStyle = (this.elementPosition.top + scrollY); break; case "right": leftStyle = this.elementPosition.left + elementWidth + this.popupOffset; topStyle = (this.elementPosition.top + scrollY); } this.hostStyleTop = topStyle + "px"; this.hostStyleLeft = leftStyle + "px"; this.hostStyleWidth = this.elementPosition.width + "px"; } ngOnDestroy() { this.subscription.unsubscribe(); } } NgxPwdStrengthComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthComponent, deps: [{ token: NgxPwdStrengthService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); NgxPwdStrengthComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.9", type: NgxPwdStrengthComponent, selector: "lib-ngx-pwd-strength", inputs: { data: "data", show: "show" }, host: { properties: { "style.top": "this.hostStyleTop", "style.left": "this.hostStyleLeft", "style.width": "this.hostStyleWidth" }, classAttribute: "ngx-pwd-strength-popup" }, ngImport: i0, template: "<div class=\"pwd-popup\">\r\n <div class=\"pwd-strength\">\r\n <div class=\"pwd-strength-fill\" [attr.data-score]=\"pwdScore?.score\"></div>\r\n </div>\r\n <ng-container *ngIf=\"pwdScore?.feedback\">\r\n <p class=\"password-feedback\" *ngIf=\"pwdScore?.feedback?.warning\">\r\n <span>&#9888;</span> {{pwdScore?.feedback?.warning}}\r\n </p>\r\n <ul class=\"password-suggetion\" *ngIf=\"pwdScore?.feedback?.suggestions\">\r\n <li *ngFor=\"let suggetion of pwdScore?.feedback?.suggestions\">{{suggetion}}</li>\r\n </ul>\r\n </ng-container>\r\n</div>\r\n\r\n", styles: [":host{background-color:#fff;color:#000;text-align:left;border-radius:2px;position:absolute;pointer-events:none;padding:10px;z-index:1000;display:block;transition:opacity .3s;opacity:1;top:0;left:0;transition:opacity .3s ease-in-out;box-shadow:0 1px 3px #0006;font-family:-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength{position:relative;height:3px;background:#d3d3d3;margin:10px auto}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength:before,:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength:after{content:\"\";height:inherit;background:transparent;display:block;border-color:#fff;border-style:solid;border-width:0 5px 0 5px;position:absolute;width:calc((100% - 20px) / 5);z-index:10}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength:before{left:calc((100% - 20px) / 5)}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength:after{right:calc((100% - 20px) / 5)}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength-fill{background:transparent;height:inherit;position:absolute;width:0;border-radius:inherit;transition:width .5s ease-in-out,background .25s}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength-fill[data-score=\"0\"]{background:darkred;width:20%}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength-fill[data-score=\"1\"]{background:orangered;width:40%}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength-fill[data-score=\"2\"]{background:orange;width:60%}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength-fill[data-score=\"3\"]{background:yellowgreen;width:80%}:host.ngx-pwd-strength-popup .pwd-popup .pwd-strength-fill[data-score=\"4\"]{background:green;width:100%}:host.ngx-pwd-strength-popup .pwd-popup .password-feedback,:host.ngx-pwd-strength-popup .pwd-popup .password-suggetion{font-size:80%;font-weight:400;display:block;margin-top:.25rem}:host.ngx-pwd-strength-popup .pwd-popup .password-suggetion{color:#6e757d!important}:host.ngx-pwd-strength-popup .pwd-popup .password-feedback{color:orange!important}:host ul{padding-left:14px;line-height:17px}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthComponent, decorators: [{ type: Component, args: [{ selector: 'lib-ngx-pwd-strength', templateUrl: './lib-ngx-pwd-strength.component.html', host: { class: "ngx-pwd-strength-popup" }, styleUrls: [ './lib-ngx-pwd-strength.component.scss' ] }] }], ctorParameters: function () { return [{ type: NgxPwdStrengthService }, { type: i0.ElementRef }]; }, propDecorators: { data: [{ type: Input }], hostStyleTop: [{ type: HostBinding, args: ["style.top"] }], hostStyleLeft: [{ type: HostBinding, args: ["style.left"] }], hostStyleWidth: [{ type: HostBinding, args: ["style.width"] }], show: [{ type: Input }] } }); class NgxPwdStrengthDirective { constructor(ngxPwdStrengthService, elementRef, componentFactoryResolver, appRef, injector) { this.ngxPwdStrengthService = ngxPwdStrengthService; this.elementRef = elementRef; this.componentFactoryResolver = componentFactoryResolver; this.appRef = appRef; this.injector = injector; } get isPopupDestroyed() { return this.componentRef && this.componentRef.hostView.destroyed; } getHostPosition() { this.hostPosition = this.elementRef.nativeElement.getBoundingClientRect(); } onMouseEnter(value) { this.displayPopup(); this.ratePassword(value); } onInput(value) { this.ratePassword(value); } onMouseLeave() { this.destroyPopup(); } ratePassword(password) { if (password) { let score = this.ngxPwdStrengthService.getScore(password); this.ngxPwdStrengthService.updateScore(score); } else { this.ngxPwdStrengthService.updateScore(null); } } displayPopup() { if (!this.componentRef || this.isPopupDestroyed) { this.buildPopup(); } } buildPopup() { this.getHostPosition(); this.loadComponent(NgxPwdStrengthComponent); } loadComponent(component) { this.componentRef = this.componentFactoryResolver .resolveComponentFactory(component) .create(this.injector); const hostComponent = this.componentRef.instance; hostComponent.data = { element: this.elementRef.nativeElement, elementPosition: this.hostPosition }; this.appRef.attachView(this.componentRef.hostView); const domElem = this.componentRef.hostView.rootNodes[0]; document.body.appendChild(domElem); hostComponent.show = true; } destroyPopup() { if (!this.isPopupDestroyed) { this.componentRef.instance.show = false; if (!this.componentRef || this.isPopupDestroyed) { return; } this.appRef.detachView(this.componentRef.hostView); this.componentRef.destroy(); } } } NgxPwdStrengthDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthDirective, deps: [{ token: NgxPwdStrengthService }, { token: i0.ElementRef }, { token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive }); NgxPwdStrengthDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.9", type: NgxPwdStrengthDirective, selector: "input[type=password][ngxPwdStrength]", host: { listeners: { "focusin": "onMouseEnter($event.target.value)", "input": "onInput($event.target.value)", "focusout": "onMouseLeave()" } }, exportAs: ["ngxPwdStrength"], ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthDirective, decorators: [{ type: Directive, args: [{ selector: 'input[type=password][ngxPwdStrength]', exportAs: 'ngxPwdStrength' }] }], ctorParameters: function () { return [{ type: NgxPwdStrengthService }, { type: i0.ElementRef }, { type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }]; }, propDecorators: { onMouseEnter: [{ type: HostListener, args: ["focusin", ["$event.target.value"]] }], onInput: [{ type: HostListener, args: ["input", ["$event.target.value"]] }], onMouseLeave: [{ type: HostListener, args: ["focusout"] }] } }); class NgxPwdStrengthModule { } NgxPwdStrengthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); NgxPwdStrengthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthModule, declarations: [NgxPwdStrengthComponent, NgxPwdStrengthDirective], imports: [CommonModule], exports: [NgxPwdStrengthDirective] }); NgxPwdStrengthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthModule, providers: [NgxPwdStrengthService], imports: [[ CommonModule ]] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.9", ngImport: i0, type: NgxPwdStrengthModule, decorators: [{ type: NgModule, args: [{ declarations: [ NgxPwdStrengthComponent, NgxPwdStrengthDirective ], imports: [ CommonModule ], exports: [ NgxPwdStrengthDirective ], providers: [NgxPwdStrengthService], entryComponents: [ NgxPwdStrengthComponent ] }] }] }); /* * Public API Surface of ngx-pwd-strength */ /** * Generated bundle index. Do not edit. */ export { NgxPwdStrengthComponent, NgxPwdStrengthDirective, NgxPwdStrengthModule, NgxPwdStrengthService }; //# sourceMappingURL=ngx-pwd-strength.js.map