mirror of
https://github.com/bitwarden/browser.git
synced 2024-10-28 07:49:41 +01:00
WIP updating callers
This commit is contained in:
parent
902f49eb00
commit
5b0003b467
@ -8,6 +8,7 @@ import { Observable, combineLatest, first, map, switchMap } from "rxjs";
|
||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
@ -49,6 +50,8 @@ export class AssignCollections {
|
||||
/** Params needed to populate the assign collections component */
|
||||
params: CollectionAssignmentParams;
|
||||
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
constructor(
|
||||
private location: Location,
|
||||
private collectionService: CollectionService,
|
||||
@ -70,7 +73,7 @@ export class AssignCollections {
|
||||
),
|
||||
);
|
||||
|
||||
combineLatest([cipher$, this.collectionService.decryptedCollections$])
|
||||
combineLatest([cipher$, this.collectionService.decryptedCollections$(this.activeUserId$)])
|
||||
.pipe(takeUntilDestroyed(), first())
|
||||
.subscribe(([cipherView, collections]) => {
|
||||
let availableCollections = collections.filter((c) => !c.readOnly);
|
||||
|
@ -22,6 +22,9 @@ import { BrowserApi } from "../../../../platform/browser/browser-api";
|
||||
import BrowserPopupUtils from "../../../../platform/popup/browser-popup-utils";
|
||||
import { VaultBrowserStateService } from "../../../services/vault-browser-state.service";
|
||||
import { VaultFilterService } from "../../../services/vault-filter.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
const ComponentId = "VaultItemsComponent";
|
||||
|
||||
@ -49,6 +52,8 @@ export class VaultItemsComponent extends BaseVaultItemsComponent implements OnIn
|
||||
private applySavedState = true;
|
||||
private scrollingContainer = "cdk-virtual-scroll-viewport";
|
||||
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
constructor(
|
||||
searchService: SearchService,
|
||||
private organizationService: OrganizationService,
|
||||
@ -64,6 +69,7 @@ export class VaultItemsComponent extends BaseVaultItemsComponent implements OnIn
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
cipherService: CipherService,
|
||||
private vaultFilterService: VaultFilterService,
|
||||
private accountService: AccountService,
|
||||
) {
|
||||
super(searchService, cipherService);
|
||||
this.applySavedState =
|
||||
@ -133,7 +139,10 @@ export class VaultItemsComponent extends BaseVaultItemsComponent implements OnIn
|
||||
this.showVaultFilter = false;
|
||||
this.collectionId = params.collectionId;
|
||||
this.searchPlaceholder = this.i18nService.t("searchCollection");
|
||||
const collectionNode = await this.collectionService.getNested(this.collectionId);
|
||||
const allCollections = await firstValueFrom(
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
);
|
||||
const collectionNode = this.collectionService.getNested(allCollections, this.collectionId);
|
||||
if (collectionNode != null && collectionNode.node != null) {
|
||||
this.groupingTitle = collectionNode.node.name;
|
||||
this.nestedCollections =
|
||||
|
@ -8,8 +8,8 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { ObservableTracker } from "@bitwarden/common/spec";
|
||||
import { CipherId } from "@bitwarden/common/types/guid";
|
||||
import { mockAccountServiceWith, ObservableTracker } from "@bitwarden/common/spec";
|
||||
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
@ -20,6 +20,7 @@ import { BrowserApi } from "../../../platform/browser/browser-api";
|
||||
import { VaultPopupAutofillService } from "./vault-popup-autofill.service";
|
||||
import { VaultPopupItemsService } from "./vault-popup-items.service";
|
||||
import { VaultPopupListFiltersService } from "./vault-popup-list-filters.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
|
||||
describe("VaultPopupItemsService", () => {
|
||||
let testBed: TestBed;
|
||||
@ -39,6 +40,7 @@ describe("VaultPopupItemsService", () => {
|
||||
const collectionService = mock<CollectionService>();
|
||||
const vaultAutofillServiceMock = mock<VaultPopupAutofillService>();
|
||||
const syncServiceMock = mock<SyncService>();
|
||||
const accountServiceMock = mockAccountServiceWith("UserId" as UserId);
|
||||
|
||||
beforeEach(() => {
|
||||
allCiphers = cipherFactory(10);
|
||||
@ -90,7 +92,7 @@ describe("VaultPopupItemsService", () => {
|
||||
];
|
||||
|
||||
organizationServiceMock.organizations$ = new BehaviorSubject([mockOrg]);
|
||||
collectionService.decryptedCollections$ = new BehaviorSubject(mockCollections);
|
||||
collectionService.decryptedCollections$.mockReturnValue(new BehaviorSubject(mockCollections));
|
||||
|
||||
activeUserLastSync$ = new BehaviorSubject(new Date());
|
||||
syncServiceMock.activeUserLastSync$.mockReturnValue(activeUserLastSync$);
|
||||
@ -105,6 +107,7 @@ describe("VaultPopupItemsService", () => {
|
||||
{ provide: CollectionService, useValue: collectionService },
|
||||
{ provide: VaultPopupAutofillService, useValue: vaultAutofillServiceMock },
|
||||
{ provide: SyncService, useValue: syncServiceMock },
|
||||
{ provide: AccountService, useValue: accountServiceMock },
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -36,6 +36,8 @@ import { PopupCipherView } from "../views/popup-cipher.view";
|
||||
|
||||
import { VaultPopupAutofillService } from "./vault-popup-autofill.service";
|
||||
import { MY_VAULT_ID, VaultPopupListFiltersService } from "./vault-popup-list-filters.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
|
||||
/**
|
||||
* Service for managing the various item lists on the new Vault tab in the browser popup.
|
||||
@ -45,6 +47,7 @@ import { MY_VAULT_ID, VaultPopupListFiltersService } from "./vault-popup-list-fi
|
||||
})
|
||||
export class VaultPopupItemsService {
|
||||
private _searchText$ = new BehaviorSubject<string>("");
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
/**
|
||||
* Subject that emits whenever new ciphers are being processed/filtered.
|
||||
@ -90,7 +93,7 @@ export class VaultPopupItemsService {
|
||||
switchMap((ciphers) =>
|
||||
combineLatest([
|
||||
this.organizationService.organizations$,
|
||||
this.collectionService.decryptedCollections$,
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
]).pipe(
|
||||
map(([organizations, collections]) => {
|
||||
const orgMap = Object.fromEntries(organizations.map((org) => [org.id, org]));
|
||||
@ -260,6 +263,7 @@ export class VaultPopupItemsService {
|
||||
private collectionService: CollectionService,
|
||||
private vaultPopupAutofillService: VaultPopupAutofillService,
|
||||
private syncService: SyncService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
applyFilter(newSearchText: string) {
|
||||
|
@ -7,11 +7,15 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
|
||||
@ -26,8 +30,8 @@ describe("VaultPopupListFiltersService", () => {
|
||||
const policyAppliesToActiveUser$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
const collectionService = {
|
||||
decryptedCollections$,
|
||||
getAllNested: () => Promise.resolve([]),
|
||||
decryptedCollections$: () => decryptedCollections$,
|
||||
getAllNested: () => [] as TreeNode<CollectionView>[],
|
||||
} as unknown as CollectionService;
|
||||
|
||||
const folderService = {
|
||||
@ -50,13 +54,15 @@ describe("VaultPopupListFiltersService", () => {
|
||||
policyAppliesToActiveUser$: jest.fn(() => policyAppliesToActiveUser$),
|
||||
};
|
||||
|
||||
const accountService = mockAccountServiceWith("userId" as UserId);
|
||||
|
||||
beforeEach(() => {
|
||||
memberOrganizations$.next([]);
|
||||
decryptedCollections$.next([]);
|
||||
policyAppliesToActiveUser$.next(false);
|
||||
policyService.policyAppliesToActiveUser$.mockClear();
|
||||
|
||||
collectionService.getAllNested = () => Promise.resolve([]);
|
||||
collectionService.getAllNested = () => [] as TreeNode<CollectionView>[];
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{
|
||||
@ -84,6 +90,10 @@ describe("VaultPopupListFiltersService", () => {
|
||||
useValue: policyService,
|
||||
},
|
||||
{ provide: FormBuilder, useClass: FormBuilder },
|
||||
{
|
||||
provide: AccountService,
|
||||
useValue: accountService,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@ -276,13 +286,11 @@ describe("VaultPopupListFiltersService", () => {
|
||||
decryptedCollections$.next(testCollections);
|
||||
|
||||
collectionService.getAllNested = () =>
|
||||
Promise.resolve(
|
||||
testCollections.map((c) => ({
|
||||
children: [],
|
||||
node: c,
|
||||
parent: null,
|
||||
})),
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it("returns all collections", (done) => {
|
||||
|
@ -1,15 +1,7 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import {
|
||||
combineLatest,
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
Observable,
|
||||
startWith,
|
||||
switchMap,
|
||||
tap,
|
||||
} from "rxjs";
|
||||
import { combineLatest, distinctUntilChanged, map, Observable, startWith, tap } from "rxjs";
|
||||
|
||||
import { CollectionService, Collection, CollectionView } from "@bitwarden/admin-console/common";
|
||||
import { DynamicTreeNode } from "@bitwarden/angular/vault/vault-filter/models/dynamic-tree-node.model";
|
||||
@ -17,6 +9,8 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@ -81,6 +75,8 @@ export class VaultPopupListFiltersService {
|
||||
map((ciphers) => Object.values(ciphers)),
|
||||
);
|
||||
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
constructor(
|
||||
private folderService: FolderService,
|
||||
private cipherService: CipherService,
|
||||
@ -89,6 +85,7 @@ export class VaultPopupListFiltersService {
|
||||
private collectionService: CollectionService,
|
||||
private formBuilder: FormBuilder,
|
||||
private policyService: PolicyService,
|
||||
private accountService: AccountService,
|
||||
) {
|
||||
this.filterForm.controls.organization.valueChanges
|
||||
.pipe(takeUntilDestroyed())
|
||||
@ -302,7 +299,7 @@ export class VaultPopupListFiltersService {
|
||||
previousFilter.organization?.id === currentFilter.organization?.id,
|
||||
),
|
||||
),
|
||||
this.collectionService.decryptedCollections$,
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
]).pipe(
|
||||
map(([filters, allCollections]) => {
|
||||
const organizationId = filters.organization?.id ?? null;
|
||||
@ -314,8 +311,8 @@ export class VaultPopupListFiltersService {
|
||||
|
||||
return collections;
|
||||
}),
|
||||
switchMap(async (collections) => {
|
||||
const nestedCollections = await this.collectionService.getAllNested(collections);
|
||||
map((collections) => {
|
||||
const nestedCollections = this.collectionService.getAllNested(collections);
|
||||
|
||||
return new DynamicTreeNode<CollectionView>({
|
||||
fullList: collections,
|
||||
|
@ -22,7 +22,7 @@ export class VaultFilterService extends BaseVaultFilterService {
|
||||
collectionService: CollectionService,
|
||||
policyService: PolicyService,
|
||||
stateProvider: StateProvider,
|
||||
private accountService: AccountService,
|
||||
accountService: AccountService,
|
||||
) {
|
||||
super(
|
||||
organizationService,
|
||||
@ -31,6 +31,7 @@ export class VaultFilterService extends BaseVaultFilterService {
|
||||
collectionService,
|
||||
policyService,
|
||||
stateProvider,
|
||||
accountService,
|
||||
);
|
||||
this.vaultFilter.myVaultOnly = false;
|
||||
this.vaultFilter.selectedOrganizationId = null;
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { CollectionService, CollectionView } from "@bitwarden/admin-console/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@ -25,6 +26,8 @@ export class CollectionsComponent implements OnInit {
|
||||
collections: CollectionView[] = [];
|
||||
organization: Organization;
|
||||
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
protected cipherDomain: Cipher;
|
||||
|
||||
constructor(
|
||||
@ -45,9 +48,7 @@ export class CollectionsComponent implements OnInit {
|
||||
async load() {
|
||||
this.cipherDomain = await this.loadCipher();
|
||||
this.collectionIds = this.loadCipherCollections();
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
this.cipher = await this.cipherDomain.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(this.cipherDomain, activeUserId),
|
||||
);
|
||||
@ -113,7 +114,9 @@ export class CollectionsComponent implements OnInit {
|
||||
}
|
||||
|
||||
protected async loadCollections() {
|
||||
const allCollections = await this.collectionService.getAllDecrypted();
|
||||
const allCollections = await firstValueFrom(
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
);
|
||||
return allCollections.filter(
|
||||
(c) => !c.readOnly && c.organizationId === this.cipher.organizationId,
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@ -26,6 +27,7 @@ export class ShareComponent implements OnInit, OnDestroy {
|
||||
organizations$: Observable<Organization[]>;
|
||||
|
||||
protected writeableCollections: Checkable<CollectionView>[] = [];
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
private _destroy = new Subject<void>();
|
||||
|
||||
@ -49,7 +51,9 @@ export class ShareComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async load() {
|
||||
const allCollections = await this.collectionService.getAllDecrypted();
|
||||
const allCollections = await firstValueFrom(
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
);
|
||||
this.writeableCollections = allCollections.map((c) => c).filter((c) => !c.readOnly);
|
||||
|
||||
this.organizations$ = this.organizationService.memberOrganizations$.pipe(
|
||||
|
@ -39,6 +39,7 @@ import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note.
|
||||
import { CipherAuthorizationService } from "@bitwarden/common/vault/services/cipher-authorization.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
|
||||
@Directive()
|
||||
export class AddEditComponent implements OnInit, OnDestroy {
|
||||
@ -98,6 +99,8 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
private personalOwnershipPolicyAppliesToActiveUser: boolean;
|
||||
private previousCipherId: string;
|
||||
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
get fido2CredentialCreationDateValue(): string {
|
||||
const dateCreated = this.i18nService.t("dateCreated");
|
||||
const creationDate = this.datePipe.transform(
|
||||
@ -253,9 +256,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
if (this.cipher == null) {
|
||||
if (this.editMode) {
|
||||
const cipher = await this.loadCipher();
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
this.cipher = await cipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId),
|
||||
);
|
||||
@ -391,9 +392,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
this.cipher.id = null;
|
||||
}
|
||||
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
const cipher = await this.encryptCipher(activeUserId);
|
||||
try {
|
||||
this.formPromise = this.saveCipher(cipher);
|
||||
@ -672,7 +671,9 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
protected async loadCollections() {
|
||||
const allCollections = await this.collectionService.getAllDecrypted();
|
||||
const allCollections = await firstValueFrom(
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
);
|
||||
return allCollections.filter((c) => !c.readOnly);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,8 @@ import {
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { ActiveUserState, StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
@ -30,6 +32,8 @@ export class VaultFilterService implements DeprecatedVaultFilterServiceAbstracti
|
||||
private readonly collapsedGroupings$: Observable<Set<string>> =
|
||||
this.collapsedGroupingsState.state$.pipe(map((c) => new Set(c)));
|
||||
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
constructor(
|
||||
protected organizationService: OrganizationService,
|
||||
protected folderService: FolderService,
|
||||
@ -37,6 +41,7 @@ export class VaultFilterService implements DeprecatedVaultFilterServiceAbstracti
|
||||
protected collectionService: CollectionService,
|
||||
protected policyService: PolicyService,
|
||||
protected stateProvider: StateProvider,
|
||||
protected accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async storeCollapsedFilterNodes(collapsedFilterNodes: Set<string>): Promise<void> {
|
||||
@ -85,14 +90,16 @@ export class VaultFilterService implements DeprecatedVaultFilterServiceAbstracti
|
||||
}
|
||||
|
||||
async buildCollections(organizationId?: string): Promise<DynamicTreeNode<CollectionView>> {
|
||||
const storedCollections = await this.collectionService.getAllDecrypted();
|
||||
const storedCollections = await firstValueFrom(
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
);
|
||||
let collections: CollectionView[];
|
||||
if (organizationId != null) {
|
||||
collections = storedCollections.filter((c) => c.organizationId === organizationId);
|
||||
} else {
|
||||
collections = storedCollections;
|
||||
}
|
||||
const nestedCollections = await this.collectionService.getAllNested(collections);
|
||||
const nestedCollections = this.collectionService.getAllNested(collections);
|
||||
return new DynamicTreeNode<CollectionView>({
|
||||
fullList: collections,
|
||||
nestedList: nestedCollections,
|
||||
|
@ -45,6 +45,24 @@ const LOGGED_OUT_INFO: AccountInfo = {
|
||||
name: undefined,
|
||||
};
|
||||
|
||||
/**
|
||||
* An rxjs map operator that extracts the UserId from an account, or throws if the account or UserId are null.
|
||||
*/
|
||||
export const getUserId = map<{ id: UserId | undefined }, UserId>((account) => {
|
||||
if (account?.id == null) {
|
||||
throw new Error("Null account or account ID");
|
||||
}
|
||||
|
||||
return account.id;
|
||||
});
|
||||
|
||||
/**
|
||||
* An rxjs map operator that extracts the UserId from an account, or returns undefined if the account or UserId are null.
|
||||
*/
|
||||
export const getOptionalUserId = map<{ id: UserId | undefined }, UserId | undefined>(
|
||||
(account) => account?.id ?? undefined,
|
||||
);
|
||||
|
||||
export class AccountServiceImplementation implements InternalAccountService {
|
||||
private accountsState: GlobalState<Record<UserId, AccountInfo>>;
|
||||
private activeAccountIdState: GlobalState<UserId | undefined>;
|
||||
|
@ -6,6 +6,7 @@ import { ApiService } from "../../abstractions/api.service";
|
||||
import { AccountService } from "../../auth/abstractions/account.service";
|
||||
import { AuthService } from "../../auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "../../auth/enums/authentication-status";
|
||||
import { getUserId } from "../../auth/services/account.service";
|
||||
import {
|
||||
SyncCipherNotification,
|
||||
SyncFolderNotification,
|
||||
@ -149,7 +150,10 @@ export abstract class CoreSyncService implements SyncService {
|
||||
notification.collectionIds != null &&
|
||||
notification.collectionIds.length > 0
|
||||
) {
|
||||
const collections = await this.collectionService.getAll();
|
||||
const activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
const collections = await firstValueFrom(
|
||||
this.collectionService.encryptedCollections$(activeUserId$),
|
||||
);
|
||||
if (collections != null) {
|
||||
for (let i = 0; i < collections.length; i++) {
|
||||
if (notification.collectionIds.indexOf(collections[i].id) > -1) {
|
||||
|
@ -134,9 +134,13 @@ export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
|
||||
if (userId == null || userId === currentUserId) {
|
||||
await this.searchService.clearIndex();
|
||||
await this.folderService.clearCache();
|
||||
await this.collectionService.clearActiveUserCache();
|
||||
}
|
||||
|
||||
// TODO: is the userId ever null here? Surely a null userId cannot be authenticated?
|
||||
// Also MasterPasswordService throws an exception if the userId is null and hasn't caused any issues
|
||||
// TODO: why do these other services clear lockingUserId and not userId?
|
||||
await this.collectionService.clearDecryptedState(userId);
|
||||
|
||||
await this.masterPasswordService.clearMasterKey(lockingUserId);
|
||||
|
||||
await this.stateService.setUserKeyAutoUnlock(null, { userId: lockingUserId });
|
||||
|
@ -72,6 +72,7 @@ import {
|
||||
ImportSuccessDialogComponent,
|
||||
} from "./dialog";
|
||||
import { ImportLastPassComponent } from "./lastpass";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
|
||||
const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
@ -129,6 +130,8 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
collections$: Observable<CollectionView[]>;
|
||||
organizations$: Observable<Organization[]>;
|
||||
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
private _organizationId: string;
|
||||
|
||||
get organizationId(): string {
|
||||
@ -205,6 +208,7 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
@Optional()
|
||||
protected importCollectionService: ImportCollectionServiceAbstraction,
|
||||
protected toastService: ToastService,
|
||||
protected accountService: AccountService,
|
||||
) {}
|
||||
|
||||
protected get importBlockedByPolicy(): boolean {
|
||||
@ -272,10 +276,10 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
}
|
||||
|
||||
if (value) {
|
||||
this.collections$ = Utils.asyncToObservable(() =>
|
||||
this.collectionService
|
||||
.getAllDecrypted()
|
||||
.then((decryptedCollections) =>
|
||||
this.collections$ = this.collectionService
|
||||
.decryptedCollections$(this.activeUserId$)
|
||||
.pipe(
|
||||
map((decryptedCollections) =>
|
||||
decryptedCollections
|
||||
.filter((c2) => c2.organizationId === value && c2.manage)
|
||||
.sort(Utils.getSortFunction(this.i18nService, "name")),
|
||||
|
@ -33,11 +33,14 @@ import {
|
||||
import { BaseVaultExportService } from "./base-vault-export.service";
|
||||
import { OrganizationVaultExportServiceAbstraction } from "./org-vault-export.service.abstraction";
|
||||
import { ExportFormat } from "./vault-export.service.abstraction";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
|
||||
export class OrganizationVaultExportService
|
||||
extends BaseVaultExportService
|
||||
implements OrganizationVaultExportServiceAbstraction
|
||||
{
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
constructor(
|
||||
private cipherService: CipherService,
|
||||
private apiService: ApiService,
|
||||
@ -185,9 +188,13 @@ export class OrganizationVaultExportService
|
||||
const promises = [];
|
||||
|
||||
promises.push(
|
||||
this.collectionService.getAllDecrypted().then(async (collections) => {
|
||||
decCollections = collections.filter((c) => c.organizationId == organizationId && c.manage);
|
||||
}),
|
||||
firstValueFrom(this.collectionService.decryptedCollections$(this.activeUserId$)).then(
|
||||
(collections) => {
|
||||
decCollections = collections.filter(
|
||||
(c) => c.organizationId == organizationId && c.manage,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
promises.push(
|
||||
@ -217,9 +224,13 @@ export class OrganizationVaultExportService
|
||||
const promises = [];
|
||||
|
||||
promises.push(
|
||||
this.collectionService.getAll().then((collections) => {
|
||||
encCollections = collections.filter((c) => c.organizationId == organizationId && c.manage);
|
||||
}),
|
||||
firstValueFrom(this.collectionService.encryptedCollections$(this.activeUserId$)).then(
|
||||
(collections) => {
|
||||
encCollections = collections.filter(
|
||||
(c) => c.organizationId == organizationId && c.manage,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
promises.push(
|
||||
|
@ -21,6 +21,8 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@ -150,6 +152,8 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
{ name: ".json (Encrypted)", value: "encrypted_json" },
|
||||
];
|
||||
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
private onlyManagedCollections = true;
|
||||
|
||||
@ -167,6 +171,7 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
protected dialogService: DialogService,
|
||||
protected organizationService: OrganizationService,
|
||||
private collectionService: CollectionService,
|
||||
protected accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -204,7 +209,7 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
}
|
||||
|
||||
this.organizations$ = combineLatest({
|
||||
collections: this.collectionService.decryptedCollections$,
|
||||
collections: this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
memberOrganizations: this.organizationService.memberOrganizations$,
|
||||
}).pipe(
|
||||
map(({ collections, memberOrganizations }) => {
|
||||
|
@ -5,6 +5,8 @@ import { CollectionService } from "@bitwarden/admin-console/common";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { OrganizationUserStatusType, PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { CipherId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
@ -29,6 +31,9 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
||||
private cipherService: CipherService = inject(CipherService);
|
||||
private folderService: FolderService = inject(FolderService);
|
||||
private collectionService: CollectionService = inject(CollectionService);
|
||||
private accountService = inject(AccountService);
|
||||
|
||||
protected activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
async buildConfig(
|
||||
mode: CipherFormMode,
|
||||
@ -39,9 +44,9 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
||||
await firstValueFrom(
|
||||
combineLatest([
|
||||
this.organizations$,
|
||||
this.collectionService.encryptedCollections$.pipe(
|
||||
this.collectionService.encryptedCollections$(this.activeUserId$).pipe(
|
||||
switchMap((c) =>
|
||||
this.collectionService.decryptedCollections$.pipe(
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$).pipe(
|
||||
filter((d) => d.length === c.length), // Ensure all collections have been decrypted
|
||||
),
|
||||
),
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, Input, OnChanges, OnDestroy } from "@angular/core";
|
||||
import { firstValueFrom, Observable, Subject, takeUntil } from "rxjs";
|
||||
import { firstValueFrom, map, Observable, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { CollectionService, CollectionView } from "@bitwarden/admin-console/common";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { isCardExpired } from "@bitwarden/common/autofill/utils";
|
||||
import { CollectionId } from "@bitwarden/common/types/guid";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
@ -56,10 +57,13 @@ export class CipherViewComponent implements OnChanges, OnDestroy {
|
||||
private destroyed$: Subject<void> = new Subject();
|
||||
cardIsExpired: boolean = false;
|
||||
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
|
||||
constructor(
|
||||
private organizationService: OrganizationService,
|
||||
private collectionService: CollectionService,
|
||||
private folderService: FolderService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async ngOnChanges() {
|
||||
@ -98,8 +102,12 @@ export class CipherViewComponent implements OnChanges, OnDestroy {
|
||||
(!this.collections || this.collections.length === 0)
|
||||
) {
|
||||
this.collections = await firstValueFrom(
|
||||
this.collectionService.decryptedCollectionViews$(
|
||||
this.cipher.collectionIds as CollectionId[],
|
||||
this.collectionService
|
||||
.decryptedCollections$(this.activeUserId$)
|
||||
.pipe(
|
||||
map((allCollections) =>
|
||||
allCollections.filter((c) => this.cipher.collectionIds.includes(c.id)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -28,8 +28,9 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enums";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherId, CollectionId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherId, CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import {
|
||||
@ -170,7 +171,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
|
||||
private get selectedOrgId(): OrganizationId {
|
||||
return this.formGroup.getRawValue().selectedOrg || this.params.organizationId;
|
||||
}
|
||||
private activeUserId: UserId;
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
@ -184,10 +185,6 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
|
||||
const onlyPersonalItems = this.params.ciphers.every((c) => c.organizationId == null);
|
||||
|
||||
if (this.selectedOrgId === MY_VAULT_ID || onlyPersonalItems) {
|
||||
@ -405,7 +402,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
|
||||
*/
|
||||
private getCollectionsForOrganization(orgId: OrganizationId): Observable<CollectionView[]> {
|
||||
return combineLatest([
|
||||
this.collectionService.decryptedCollections$,
|
||||
this.collectionService.decryptedCollections$(this.activeUserId$),
|
||||
this.organizationService.organizations$,
|
||||
]).pipe(
|
||||
map(([collections, organizations]) => {
|
||||
@ -429,7 +426,7 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
|
||||
shareableCiphers,
|
||||
organizationId,
|
||||
selectedCollectionIds,
|
||||
this.activeUserId,
|
||||
await firstValueFrom(this.activeUserId$),
|
||||
);
|
||||
|
||||
this.toastService.showToast({
|
||||
@ -470,7 +467,10 @@ export class AssignCollectionsComponent implements OnInit, OnDestroy, AfterViewI
|
||||
private async updateAssignedCollections(cipherView: CipherView) {
|
||||
const { collections } = this.formGroup.getRawValue();
|
||||
cipherView.collectionIds = collections.map((i) => i.id as CollectionId);
|
||||
const cipher = await this.cipherService.encrypt(cipherView, this.activeUserId);
|
||||
const cipher = await this.cipherService.encrypt(
|
||||
cipherView,
|
||||
await firstValueFrom(this.activeUserId$),
|
||||
);
|
||||
if (this.params.isSingleCipherAdmin) {
|
||||
await this.cipherService.saveCollectionsWithServerAdmin(cipher);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user