mirror of
https://github.com/bitwarden/browser
synced 2025-01-23 17:53:31 +01:00
[PM-2417] Update LoginApprovalComponent on Desktop (#6751)
* [PM-2417] convert modal to dialog service * code format * [PM-2417] Fix title * [PM-2417] Remove unnecessary class * Updated to use a local reference for the dialog. * Changes to clarify the method naming * More cleanup with Will. * Removed unused style --------- Co-authored-by: Todd Martin <tmartin@bitwarden.com> Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com> Co-authored-by: Todd Martin <106564991+trmartin4@users.noreply.github.com>
This commit is contained in:
parent
167648e213
commit
2a338319ea
@ -399,7 +399,11 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
break;
|
||||
case "openLoginApproval":
|
||||
if (message.notificationId != null) {
|
||||
await this.openLoginApproval(message.notificationId);
|
||||
this.dialogService.closeAll();
|
||||
const dialogRef = LoginApprovalComponent.open(this.dialogService, {
|
||||
notificationId: message.notificationId,
|
||||
});
|
||||
await firstValueFrom(dialogRef.closed);
|
||||
}
|
||||
break;
|
||||
case "redrawMenu":
|
||||
@ -473,19 +477,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
async openLoginApproval(notificationId: string) {
|
||||
this.modalService.closeAll();
|
||||
|
||||
this.modal = await this.modalService.open(LoginApprovalComponent, {
|
||||
data: { notificationId: notificationId },
|
||||
});
|
||||
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
this.modal.onClosed.subscribe(() => {
|
||||
this.modal = null;
|
||||
});
|
||||
}
|
||||
|
||||
private async updateAppMenu() {
|
||||
let updateRequest: MenuUpdateRequest;
|
||||
const stateAccounts = await firstValueFrom(this.stateService.accounts$);
|
||||
|
@ -14,7 +14,6 @@ import { DeleteAccountComponent } from "../auth/delete-account.component";
|
||||
import { EnvironmentComponent } from "../auth/environment.component";
|
||||
import { HintComponent } from "../auth/hint.component";
|
||||
import { LockComponent } from "../auth/lock.component";
|
||||
import { LoginApprovalComponent } from "../auth/login/login-approval.component";
|
||||
import { LoginModule } from "../auth/login/login.module";
|
||||
import { RegisterComponent } from "../auth/register.component";
|
||||
import { RemovePasswordComponent } from "../auth/remove-password.component";
|
||||
@ -101,7 +100,6 @@ import { SendComponent } from "./tools/send/send.component";
|
||||
VaultTimeoutInputComponent,
|
||||
ViewComponent,
|
||||
ViewCustomFieldsComponent,
|
||||
LoginApprovalComponent,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
|
@ -1,43 +1,42 @@
|
||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="loginApprovalTitle">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div id="login-approval-page" class="modal-content">
|
||||
<div class="section-title">
|
||||
<p style="text-transform: uppercase">{{ "areYouTryingtoLogin" | i18n }}</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="section">
|
||||
<h4>{{ "logInAttemptBy" | i18n: email }}</h4>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h4 class="label">{{ "fingerprintPhraseHeader" | i18n }}</h4>
|
||||
<code>{{ fingerprintPhrase }}</code>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h4 class="label">{{ "deviceType" | i18n }}</h4>
|
||||
<p>{{ authRequestResponse?.requestDeviceType }}</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h4 class="label">{{ "ipAddress" | i18n }}</h4>
|
||||
<p>{{ authRequestResponse?.requestIpAddress }}</p>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h4 class="label">{{ "time" | i18n }}</h4>
|
||||
<p>{{ requestTimeText }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="primary" (click)="approveLogin(true, true)">
|
||||
{{ "confirmLogIn" | i18n }}
|
||||
</button>
|
||||
<button type="button" (click)="approveLogin(false, true)">
|
||||
{{ "denyLogIn" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<bit-dialog>
|
||||
<span bitDialogTitle>{{ "areYouTryingtoLogin" | i18n }}</span>
|
||||
<ng-container bitDialogContent>
|
||||
<h4>{{ "logInAttemptBy" | i18n: email }}</h4>
|
||||
<div>
|
||||
<b>{{ "fingerprintPhraseHeader" | i18n }}</b>
|
||||
<p class="tw-text-code">{{ fingerprintPhrase }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<b>{{ "deviceType" | i18n }}</b>
|
||||
<p>{{ authRequestResponse?.requestDeviceType }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<b>{{ "ipAddress" | i18n }}</b>
|
||||
<p>{{ authRequestResponse?.requestIpAddress }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<b>{{ "time" | i18n }}</b>
|
||||
<p>{{ requestTimeText }}</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container bitDialogFooter>
|
||||
<button
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="primary"
|
||||
[bitAction]="approveLogin"
|
||||
[bitDialogClose]="true"
|
||||
>
|
||||
{{ "confirmLogIn" | i18n }}
|
||||
</button>
|
||||
<button
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="secondary"
|
||||
[bitAction]="denyLogin"
|
||||
[bitDialogClose]="true"
|
||||
>
|
||||
{{ "denyLogIn" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { Component, OnInit, OnDestroy } from "@angular/core";
|
||||
import { Subject } from "rxjs";
|
||||
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, OnInit, OnDestroy, Inject } from "@angular/core";
|
||||
import { Subject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
|
||||
import { ModalConfig } from "@bitwarden/angular/services/modal.service";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||
@ -12,13 +13,25 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import {
|
||||
AsyncActionsModule,
|
||||
ButtonModule,
|
||||
DialogModule,
|
||||
DialogService,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
const RequestTimeOut = 60000 * 15; //15 Minutes
|
||||
const RequestTimeUpdate = 60000 * 5; //5 Minutes
|
||||
|
||||
export interface LoginApprovalDialogParams {
|
||||
notificationId: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "login-approval",
|
||||
templateUrl: "login-approval.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, AsyncActionsModule, ButtonModule, DialogModule, JslibModule],
|
||||
})
|
||||
export class LoginApprovalComponent implements OnInit, OnDestroy {
|
||||
notificationId: string;
|
||||
@ -30,9 +43,9 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
||||
authRequestResponse: AuthRequestResponse;
|
||||
interval: NodeJS.Timeout;
|
||||
requestTimeText: string;
|
||||
dismissModal: boolean;
|
||||
|
||||
constructor(
|
||||
@Inject(DIALOG_DATA) private params: LoginApprovalDialogParams,
|
||||
protected stateService: StateService,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected i18nService: I18nService,
|
||||
@ -40,23 +53,17 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
||||
protected authService: AuthService,
|
||||
protected appIdService: AppIdService,
|
||||
protected cryptoService: CryptoService,
|
||||
private modalRef: ModalRef,
|
||||
config: ModalConfig,
|
||||
private dialogRef: DialogRef,
|
||||
) {
|
||||
this.notificationId = config.data.notificationId;
|
||||
|
||||
this.dismissModal = true;
|
||||
this.modalRef.onClosed
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
.subscribe(() => {
|
||||
if (this.dismissModal) {
|
||||
this.approveLogin(false, false);
|
||||
}
|
||||
});
|
||||
this.notificationId = params.notificationId;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
async ngOnDestroy(): Promise<void> {
|
||||
clearInterval(this.interval);
|
||||
const closedWithButton = await firstValueFrom(this.dialogRef.closed);
|
||||
if (!closedWithButton) {
|
||||
this.retrieveAuthRequestAndRespond(false);
|
||||
}
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
@ -86,14 +93,24 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
async approveLogin(approveLogin: boolean, approveDenyButtonClicked: boolean) {
|
||||
clearInterval(this.interval);
|
||||
/**
|
||||
* Strongly-typed helper to open a LoginApprovalDialog
|
||||
* @param dialogService Instance of the dialog service that will be used to open the dialog
|
||||
* @param data Configuration for the dialog
|
||||
*/
|
||||
static open(dialogService: DialogService, data: LoginApprovalDialogParams) {
|
||||
return dialogService.open(LoginApprovalComponent, { data });
|
||||
}
|
||||
|
||||
this.dismissModal = !approveDenyButtonClicked;
|
||||
if (approveDenyButtonClicked) {
|
||||
this.modalRef.close();
|
||||
}
|
||||
denyLogin = async () => {
|
||||
await this.retrieveAuthRequestAndRespond(false);
|
||||
};
|
||||
|
||||
approveLogin = async () => {
|
||||
await this.retrieveAuthRequestAndRespond(true);
|
||||
};
|
||||
|
||||
private async retrieveAuthRequestAndRespond(approve: boolean) {
|
||||
this.authRequestResponse = await this.apiService.getAuthRequest(this.notificationId);
|
||||
if (this.authRequestResponse.requestApproved || this.authRequestResponse.responseDate != null) {
|
||||
this.platformUtilsService.showToast(
|
||||
@ -105,7 +122,7 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
||||
const loginResponse = await this.authService.passwordlessLogin(
|
||||
this.authRequestResponse.id,
|
||||
this.authRequestResponse.publicKey,
|
||||
approveLogin,
|
||||
approve,
|
||||
);
|
||||
this.showResultToast(loginResponse);
|
||||
}
|
||||
@ -165,7 +182,7 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
} else {
|
||||
clearInterval(this.interval);
|
||||
this.modalRef.close();
|
||||
this.dialogRef.close();
|
||||
this.platformUtilsService.showToast(
|
||||
"info",
|
||||
null,
|
||||
|
Loading…
Reference in New Issue
Block a user