1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-24 21:41:33 +01:00

[PM-2014] feat: return undefined when credential creation fails

This commit is contained in:
Andreas Coroiu 2023-05-08 15:54:26 +02:00
parent c593339363
commit 8997fb3422
No known key found for this signature in database
GPG Key ID: E70B5FFC81DFEC1A
3 changed files with 36 additions and 10 deletions

View File

@ -6,6 +6,8 @@ import { VerificationType } from "@bitwarden/common/auth/enums/verification-type
import { ChallengeResponse } from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
import { Verification } from "@bitwarden/common/types/verification";
import { NewCredentialOptionsView } from "../../views/new-credential-options.view";
import { WebauthnApiService } from "./webauthn-api.service";
import { WebauthnService } from "./webauthn.service";
@ -13,13 +15,20 @@ describe("WebauthnService", () => {
let apiService!: MockProxy<WebauthnApiService>;
let platformUtilsService!: MockProxy<PlatformUtilsService>;
let i18nService!: MockProxy<I18nService>;
let credentials: MockProxy<CredentialsContainer>;
let webauthnService!: WebauthnService;
beforeAll(() => {
apiService = mock<WebauthnApiService>();
platformUtilsService = mock<PlatformUtilsService>();
i18nService = mock<I18nService>();
webauthnService = new WebauthnService(apiService, platformUtilsService, i18nService);
credentials = mock<CredentialsContainer>();
webauthnService = new WebauthnService(
apiService,
platformUtilsService,
i18nService,
credentials
);
});
describe("getNewCredentialOptions", () => {
@ -43,6 +52,17 @@ describe("WebauthnService", () => {
expect(result).toEqual({ challenge });
});
});
describe("createCredential", () => {
it("should return undefined when navigator.credentials throws", async () => {
credentials.create.mockRejectedValue(new Error("Mocked error"));
const options = createNewCredentialOptions();
const result = await webauthnService.createCredential(options);
expect(result).toBeUndefined();
});
});
});
function createVerification(): Verification {
@ -51,3 +71,7 @@ function createVerification(): Verification {
secret: "secret",
};
}
function createNewCredentialOptions(): NewCredentialOptionsView {
return new NewCredentialOptionsView(Symbol() as any);
}

View File

@ -1,4 +1,4 @@
import { Injectable } from "@angular/core";
import { Injectable, Optional } from "@angular/core";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
@ -17,10 +17,13 @@ export class WebauthnService {
constructor(
private apiService: WebauthnApiService,
private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService
private i18nService: I18nService,
@Optional() private credentials: CredentialsContainer = navigator.credentials
) {}
async getNewCredentialOptions(verification: Verification): Promise<NewCredentialOptionsView> {
async getNewCredentialOptions(
verification: Verification
): Promise<NewCredentialOptionsView | undefined> {
try {
return { challenge: await this.apiService.getChallenge(verification) };
} catch (error) {
@ -39,8 +42,7 @@ export class WebauthnService {
async createCredential(
credentialOptions: NewCredentialOptionsView
): Promise<WebauthnCredentialView> {
await new Promise((_, reject) => setTimeout(() => reject(new Error("Not implemented")), 1000));
return undefined;
): Promise<WebauthnCredentialView | undefined> {
return await new Promise((resolve) => setTimeout(() => resolve(undefined), 1000));
}
}

View File

@ -71,10 +71,10 @@ export class CreateCredentialDialogComponent {
}
if (this.currentStep === "credentialCreation") {
try {
await this.webauthnService.createCredential(this.credentialOptions);
} catch {
const credential = await this.webauthnService.createCredential(this.credentialOptions);
if (credential === undefined) {
this.currentStep = "credentialCreationFailed";
return;
}
}
} finally {