Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PM 2048 Update Two Factor Options dialog #8565

Merged
merged 11 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 41 additions & 64 deletions apps/web/src/app/auth/two-factor-options.component.html
Original file line number Diff line number Diff line change
@@ -1,68 +1,45 @@
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="twoStepOptionsTitle">
<div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title" id="twoStepOptionsTitle">{{ "twoStepOptions" | i18n }}</h1>
<button
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="list-group list-group-flush-2fa">
<div *ngFor="let p of providers" class="list-group-item list-group-item-action">
<div class="two-factor-content">
<div class="logo-col">
<img [class]="'mfaType' + p.type" [alt]="p.name + ' logo'" />
</div>
<div class="text-col">
<h3>{{ p.name }}</h3>
{{ p.description }}
</div>
<div class="btn-col">
<button
[attr.aria-describedby]="p.name"
type="button"
class="btn btn-outline-secondary btn-sm"
(click)="choose(p)"
>
{{ "select" | i18n }}
</button>
</div>
</div>
</div>
<div class="list-group-item list-group-item-action" (click)="recover()">
<div class="two-factor-content">
<div class="logo-col">
<img class="recovery-code-img" alt="rc logo" />
</div>
<div class="text-col">
<h3>{{ "recoveryCodeTitle" | i18n }}</h3>
{{ "recoveryCodeDesc" | i18n }}
</div>
<div class="btn-col">
<button
[attr.aria-describedby]="'recoveryCodeTitle' | i18n"
type="button"
class="btn btn-outline-secondary btn-sm"
(click)="recover()"
>
{{ "select" | i18n }}
</button>
</div>
</div>
</div>
<bit-dialog dialogSize="large">
<span bitDialogTitle>
{{ "twoStepOptions" | i18n }}
</span>
<ng-container bitDialogContent>
<div *ngFor="let p of providers" class="tw-m-2">
<div class="tw-flex tw-items-center tw-justify-center tw-gap-4">
<div class="tw-flex tw-items-center tw-justify-center tw-min-w-[100px]">
<img [class]="'mfaType' + p.type" [alt]="p.name + ' logo'" />
</div>
<div class="tw-flex-1">
<h3 bitTypography="h3">{{ p.name }}</h3>
<p bitTypography="body1">{{ p.description }}</p>
</div>
<div class="tw-min-w-20">
<button bitButton type="button" buttonType="secondary" (click)="choose(p)">
{{ "select" | i18n }}
</button>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
{{ "close" | i18n }}
</button>
<hr />
</div>
<div class="tw-m-2" (click)="recover()">
<div class="tw-flex tw-items-center tw-justify-center tw-gap-4">
<div class="tw-flex tw-items-center tw-justify-center tw-min-w-[100px]">
<img class="recovery-code-img" alt="rc logo" />
</div>
<div class="tw-flex-1">
<h3 bitTypography="h3">{{ "recoveryCodeTitle" | i18n }}</h3>
<p bitTypography="body1">{{ "recoveryCodeDesc" | i18n }}</p>
</div>
<div class="tw-min-w-20">
<button bitButton type="button" buttonType="secondary" (click)="recover()">
{{ "select" | i18n }}
</button>
</div>
</div>
</div>
</div>
</div>
</ng-container>
<ng-container bitDialogFooter>
<button bitButton type="button" buttonType="secondary" bitDialogClose>
{{ "close" | i18n }}
</button>
</ng-container>
</bit-dialog>
28 changes: 28 additions & 0 deletions apps/web/src/app/auth/two-factor-options.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { DialogRef } from "@angular/cdk/dialog";

Check notice on line 1 in apps/web/src/app/auth/two-factor-options.component.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ No longer an issue: Excess Number of Function Arguments

TwoFactorOptionsComponent.constructor is no longer above the threshold for number of arguments
import { Component } from "@angular/core";
import { Router } from "@angular/router";

import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { DialogService } from "@bitwarden/components";

export enum TwoFactorOptionsDialogResult {
Provider = "Provider selected",
Recover = "Recover selected",
}

export type TwoFactorOptionsDialogResultType = {
result: TwoFactorOptionsDialogResult;
type: TwoFactorProviderType;
};

@Component({
selector: "app-two-factor-options",
Expand All @@ -18,7 +31,22 @@
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
environmentService: EnvironmentService,
private dialogRef: DialogRef,

Check warning on line 34 in apps/web/src/app/auth/two-factor-options.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/auth/two-factor-options.component.ts#L34

Added line #L34 was not covered by tests
) {
super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
}

async choose(p: any) {
await super.choose(p);
this.dialogRef.close({ result: TwoFactorOptionsDialogResult.Provider, type: p.type });

Check warning on line 41 in apps/web/src/app/auth/two-factor-options.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/auth/two-factor-options.component.ts#L40-L41

Added lines #L40 - L41 were not covered by tests
}

async recover() {
await super.recover();
this.dialogRef.close({ result: TwoFactorOptionsDialogResult.Recover });

Check warning on line 46 in apps/web/src/app/auth/two-factor-options.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/auth/two-factor-options.component.ts#L45-L46

Added lines #L45 - L46 were not covered by tests
}

static open(dialogService: DialogService) {
return dialogService.open<TwoFactorOptionsDialogResultType>(TwoFactorOptionsComponent);

Check warning on line 50 in apps/web/src/app/auth/two-factor-options.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/auth/two-factor-options.component.ts#L50

Added line #L50 was not covered by tests
}
}
1 change: 0 additions & 1 deletion apps/web/src/app/auth/two-factor.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,3 @@
</div>
</div>
</form>
<ng-template #twoFactorOptions></ng-template>
34 changes: 14 additions & 20 deletions apps/web/src/app/auth/two-factor.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Component, Inject, OnDestroy, ViewChild, ViewContainerRef } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { lastValueFrom } from "rxjs";

import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import {
LoginStrategyServiceAbstraction,
LoginEmailServiceAbstraction,
Expand All @@ -14,7 +14,6 @@
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/auth/abstractions/master-password.service.abstraction";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
Expand All @@ -23,8 +22,13 @@
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { DialogService } from "@bitwarden/components";

import { TwoFactorOptionsComponent } from "./two-factor-options.component";
import {
TwoFactorOptionsDialogResult,
TwoFactorOptionsComponent,
TwoFactorOptionsDialogResultType,
} from "./two-factor-options.component";

@Component({
selector: "app-two-factor",
Expand All @@ -43,7 +47,7 @@
platformUtilsService: PlatformUtilsService,
stateService: StateService,
environmentService: EnvironmentService,
private modalService: ModalService,
private dialogService: DialogService,
route: ActivatedRoute,
logService: LogService,
twoFactorService: TwoFactorService,
Expand Down Expand Up @@ -80,22 +84,12 @@
}

async anotherMethod() {
const [modal] = await this.modalService.openViewRef(
TwoFactorOptionsComponent,
this.twoFactorOptionsModal,
(comp) => {
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
comp.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => {
modal.close();
this.selectedProviderType = provider;
await this.init();
});
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
comp.onRecoverSelected.subscribe(() => {
modal.close();
});
},
);
const dialogRef = TwoFactorOptionsComponent.open(this.dialogService);
const response: TwoFactorOptionsDialogResultType = await lastValueFrom(dialogRef.closed);

Check warning on line 88 in apps/web/src/app/auth/two-factor.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/auth/two-factor.component.ts#L87-L88

Added lines #L87 - L88 were not covered by tests
if (response.result === TwoFactorOptionsDialogResult.Provider) {
this.selectedProviderType = response.type;
await this.init();

Check warning on line 91 in apps/web/src/app/auth/two-factor.component.ts

View check run for this annotation

Codecov / codecov/patch

apps/web/src/app/auth/two-factor.component.ts#L90-L91

Added lines #L90 - L91 were not covered by tests
}
}

protected override handleMigrateEncryptionKey(result: AuthResult): boolean {
Expand Down