مقياس قوة كلمة المرور - Password Strength Meter
قم بإنشاء مكون بالمحتويات التالية:
الـ HTML:
<input #poor type="hidden" [value]="'PWD_STRENGTH.POOR' | translate">
<input #notGood type="hidden" [value]="'PWD_STRENGTH.NOT_GOOD' | translate">
<input #average type="hidden" [value]="'PWD_STRENGTH.AVERAGE' | translate">
<input #good type="hidden" [value]="'PWD_STRENGTH.GOOD' | translate">
<div class="strength">
<ul class="strengthBar mt-2">
<li class="point" [style.background-color]="bar0"></li>
<li class="point" [style.background-color]="bar1"></li>
<li class="point" [style.background-color]="bar2"></li>
<li class="point" [style.background-color]="bar3"></li>
</ul>
<p class="text-center mb-0" [style.color]="messageColor" *ngIf="passwordToCheck?.length">{{ message }}</p>
</div>
الـ SCSS:
.strength {
display: flex;
flex-direction: row;
}
.strengthBar {
display: flex;
flex-grow: 1;
list-style: none;
margin: 0;
padding: 0;
vertical-align: 2px;
}
.point:last-of-type {
margin: 0 !important;
}
.point {
background: #ddd;
border-radius: 2px;
display: inline-block;
height: 5px;
margin-right: 1px;
flex-grow: 1;
}
p {
font-weight: bold;
flex-grow: 0.1;
}
الـ TS:
import { Component, ElementRef, EventEmitter, Input, OnChanges, Output, SimpleChange, ViewChild } from '@angular/core';
@Component({
selector: 'app-password-strength',
templateUrl: './password-strength.component.html',
styleUrls: ['./password-strength.component.scss']
})
export class PasswordStrengthComponent implements OnChanges {
@ViewChild('poor') poor: ElementRef<HTMLInputElement>;
@ViewChild('notGood') notGood: ElementRef<HTMLInputElement>;
@ViewChild('average') average: ElementRef<HTMLInputElement>;
@ViewChild('good') good: ElementRef<HTMLInputElement>;
bar0: string;
bar1: string;
bar2: string;
bar3: string;
@Input() public passwordToCheck: string;
@Output() passwordStrength = new EventEmitter<boolean>();
private colors = ['darkred', 'orangered', 'orange', 'yellowgreen'];
message: string;
messageColor: string;
checkStrength(password: string) {
// 1
let force = 0;
// 2
const regex = /[$-/:-?{-~!"^_@`\[\]]/g;
const lowerLetters = /[a-z]+/.test(password);
const upperLetters = /[A-Z]+/.test(password);
const numbers = /[0-9]+/.test(password);
const symbols = regex.test(password);
// 3
const flags = [lowerLetters, upperLetters, numbers, symbols];
// 4
let passedMatches = 0;
for (const flag of flags) {
passedMatches += flag === true ? 1 : 0;
}
// 5
force += 2 * password.length + (password.length >= 10 ? 1 : 0);
force += passedMatches * 10;
// 6
force = password.length <= 6 ? Math.min(force, 10) : force;
// 7
force = passedMatches === 1 ? Math.min(force, 10) : force;
force = passedMatches === 2 ? Math.min(force, 20) : force;
force = passedMatches === 3 ? Math.min(force, 30) : force;
force = passedMatches === 4 ? Math.min(force, 40) : force;
return force;
}
ngOnChanges(changes: { [propName: string]: SimpleChange }): void {
const password = changes['passwordToCheck'].currentValue;
this.setBarColors(4, '#DDD');
if (password) {
const pwdStrength = this.checkStrength(password);
pwdStrength === 40 ? this.passwordStrength.emit(true) : this.passwordStrength.emit(false);
const color = this.getColor(pwdStrength);
this.setBarColors(color.index, color.color);
switch (pwdStrength) {
case 10:
this.message = this.poor.nativeElement.value;
break;
case 20:
this.message = this.notGood.nativeElement.value;
break;
case 30:
this.message = this.average.nativeElement.value;
break;
case 40:
this.message = this.good.nativeElement.value;
break;
}
} else {
this.message = '';
}
}
private getColor(strength: number) {
let index = 0;
if (strength === 10) {
index = 0;
} else if (strength === 20) {
index = 1;
} else if (strength === 30) {
index = 2;
} else if (strength === 40) {
index = 3;
} else {
index = 4;
}
this.messageColor = this.colors[index];
return {
index: index + 1,
color: this.colors[index],
};
}
private setBarColors(count: number, color: string) {
for (let n = 0; n < count; n++) {
(this as any)['bar' + n] = color;
}
}
}
للاستدعاء الـ HTML:
<mat-form-field class="w-100 mt-1" appearance="outline">
<mat-label>{{'LABELS.PASSWORD' |
translate}}</mat-label>
<input #password [(ngModel)]="user.password" formControlName="password" maxlength="16" matInput
[type]="visibilityPassword === true? 'text': 'password'"
[placeholder]="'PLACEHOLDERS.PASSWORD' | translate" required>
<mat-icon matSuffix class="icon-edit" (click)="visibilityPassword = !visibilityPassword"
[matTooltip]="visibilityPassword === true? ('TOOLTIPS.HIDE_PASSWORD' | translate): ('TOOLTIPS.SHOW_PASSWORD' | translate)">{{visibilityPassword
=== true?
'visibility_off':'visibility'}}</mat-icon>
<app-password-strength [passwordToCheck]="password.value"
(passwordStrength)="onPasswordStrengthChanged($event)"></app-password-strength>
<mat-icon matSuffix class="icon-edit">password</mat-icon>
<mat-error align="start" *ngIf="thirdFormGroup.controls['password'].hasError('required')">
{{'ERRORS.REQUIRED' | translate}}
</mat-error>
<mat-hint align="end">{{password.value.length}} /
16</mat-hint>
</mat-form-field>
الـ TS:
visibilityPassword: boolean = false;
strongPassword = false;
onPasswordStrengthChanged(event: boolean) {
this.strongPassword = event;
}
create() {
if (this.thirdFormGroup.invalid) {
this.snackBarService.danger(this.translateService.instant('ERRORS.PASSWORD_NOT_ENOUGH'), '');
return;
}
if (this.strongPassword === false) {
this.snackBarService.danger(this.translateService.instant('ERRORS.PWD_STRENGTH'), '');
return;
}
}
thirdFormGroup = this._formBuilder.group({
password: ['', Validators.required],
});
تعليقات
إرسال تعليق