mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-24 21:41:33 +01:00
Merge branch 'main' into auth/pm-8111/browser-refresh-login-component
This commit is contained in:
commit
68f358b804
@ -559,9 +559,11 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async fingerprint() {
|
||||
const fingerprint = await this.cryptoService.getFingerprint(
|
||||
await this.stateService.getUserId(),
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const publicKey = await firstValueFrom(this.cryptoService.userPublicKey$(activeUserId));
|
||||
const fingerprint = await this.cryptoService.getFingerprint(activeUserId, publicKey);
|
||||
|
||||
const dialogRef = FingerprintDialogComponent.open(this.dialogService, {
|
||||
fingerprint,
|
||||
|
@ -74,7 +74,7 @@ describe("AutofillInit", () => {
|
||||
Object.defineProperty(document, "readyState", { value: "complete", writable: true });
|
||||
|
||||
autofillInit.init();
|
||||
jest.advanceTimersByTime(250);
|
||||
jest.advanceTimersByTime(750);
|
||||
|
||||
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("bgCollectPageDetails", {
|
||||
sender: "autofillInit",
|
||||
|
@ -78,7 +78,7 @@ class AutofillInit implements AutofillInitInterface {
|
||||
this.clearCollectPageDetailsOnLoadTimeout();
|
||||
this.collectPageDetailsOnLoadTimeout = setTimeout(
|
||||
() => this.sendExtensionMessage("bgCollectPageDetails", { sender: "autofillInit" }),
|
||||
250,
|
||||
750,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,9 @@
|
||||
class="bwi bwi-collection text-muted"
|
||||
></i>
|
||||
</span>
|
||||
<span class="detail" *ngIf="getSubName(cipher)">{{ getSubName(cipher) }}</span>
|
||||
<span *ngIf="cipher.subTitle" slot="secondary">{{ cipher.subTitle }}</span>
|
||||
<ng-container slot="secondary">
|
||||
<div *ngIf="getSubName(cipher)">{{ getSubName(cipher) }}</div>
|
||||
<div *ngIf="cipher.subTitle">{{ cipher.subTitle }}</div>
|
||||
</ng-container>
|
||||
</button>
|
||||
</bit-item>
|
||||
|
@ -287,7 +287,7 @@ export class Fido2Component implements OnInit, OnDestroy {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "overwritePasskey" },
|
||||
content: { key: "overwritePasskeyAlert" },
|
||||
type: "info",
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
|
@ -34,28 +34,30 @@ export class AutoFillConstants {
|
||||
"totpcode",
|
||||
"2facode",
|
||||
"approvals_code",
|
||||
"code",
|
||||
"mfacode",
|
||||
"otc",
|
||||
"otc-code",
|
||||
"otp",
|
||||
"onetimecode",
|
||||
"otp-code",
|
||||
"otpcode",
|
||||
"pin",
|
||||
"onetimepassword",
|
||||
"security_code",
|
||||
"twofactor",
|
||||
"twofa",
|
||||
"twofactorcode",
|
||||
"verificationCode",
|
||||
"verification code",
|
||||
];
|
||||
|
||||
static readonly AmbiguousTotpFieldNames: string[] = ["code", "pin", "otc", "otp"];
|
||||
|
||||
static readonly SearchFieldNames: string[] = ["search", "query", "find", "go"];
|
||||
|
||||
static readonly FieldIgnoreList: string[] = ["captcha", "findanything", "forgot"];
|
||||
|
||||
static readonly PasswordFieldExcludeList: string[] = [
|
||||
"hint",
|
||||
...AutoFillConstants.FieldIgnoreList,
|
||||
"onetimepassword",
|
||||
...AutoFillConstants.TotpFieldNames,
|
||||
];
|
||||
|
||||
static readonly ExcludedAutofillLoginTypes: string[] = [
|
||||
|
@ -2260,29 +2260,23 @@ describe("AutofillService", () => {
|
||||
options,
|
||||
);
|
||||
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenCalledTimes(4);
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenCalledWith(
|
||||
usernameField,
|
||||
AutoFillConstants.UsernameFieldNames,
|
||||
);
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenCalledWith(
|
||||
emailField,
|
||||
AutoFillConstants.UsernameFieldNames,
|
||||
);
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenCalledWith(
|
||||
telephoneField,
|
||||
AutoFillConstants.UsernameFieldNames,
|
||||
);
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenNthCalledWith(
|
||||
4,
|
||||
expect(AutofillService.fieldIsFuzzyMatch).toHaveBeenCalledWith(
|
||||
totpField,
|
||||
AutoFillConstants.UsernameFieldNames,
|
||||
);
|
||||
expect(AutofillService.fieldIsFuzzyMatch).not.toHaveBeenNthCalledWith(
|
||||
5,
|
||||
expect(AutofillService.fieldIsFuzzyMatch).not.toHaveBeenCalledWith(
|
||||
nonViewableField,
|
||||
AutoFillConstants.UsernameFieldNames,
|
||||
);
|
||||
@ -2328,6 +2322,7 @@ describe("AutofillService", () => {
|
||||
|
||||
it("will not attempt to fuzzy match a totp field if totp autofill is not allowed", async () => {
|
||||
options.allowTotpAutofill = false;
|
||||
jest.spyOn(autofillService as any, "findMatchingFieldIndex");
|
||||
|
||||
await autofillService["generateLoginFillScript"](
|
||||
fillScript,
|
||||
@ -2336,7 +2331,7 @@ describe("AutofillService", () => {
|
||||
options,
|
||||
);
|
||||
|
||||
expect(AutofillService.fieldIsFuzzyMatch).not.toHaveBeenCalledWith(
|
||||
expect(autofillService["findMatchingFieldIndex"]).not.toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
AutoFillConstants.TotpFieldNames,
|
||||
);
|
||||
@ -2386,7 +2381,6 @@ describe("AutofillService", () => {
|
||||
false,
|
||||
false,
|
||||
);
|
||||
expect(AutofillService.fieldIsFuzzyMatch).not.toHaveBeenCalled();
|
||||
expect(AutofillService.fillByOpid).toHaveBeenCalledTimes(2);
|
||||
expect(AutofillService.fillByOpid).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
|
@ -887,7 +887,10 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
options.allowTotpAutofill &&
|
||||
f.viewable &&
|
||||
(f.type === "text" || f.type === "number") &&
|
||||
(AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.TotpFieldNames) ||
|
||||
(AutofillService.fieldIsFuzzyMatch(f, [
|
||||
...AutoFillConstants.TotpFieldNames,
|
||||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||||
]) ||
|
||||
f.autoCompleteType === "one-time-code")
|
||||
) {
|
||||
totps.push(f);
|
||||
@ -2558,6 +2561,11 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
return;
|
||||
}
|
||||
|
||||
// We want to avoid treating TOTP fields as password fields
|
||||
if (AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.TotpFieldNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isLikePassword = () => {
|
||||
if (f.type !== "text") {
|
||||
return false;
|
||||
@ -2670,12 +2678,18 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
(withoutForm || f.form === passwordField.form) &&
|
||||
(canBeHidden || f.viewable) &&
|
||||
(f.type === "text" || f.type === "number") &&
|
||||
AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.TotpFieldNames)
|
||||
AutofillService.fieldIsFuzzyMatch(f, [
|
||||
...AutoFillConstants.TotpFieldNames,
|
||||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||||
])
|
||||
) {
|
||||
totpField = f;
|
||||
|
||||
if (
|
||||
this.findMatchingFieldIndex(f, AutoFillConstants.TotpFieldNames) > -1 ||
|
||||
this.findMatchingFieldIndex(f, [
|
||||
...AutoFillConstants.TotpFieldNames,
|
||||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||||
]) > -1 ||
|
||||
f.autoCompleteType === "one-time-code"
|
||||
) {
|
||||
// We found an exact match. No need to keep looking.
|
||||
|
@ -30,7 +30,6 @@ export class InlineMenuFieldQualificationService
|
||||
this.webAuthnAutocompleteValue,
|
||||
]);
|
||||
private fieldIgnoreListString = AutoFillConstants.FieldIgnoreList.join(",");
|
||||
private passwordFieldExcludeListString = AutoFillConstants.PasswordFieldExcludeList.join(",");
|
||||
private currentPasswordAutocompleteValue = "current-password";
|
||||
private newPasswordAutoCompleteValue = "new-password";
|
||||
private autofillFieldKeywordsMap: AutofillKeywordsMap = new WeakMap();
|
||||
@ -927,7 +926,7 @@ export class InlineMenuFieldQualificationService
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(this.passwordFieldExcludeListString.indexOf(cleanedValue) > -1);
|
||||
return !AutoFillConstants.PasswordFieldExcludeList.some((i) => cleanedValue.indexOf(i) > -1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1094,13 +1093,29 @@ export class InlineMenuFieldQualificationService
|
||||
];
|
||||
const keywordsSet = new Set<string>();
|
||||
for (let i = 0; i < keywords.length; i++) {
|
||||
if (typeof keywords[i] === "string") {
|
||||
keywords[i]
|
||||
.toLowerCase()
|
||||
.replace(/-/g, "")
|
||||
.replace(/[^a-zA-Z0-9]+/g, "|")
|
||||
.split("|")
|
||||
.forEach((keyword) => keywordsSet.add(keyword));
|
||||
if (keywords[i] && typeof keywords[i] === "string") {
|
||||
let keywordEl = keywords[i].toLowerCase();
|
||||
keywordsSet.add(keywordEl);
|
||||
|
||||
// Remove hyphens from all potential keywords, we want to treat these as a single word.
|
||||
keywordEl = keywordEl.replace(/-/g, "");
|
||||
|
||||
// Split the keyword by non-alphanumeric characters to get the keywords without treating a space as a separator.
|
||||
keywordEl.split(/[^\p{L}\d]+/gu).forEach((keyword) => {
|
||||
if (keyword) {
|
||||
keywordsSet.add(keyword);
|
||||
}
|
||||
});
|
||||
|
||||
// Collapse all spaces and split by non-alphanumeric characters to get the keywords
|
||||
keywordEl
|
||||
.replace(/\s/g, "")
|
||||
.split(/[^\p{L}\d]+/gu)
|
||||
.forEach((keyword) => {
|
||||
if (keyword) {
|
||||
keywordsSet.add(keyword);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,11 @@ export class GetCommand extends DownloadCommand {
|
||||
private async getFingerprint(id: string) {
|
||||
let fingerprint: string[] = null;
|
||||
if (id === "me") {
|
||||
fingerprint = await this.cryptoService.getFingerprint(await this.stateService.getUserId());
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const publicKey = await firstValueFrom(this.cryptoService.userPublicKey$(activeUserId));
|
||||
fingerprint = await this.cryptoService.getFingerprint(activeUserId, publicKey);
|
||||
} else if (Utils.isGuid(id)) {
|
||||
try {
|
||||
const response = await this.apiService.getUserPublicKey(id);
|
||||
|
@ -2,7 +2,7 @@ import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import * as jsdom from "jsdom";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import {
|
||||
OrganizationUserApiService,
|
||||
@ -119,7 +119,6 @@ import {
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service";
|
||||
import { SendStateProvider } from "@bitwarden/common/tools/send/services/send-state.provider";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type";
|
||||
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherService } from "@bitwarden/common/vault/services/cipher.service";
|
||||
@ -788,13 +787,13 @@ export class ServiceContainer {
|
||||
this.authService.logOut(() => {
|
||||
/* Do nothing */
|
||||
});
|
||||
const userId = (await this.stateService.getUserId()) as UserId;
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||
await Promise.all([
|
||||
this.eventUploadService.uploadEvents(userId as UserId),
|
||||
this.eventUploadService.uploadEvents(userId),
|
||||
this.cryptoService.clearKeys(),
|
||||
this.cipherService.clear(userId),
|
||||
this.folderService.clear(userId),
|
||||
this.collectionService.clear(userId as UserId),
|
||||
this.collectionService.clear(userId),
|
||||
]);
|
||||
|
||||
await this.stateEventRunnerService.handleEvent("logout", userId);
|
||||
|
@ -196,22 +196,23 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
||||
|
||||
async ngOnInit() {
|
||||
this.vaultTimeoutOptions = await this.generateVaultTimeoutOptions();
|
||||
|
||||
this.userHasMasterPassword = await this.userVerificationService.hasMasterPassword();
|
||||
|
||||
this.isWindows = (await this.platformUtilsService.getDevice()) === DeviceType.WindowsDesktop;
|
||||
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
|
||||
this.isLinux = (await this.platformUtilsService.getDevice()) === DeviceType.LinuxDesktop;
|
||||
|
||||
if ((await this.stateService.getUserId()) == null) {
|
||||
if (activeAccount == null || activeAccount.id == null) {
|
||||
return;
|
||||
}
|
||||
this.currentUserEmail = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.email)),
|
||||
);
|
||||
this.currentUserId = (await this.stateService.getUserId()) as UserId;
|
||||
this.userHasMasterPassword = await this.userVerificationService.hasMasterPassword();
|
||||
|
||||
this.isWindows = this.platformUtilsService.getDevice() === DeviceType.WindowsDesktop;
|
||||
|
||||
this.currentUserEmail = activeAccount.email;
|
||||
this.currentUserId = activeAccount.id;
|
||||
|
||||
this.availableVaultTimeoutActions$ = this.refreshTimeoutSettings$.pipe(
|
||||
switchMap(() => this.vaultTimeoutSettingsService.availableVaultTimeoutActions$()),
|
||||
switchMap(() =>
|
||||
this.vaultTimeoutSettingsService.availableVaultTimeoutActions$(activeAccount.id),
|
||||
),
|
||||
);
|
||||
|
||||
// Load timeout policy
|
||||
@ -236,12 +237,8 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
||||
}),
|
||||
);
|
||||
|
||||
const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id;
|
||||
|
||||
// Load initial values
|
||||
this.userHasPinSet = await this.pinService.isPinSet(userId);
|
||||
|
||||
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
|
||||
this.userHasPinSet = await this.pinService.isPinSet(activeAccount.id);
|
||||
|
||||
const initialValues = {
|
||||
vaultTimeout: await firstValueFrom(
|
||||
|
@ -235,7 +235,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.modalService.closeAll();
|
||||
if (
|
||||
message.userId == null ||
|
||||
message.userId === (await this.stateService.getUserId())
|
||||
message.userId ===
|
||||
(await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id))))
|
||||
) {
|
||||
await this.router.navigate(["lock"]);
|
||||
}
|
||||
@ -274,9 +275,11 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
await this.openModal<PremiumComponent>(PremiumComponent, this.premiumRef);
|
||||
break;
|
||||
case "showFingerprintPhrase": {
|
||||
const fingerprint = await this.cryptoService.getFingerprint(
|
||||
await this.stateService.getUserId(),
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const publicKey = await firstValueFrom(this.cryptoService.userPublicKey$(activeUserId));
|
||||
const fingerprint = await this.cryptoService.getFingerprint(activeUserId, publicKey);
|
||||
const dialogRef = FingerprintDialogComponent.open(this.dialogService, { fingerprint });
|
||||
await firstValueFrom(dialogRef.closed);
|
||||
break;
|
||||
|
@ -201,8 +201,11 @@ export class AccountSwitcherComponent implements OnInit {
|
||||
}): Promise<{ [userId: string]: InactiveAccount }> {
|
||||
const inactiveAccounts: { [userId: string]: InactiveAccount } = {};
|
||||
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
for (const userId in baseAccounts) {
|
||||
if (userId == null || userId === (await this.stateService.getUserId())) {
|
||||
if (userId == null || userId === activeUserId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -461,11 +461,10 @@ describe("LockComponent", () => {
|
||||
});
|
||||
|
||||
describe("canUseBiometric", () => {
|
||||
it("should call getUserId() on stateService", async () => {
|
||||
stateServiceMock.getUserId.mockResolvedValue("userId");
|
||||
it("should call biometric.enabled with current active user", async () => {
|
||||
await component["canUseBiometric"]();
|
||||
|
||||
expect(ipc.keyManagement.biometric.enabled).toHaveBeenCalledWith("userId");
|
||||
expect(ipc.keyManagement.biometric.enabled).toHaveBeenCalledWith(mockUserId);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Component, NgZone, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { firstValueFrom, switchMap } from "rxjs";
|
||||
import { firstValueFrom, map, switchMap } from "rxjs";
|
||||
|
||||
import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
|
||||
import { PinServiceAbstraction } from "@bitwarden/auth/common";
|
||||
@ -182,7 +182,7 @@ export class LockComponent extends BaseLockComponent implements OnInit, OnDestro
|
||||
}
|
||||
|
||||
private async canUseBiometric() {
|
||||
const userId = await this.stateService.getUserId();
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||
return await ipc.keyManagement.biometric.enabled(userId);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { StateEventRunnerService } from "@bitwarden/common/platform/state";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
@ -277,7 +276,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
await this.displayLogoutReason(logoutReason);
|
||||
|
||||
await this.eventUploadService.uploadEvents();
|
||||
const userId = (await this.stateService.getUserId()) as UserId;
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(map((a) => a?.id)));
|
||||
|
||||
const logoutPromise = firstValueFrom(
|
||||
this.authService.authStatusFor$(userId).pipe(
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormControl, FormGroup } from "@angular/forms";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import { firstValueFrom, map, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/update-profile.request";
|
||||
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { ChangeAvatarDialogComponent } from "./change-avatar-dialog.component";
|
||||
@ -30,8 +29,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private stateService: StateService,
|
||||
private accountService: AccountService,
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
@ -39,7 +37,9 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
async ngOnInit() {
|
||||
this.profile = await this.apiService.getProfile();
|
||||
this.loading = false;
|
||||
this.fingerprintMaterial = await this.stateService.getUserId();
|
||||
this.fingerprintMaterial = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
this.formGroup.get("name").setValue(this.profile.name);
|
||||
this.formGroup.get("email").setValue(this.profile.email);
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ApiKeyComponent } from "./api-key.component";
|
||||
@ -21,7 +22,7 @@ export class SecurityKeysComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
private userVerificationService: UserVerificationService,
|
||||
private stateService: StateService,
|
||||
private accountService: AccountService,
|
||||
private apiService: ApiService,
|
||||
private dialogService: DialogService,
|
||||
) {}
|
||||
@ -31,7 +32,9 @@ export class SecurityKeysComponent implements OnInit {
|
||||
}
|
||||
|
||||
async viewUserApiKey() {
|
||||
const entityId = await this.stateService.getUserId();
|
||||
const entityId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
await ApiKeyComponent.open(this.dialogService, {
|
||||
data: {
|
||||
keyType: "user",
|
||||
@ -47,7 +50,9 @@ export class SecurityKeysComponent implements OnInit {
|
||||
}
|
||||
|
||||
async rotateUserApiKey() {
|
||||
const entityId = await this.stateService.getUserId();
|
||||
const entityId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
await ApiKeyComponent.open(this.dialogService, {
|
||||
data: {
|
||||
keyType: "user",
|
||||
|
@ -58,6 +58,14 @@ export abstract class StateService<T extends Account = Account> {
|
||||
setCryptoMasterKeyAuto: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
getDuckDuckGoSharedKey: (options?: StorageOptions) => Promise<string>;
|
||||
setDuckDuckGoSharedKey: (value: string, options?: StorageOptions) => Promise<void>;
|
||||
|
||||
/**
|
||||
* @deprecated Use `TokenService.hasAccessToken$()` or `AuthService.authStatusFor$` instead.
|
||||
*/
|
||||
getIsAuthenticated: (options?: StorageOptions) => Promise<boolean>;
|
||||
|
||||
/**
|
||||
* @deprecated Use `AccountService.activeAccount$` instead.
|
||||
*/
|
||||
getUserId: (options?: StorageOptions) => Promise<string>;
|
||||
}
|
||||
|
@ -138,8 +138,6 @@ describe("VaultTimeoutService", () => {
|
||||
return new BehaviorSubject<VaultTimeout>(accounts[userId]?.vaultTimeout);
|
||||
});
|
||||
|
||||
stateService.getUserId.mockResolvedValue(globalSetups?.userId);
|
||||
|
||||
// Set desired user active and known users on accounts service : note the only thing that matters here is that the ID are set
|
||||
if (globalSetups?.userId) {
|
||||
accountService.activeAccountSubject.next({
|
||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -178,7 +178,7 @@
|
||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||
"type-fest": "2.19.0",
|
||||
"typescript": "5.1.6",
|
||||
"url": "0.11.3",
|
||||
"url": "0.11.4",
|
||||
"util": "0.12.5",
|
||||
"wait-on": "8.0.1",
|
||||
"webpack": "5.94.0",
|
||||
@ -37794,14 +37794,17 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/url": {
|
||||
"version": "0.11.3",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz",
|
||||
"integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==",
|
||||
"version": "0.11.4",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz",
|
||||
"integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^1.4.1",
|
||||
"qs": "^6.11.2"
|
||||
"qs": "^6.12.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/url-parse": {
|
||||
|
@ -139,7 +139,7 @@
|
||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||
"type-fest": "2.19.0",
|
||||
"typescript": "5.1.6",
|
||||
"url": "0.11.3",
|
||||
"url": "0.11.4",
|
||||
"util": "0.12.5",
|
||||
"wait-on": "8.0.1",
|
||||
"webpack": "5.94.0",
|
||||
|
Loading…
Reference in New Issue
Block a user