1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-08 12:40:26 +00:00

key connector reactive

This commit is contained in:
Maciej Zieniuk
2025-03-25 11:16:51 +00:00
parent 1bda7d44fb
commit 60dc468814
6 changed files with 45 additions and 15 deletions

View File

@@ -733,6 +733,7 @@ export default class MainBackground {
this.badgeSettingsService = new BadgeSettingsService(this.stateProvider);
this.policyApiService = new PolicyApiService(this.policyService, this.apiService);
this.keyConnectorService = new KeyConnectorService(
this.accountService,
this.masterPasswordService,
this.keyService,
this.apiService,
@@ -742,6 +743,7 @@ export default class MainBackground {
this.keyGenerationService,
logoutCallback,
this.stateProvider,
this.messagingService,
);
const sdkClientFactory = flagEnabled("sdk")

View File

@@ -563,6 +563,7 @@ export class ServiceContainer {
this.policyApiService = new PolicyApiService(this.policyService, this.apiService);
this.keyConnectorService = new KeyConnectorService(
this.accountService,
this.masterPasswordService,
this.keyService,
this.apiService,
@@ -572,6 +573,7 @@ export class ServiceContainer {
this.keyGenerationService,
logoutCallback,
this.stateProvider,
this.messagingService,
);
this.twoFactorService = new TwoFactorService(

View File

@@ -977,6 +977,7 @@ const safeProviders: SafeProvider[] = [
provide: KeyConnectorServiceAbstraction,
useClass: KeyConnectorService,
deps: [
AccountServiceAbstraction,
InternalMasterPasswordServiceAbstraction,
KeyService,
ApiServiceAbstraction,
@@ -986,6 +987,7 @@ const safeProviders: SafeProvider[] = [
KeyGenerationServiceAbstraction,
LOGOUT_CALLBACK,
StateProvider,
MessagingServiceAbstraction,
],
}),
safeProvider({

View File

@@ -3,6 +3,7 @@ import { firstValueFrom, of } from "rxjs";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { KeyService } from "@bitwarden/key-management";
import { FakeAccountService, FakeStateProvider, mockAccountServiceWith } from "../../../../spec";
@@ -36,6 +37,7 @@ describe("KeyConnectorService", () => {
const logService = mock<LogService>();
const organizationService = mock<OrganizationService>();
const keyGenerationService = mock<KeyGenerationService>();
const messagingService = mock<MessagingService>();
let stateProvider: FakeStateProvider;
@@ -57,6 +59,7 @@ describe("KeyConnectorService", () => {
stateProvider = new FakeStateProvider(accountService);
keyConnectorService = new KeyConnectorService(
accountService,
masterPasswordService,
keyService,
apiService,
@@ -66,6 +69,7 @@ describe("KeyConnectorService", () => {
keyGenerationService,
async () => {},
stateProvider,
messagingService,
);
});

View File

@@ -1,8 +1,10 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { firstValueFrom } from "rxjs";
import { combineLatest, filter, firstValueFrom, of, switchMap } from "rxjs";
import { LogoutReason } from "@bitwarden/auth/common";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import {
Argon2KdfConfig,
KdfConfig,
@@ -58,6 +60,7 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
private convertAccountToKeyConnectorState: ActiveUserState<boolean>;
constructor(
accountService: AccountService,
private masterPasswordService: InternalMasterPasswordServiceAbstraction,
private keyService: KeyService,
private apiService: ApiService,
@@ -67,11 +70,40 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
private keyGenerationService: KeyGenerationService,
private logoutCallback: (logoutReason: LogoutReason, userId?: string) => Promise<void>,
private stateProvider: StateProvider,
private messagingService: MessagingService,
) {
this.usesKeyConnectorState = this.stateProvider.getActive(USES_KEY_CONNECTOR);
this.convertAccountToKeyConnectorState = this.stateProvider.getActive(
CONVERT_ACCOUNT_TO_KEY_CONNECTOR,
);
accountService.activeAccount$
.pipe(
filter((account) => account != null),
switchMap((account) =>
combineLatest([
of(account.id),
this.organizationService
.organizations$(account.id)
.pipe(filter((organizations) => organizations != null)),
tokenService.hasAccessToken$(account.id).pipe(filter((hasToken) => hasToken)),
]),
),
switchMap(async ([userId, organizations]) => {
const needsMigration = await this.userNeedsMigration(userId, organizations);
if (needsMigration) {
await this.setConvertAccountRequired(true, userId);
} else {
await this.removeConvertAccountRequired(userId);
}
return needsMigration;
}),
)
.subscribe((needsMigration) => {
if (needsMigration) {
this.messagingService.send("convertAccountToKeyConnector");
}
});
}
async setUsesKeyConnector(usesKeyConnector: boolean, userId: UserId) {
@@ -84,7 +116,7 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
);
}
async userNeedsMigration(userId: UserId, organizations: Organization[]) {
async userNeedsMigration(userId: UserId, organizations: Organization[]): Promise<boolean> {
const loggedInUsingSso = await this.tokenService.getIsExternal(userId);
const requiredByOrganization = this.findManagingOrganization(organizations) != null;
const userIsNotUsingKeyConnector = !(await this.getUsesKeyConnector(userId));

View File

@@ -7,7 +7,6 @@ import {
CollectionData,
CollectionDetailsResponse,
} from "@bitwarden/admin-console/common";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { KeyService } from "@bitwarden/key-management";
// FIXME: remove `src` and fix import
@@ -214,14 +213,7 @@ export class DefaultSyncService extends CoreSyncService {
await this.providerService.save(providers, response.id);
const organizations = await this.syncProfileOrganizations(response, response.id);
if (await this.keyConnectorService.userNeedsMigration(response.id, organizations)) {
await this.keyConnectorService.setConvertAccountRequired(true, response.id);
this.messageSender.send("convertAccountToKeyConnector");
} else {
await this.keyConnectorService.removeConvertAccountRequired(response.id);
}
await this.syncProfileOrganizations(response, response.id);
}
private async setForceSetPasswordReasonIfNeeded(profileResponse: ProfileResponse) {
@@ -292,10 +284,6 @@ export class DefaultSyncService extends CoreSyncService {
});
await this.organizationService.replace(organizations, userId);
return Object.values(organizations).map(
(organizationData) => new Organization(organizationData),
);
}
private async syncFolders(response: FolderResponse[], userId: UserId) {