mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[SG-414] Refactor password strength component (#3186)
* moved password strength to libs * refactored password strength component * made changes on desktop and browser to reuse component * resolved suggestions from PR review * shared module restructure * shared module restructure
This commit is contained in:
@@ -32,11 +32,15 @@
|
||||
name="MasterPasswordHash"
|
||||
class="text-monospace form-control mb-1"
|
||||
[(ngModel)]="masterPassword"
|
||||
(input)="updatePasswordStrength()"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true">
|
||||
<app-password-strength
|
||||
[password]="masterPassword"
|
||||
[email]="email"
|
||||
[showText]="true"
|
||||
(passwordStrengthResult)="getStrengthResult($event)"
|
||||
>
|
||||
</app-password-strength>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -44,13 +44,13 @@
|
||||
name="NewMasterPasswordHash"
|
||||
class="form-control mb-1"
|
||||
[(ngModel)]="masterPassword"
|
||||
(input)="updatePasswordStrength()"
|
||||
required
|
||||
appInputVerbatim
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<app-password-strength
|
||||
[score]="masterPasswordScore"
|
||||
[password]="masterPassword"
|
||||
[email]="email"
|
||||
[showText]="true"
|
||||
></app-password-strength>
|
||||
</div>
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
name="MasterPasswordHash"
|
||||
class="text-monospace form-control mb-1"
|
||||
[(ngModel)]="masterPassword"
|
||||
(input)="updatePasswordStrength()"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true">
|
||||
<app-password-strength
|
||||
[password]="masterPassword"
|
||||
[email]="email"
|
||||
[showText]="true"
|
||||
>
|
||||
</app-password-strength>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<div class="progress">
|
||||
<div
|
||||
class="progress-bar {{ color }}"
|
||||
role="progressbar"
|
||||
[ngStyle]="{ width: scoreWidth + '%' }"
|
||||
attr.aria-valuenow="{{ scoreWidth }}"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
>
|
||||
<ng-container *ngIf="showText && text">
|
||||
{{ text }}
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Component, Input, OnChanges } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-password-strength",
|
||||
templateUrl: "password-strength.component.html",
|
||||
})
|
||||
export class PasswordStrengthComponent implements OnChanges {
|
||||
@Input() score?: number;
|
||||
@Input() showText = false;
|
||||
|
||||
scoreWidth = 0;
|
||||
color = "bg-danger";
|
||||
text: string;
|
||||
|
||||
constructor(private i18nService: I18nService) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.scoreWidth = this.score == null ? 0 : (this.score + 1) * 20;
|
||||
switch (this.score) {
|
||||
case 4:
|
||||
this.color = "bg-success";
|
||||
this.text = this.i18nService.t("strong");
|
||||
break;
|
||||
case 3:
|
||||
this.color = "bg-primary";
|
||||
this.text = this.i18nService.t("good");
|
||||
break;
|
||||
case 2:
|
||||
this.color = "bg-warning";
|
||||
this.text = this.i18nService.t("weak");
|
||||
break;
|
||||
default:
|
||||
this.color = "bg-danger";
|
||||
this.text = this.score != null ? this.i18nService.t("weak") : null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@
|
||||
<input
|
||||
id="register-form_input_master-password"
|
||||
bitInput
|
||||
(input)="updatePasswordStrength()"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
formControlName="masterPassword"
|
||||
/>
|
||||
@@ -50,7 +49,13 @@
|
||||
{{ "masterPassImportant" | i18n }}
|
||||
</bit-hint>
|
||||
</bit-form-field>
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true">
|
||||
<app-password-strength
|
||||
[password]="formGroup.get('masterPassword')?.value"
|
||||
[email]="formGroup.get('email')?.value"
|
||||
[name]="formGroup.get('name')?.value"
|
||||
[showText]="true"
|
||||
(passwordStrengthResult)="getStrengthResult($event)"
|
||||
>
|
||||
</app-password-strength>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ export class RegisterFormComponent extends BaseRegisterComponent {
|
||||
if (
|
||||
this.enforcedPolicyOptions != null &&
|
||||
!this.policyService.evaluateMasterPassword(
|
||||
this.masterPasswordScore,
|
||||
this.passwordStrengthResult.score,
|
||||
this.formGroup.get("masterPassword")?.value,
|
||||
this.enforcedPolicyOptions
|
||||
)
|
||||
|
||||
@@ -66,7 +66,6 @@ import {
|
||||
MenuModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { PasswordStrengthComponent } from "../components/password-strength.component";
|
||||
import { PaymentComponent } from "../settings/payment.component";
|
||||
import { TaxInfoComponent } from "../settings/tax-info.component";
|
||||
|
||||
@@ -122,7 +121,7 @@ registerLocaleData(localeZhCn, "zh-CN");
|
||||
registerLocaleData(localeZhTw, "zh-TW");
|
||||
|
||||
@NgModule({
|
||||
declarations: [PasswordStrengthComponent, PaymentComponent, TaxInfoComponent],
|
||||
declarations: [PaymentComponent, TaxInfoComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
DragDropModule,
|
||||
@@ -158,7 +157,6 @@ registerLocaleData(localeZhTw, "zh-TW");
|
||||
MenuModule,
|
||||
FormFieldModule,
|
||||
SubmitButtonModule,
|
||||
PasswordStrengthComponent,
|
||||
PaymentComponent,
|
||||
TaxInfoComponent,
|
||||
],
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
required
|
||||
appInputVerbatim
|
||||
autocomplete="new-password"
|
||||
(input)="updatePasswordStrength()"
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button
|
||||
@@ -78,7 +77,7 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true">
|
||||
<app-password-strength [password]="newPassword" [email]="email" [showText]="true">
|
||||
</app-password-strength>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from "@angular/core";
|
||||
|
||||
import { PasswordStrengthComponent } from "@bitwarden/angular/shared/components/password-strength/password-strength.component";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
@@ -22,13 +23,13 @@ export class ResetPasswordComponent implements OnInit {
|
||||
@Input() id: string;
|
||||
@Input() organizationId: string;
|
||||
@Output() onPasswordReset = new EventEmitter();
|
||||
@ViewChild(PasswordStrengthComponent) passwordStrengthComponent: PasswordStrengthComponent;
|
||||
|
||||
enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
newPassword: string = null;
|
||||
showPassword = false;
|
||||
masterPasswordScore: number;
|
||||
formPromise: Promise<any>;
|
||||
private newPasswordStrengthTimeout: any;
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
@@ -52,7 +53,7 @@ export class ResetPasswordComponent implements OnInit {
|
||||
async generatePassword() {
|
||||
const options = (await this.passwordGenerationService.getOptions())[0];
|
||||
this.newPassword = await this.passwordGenerationService.generatePassword(options);
|
||||
this.updatePasswordStrength();
|
||||
this.passwordStrengthComponent.updatePasswordStrength(this.newPassword);
|
||||
}
|
||||
|
||||
togglePassword() {
|
||||
@@ -183,35 +184,4 @@ export class ResetPasswordComponent implements OnInit {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
updatePasswordStrength() {
|
||||
if (this.newPasswordStrengthTimeout != null) {
|
||||
clearTimeout(this.newPasswordStrengthTimeout);
|
||||
}
|
||||
this.newPasswordStrengthTimeout = setTimeout(() => {
|
||||
const strengthResult = this.passwordGenerationService.passwordStrength(
|
||||
this.newPassword,
|
||||
this.getPasswordStrengthUserInput()
|
||||
);
|
||||
this.masterPasswordScore = strengthResult == null ? null : strengthResult.score;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
private getPasswordStrengthUserInput() {
|
||||
let userInput: string[] = [];
|
||||
const atPosition = this.email.indexOf("@");
|
||||
if (atPosition > -1) {
|
||||
userInput = userInput.concat(
|
||||
this.email
|
||||
.substr(0, atPosition)
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.split(/[^A-Za-z0-9]/)
|
||||
);
|
||||
}
|
||||
if (this.name != null && this.name !== "") {
|
||||
userInput = userInput.concat(this.name.trim().toLowerCase().split(" "));
|
||||
}
|
||||
return userInput;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,15 +37,17 @@
|
||||
name="NewMasterPasswordHash"
|
||||
class="form-control mb-1"
|
||||
[(ngModel)]="masterPassword"
|
||||
(input)="updatePasswordStrength()"
|
||||
required
|
||||
appInputVerbatim
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<app-password-strength
|
||||
[score]="masterPasswordScore"
|
||||
[password]="masterPassword"
|
||||
[email]="email"
|
||||
[showText]="true"
|
||||
></app-password-strength>
|
||||
(passwordStrengthResult)="getStrengthResult($event)"
|
||||
>
|
||||
</app-password-strength>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
|
||||
@@ -39,12 +39,16 @@
|
||||
name="NewMasterPasswordHash"
|
||||
class="form-control mb-1"
|
||||
[(ngModel)]="masterPassword"
|
||||
(input)="updatePasswordStrength()"
|
||||
required
|
||||
appInputVerbatim
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<app-password-strength [score]="masterPasswordScore" [showText]="true">
|
||||
<app-password-strength
|
||||
[password]="masterPassword"
|
||||
[email]="email"
|
||||
[showText]="true"
|
||||
(passwordStrengthResult)="getStrengthResult($event)"
|
||||
>
|
||||
</app-password-strength>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user