mirror of
https://github.com/bitwarden/browser
synced 2026-02-08 04:33:38 +00:00
reactive key connector service
This commit is contained in:
@@ -67,9 +67,6 @@ export class ConvertToKeyConnectorCommand {
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.keyConnectorService.removeConvertAccountRequired(this.userId);
|
||||
await this.keyConnectorService.setUsesKeyConnector(true, this.userId);
|
||||
|
||||
// Update environment URL - required for api key login
|
||||
const env = await firstValueFrom(this.environmentService.environment$);
|
||||
const urls = env.getUrls();
|
||||
|
||||
@@ -61,7 +61,7 @@ export class RemovePasswordComponent implements OnInit {
|
||||
return this.continuing || this.leaving;
|
||||
}
|
||||
|
||||
async convert() {
|
||||
convert = async () => {
|
||||
this.continuing = true;
|
||||
|
||||
try {
|
||||
@@ -71,7 +71,6 @@ export class RemovePasswordComponent implements OnInit {
|
||||
variant: "success",
|
||||
message: this.i18nService.t("removedMasterPassword"),
|
||||
});
|
||||
await this.keyConnectorService.removeConvertAccountRequired(this.activeUserId);
|
||||
|
||||
await this.router.navigate([""]);
|
||||
} catch (e) {
|
||||
@@ -79,9 +78,9 @@ export class RemovePasswordComponent implements OnInit {
|
||||
|
||||
this.handleActionError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
async leave() {
|
||||
leave = async () => {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: this.organization.name,
|
||||
content: { key: "leaveOrganizationConfirmation" },
|
||||
@@ -95,12 +94,12 @@ export class RemovePasswordComponent implements OnInit {
|
||||
this.leaving = true;
|
||||
try {
|
||||
await this.organizationApiService.leave(this.organization.id);
|
||||
await this.keyConnectorService.removeConvertAccountRequired(this.activeUserId);
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
message: this.i18nService.t("leftOrganization"),
|
||||
});
|
||||
await this.keyConnectorService.removeConvertAccountRequired(this.activeUserId);
|
||||
|
||||
await this.router.navigate([""]);
|
||||
} catch (e) {
|
||||
@@ -108,7 +107,7 @@ export class RemovePasswordComponent implements OnInit {
|
||||
|
||||
this.handleActionError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleActionError(e: unknown) {
|
||||
let message = "";
|
||||
|
||||
@@ -11,8 +11,6 @@ export abstract class KeyConnectorService {
|
||||
|
||||
abstract migrateUser(userId: UserId): Promise<void>;
|
||||
|
||||
abstract userNeedsMigration(userId: UserId, organizations: Organization[]): Promise<boolean>;
|
||||
|
||||
abstract convertNewSsoUserToKeyConnector(
|
||||
tokenResponse: IdentityTokenResponse,
|
||||
orgId: string,
|
||||
@@ -21,8 +19,6 @@ export abstract class KeyConnectorService {
|
||||
|
||||
abstract setUsesKeyConnector(enabled: boolean, userId: UserId): Promise<void>;
|
||||
|
||||
abstract setConvertAccountRequired(status: boolean | null, userId: UserId): Promise<void>;
|
||||
|
||||
abstract getConvertAccountRequired(): Promise<boolean>;
|
||||
|
||||
abstract removeConvertAccountRequired(userId: UserId): Promise<void>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { combineLatest, filter, firstValueFrom, of, switchMap } from "rxjs";
|
||||
import { combineLatest, distinctUntilChanged, filter, firstValueFrom, of, switchMap } from "rxjs";
|
||||
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
@@ -43,6 +43,7 @@ export const USES_KEY_CONNECTOR = new UserKeyDefinition<boolean | null>(
|
||||
{
|
||||
deserializer: (usesKeyConnector) => usesKeyConnector,
|
||||
clearOn: ["logout"],
|
||||
cleanupDelayMs: 0,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -52,6 +53,7 @@ export const CONVERT_ACCOUNT_TO_KEY_CONNECTOR = new UserKeyDefinition<boolean |
|
||||
{
|
||||
deserializer: (convertAccountToKeyConnector) => convertAccountToKeyConnector,
|
||||
clearOn: ["logout"],
|
||||
cleanupDelayMs: 0,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -86,24 +88,29 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
this.organizationService
|
||||
.organizations$(account.id)
|
||||
.pipe(filter((organizations) => organizations != null)),
|
||||
this.stateProvider
|
||||
.getUserState$(USES_KEY_CONNECTOR, account.id)
|
||||
.pipe(filter((usesKeyConnector) => usesKeyConnector != null)),
|
||||
tokenService.hasAccessToken$(account.id).pipe(filter((hasToken) => hasToken)),
|
||||
]),
|
||||
),
|
||||
switchMap(async ([userId, organizations]) => {
|
||||
const needsMigration = await this.userNeedsMigration(userId, organizations);
|
||||
distinctUntilChanged(),
|
||||
switchMap(async ([userId, organizations, usesKeyConnector]) => {
|
||||
const loggedInUsingSso = await this.tokenService.getIsExternal(userId);
|
||||
const requiredByOrganization = this.findManagingOrganization(organizations) != null;
|
||||
const userIsNotUsingKeyConnector = !usesKeyConnector;
|
||||
|
||||
const needsMigration =
|
||||
loggedInUsingSso && requiredByOrganization && userIsNotUsingKeyConnector;
|
||||
if (needsMigration) {
|
||||
await this.setConvertAccountRequired(true, userId);
|
||||
this.messagingService.send("convertAccountToKeyConnector");
|
||||
} else {
|
||||
await this.removeConvertAccountRequired(userId);
|
||||
}
|
||||
return needsMigration;
|
||||
}),
|
||||
)
|
||||
.subscribe((needsMigration) => {
|
||||
if (needsMigration) {
|
||||
this.messagingService.send("convertAccountToKeyConnector");
|
||||
}
|
||||
});
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
async setUsesKeyConnector(usesKeyConnector: boolean, userId: UserId) {
|
||||
@@ -116,14 +123,6 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
return loggedInUsingSso && requiredByOrganization && userIsNotUsingKeyConnector;
|
||||
}
|
||||
|
||||
async migrateUser(userId: UserId) {
|
||||
const organization = await this.getManagingOrganization(userId);
|
||||
const masterKey = await firstValueFrom(this.masterPasswordService.masterKey$(userId));
|
||||
@@ -139,6 +138,9 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
}
|
||||
|
||||
await this.apiService.postConvertToKeyConnector();
|
||||
|
||||
await this.setUsesKeyConnector(true, userId);
|
||||
await this.removeConvertAccountRequired(userId);
|
||||
}
|
||||
|
||||
// TODO: UserKey should be renamed to MasterKey and typed accordingly
|
||||
@@ -210,10 +212,6 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
await this.apiService.postSetKeyConnectorKey(setPasswordRequest);
|
||||
}
|
||||
|
||||
async setConvertAccountRequired(status: boolean | null, userId: UserId) {
|
||||
await this.stateProvider.setUserState(CONVERT_ACCOUNT_TO_KEY_CONNECTOR, status, userId);
|
||||
}
|
||||
|
||||
getConvertAccountRequired(): Promise<boolean> {
|
||||
return firstValueFrom(this.convertAccountToKeyConnectorState.state$);
|
||||
}
|
||||
@@ -222,6 +220,10 @@ export class KeyConnectorService implements KeyConnectorServiceAbstraction {
|
||||
await this.setConvertAccountRequired(null, userId);
|
||||
}
|
||||
|
||||
private async setConvertAccountRequired(status: boolean | null, userId: UserId) {
|
||||
await this.stateProvider.setUserState(CONVERT_ACCOUNT_TO_KEY_CONNECTOR, status, userId);
|
||||
}
|
||||
|
||||
private handleKeyConnectorError(e: any) {
|
||||
this.logService.error(e);
|
||||
if (this.logoutCallback != null) {
|
||||
|
||||
Reference in New Issue
Block a user