ngx-pwd-strength
Version:
Angular Package, that measure password strength and indicate how secure is it
260 lines (252 loc) • 14.8 kB
JavaScript
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>⚠</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