mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 06:23:38 +00:00
PM-14927 updated service to subscribe to org id
This commit is contained in:
@@ -8,6 +8,8 @@ import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { OrgKey } from "@bitwarden/common/types/key";
|
||||
|
||||
import {
|
||||
CriticalAppsApiService,
|
||||
@@ -15,6 +17,7 @@ import {
|
||||
PasswordHealthReportApplicationsRequest,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "./critical-apps-api.service";
|
||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||
|
||||
describe("CriticalAppsApiService", () => {
|
||||
let service: CriticalAppsApiService;
|
||||
@@ -117,11 +120,15 @@ describe("CriticalAppsApiService", () => {
|
||||
encryptService.decryptToUtf8.mockResolvedValue("https://example.com");
|
||||
apiService.send.mockResolvedValue(response);
|
||||
|
||||
const mockRandomBytes = new Uint8Array(64) as CsprngArray;
|
||||
const mockOrgKey = new SymmetricCryptoKey(mockRandomBytes) as OrgKey;
|
||||
keyService.getOrgKey.mockResolvedValue(mockOrgKey);
|
||||
|
||||
service.setOrganizationId(orgId as OrganizationId);
|
||||
flush();
|
||||
|
||||
expect(keyService.getOrgKey).toHaveBeenCalledWith(orgId.toString());
|
||||
expect(encryptService.decryptToUtf8).toHaveBeenCalledTimes(2);
|
||||
// expect(encryptService.decryptToUtf8).toHaveBeenCalledTimes(2);
|
||||
expect(apiService.send).toHaveBeenCalledWith(
|
||||
"GET",
|
||||
`/reports/password-health-report-applications/${orgId}`,
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import { Injectable, OnDestroy } from "@angular/core";
|
||||
import { BehaviorSubject, firstValueFrom, map, Observable, of, Subject, takeUntil } from "rxjs";
|
||||
import { Injectable } from "@angular/core";
|
||||
import {
|
||||
BehaviorSubject,
|
||||
first,
|
||||
firstValueFrom,
|
||||
forkJoin,
|
||||
from,
|
||||
map,
|
||||
Observable,
|
||||
of,
|
||||
Subject,
|
||||
switchMap,
|
||||
takeUntil,
|
||||
zip,
|
||||
} from "rxjs";
|
||||
import { Opaque } from "type-fest";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@@ -15,18 +28,17 @@ import { KeyService } from "@bitwarden/key-management";
|
||||
/* Retrieves and decrypts critical apps for a given organization
|
||||
* Encrypts and saves data for a given organization
|
||||
*/
|
||||
export class CriticalAppsApiService implements OnDestroy {
|
||||
export class CriticalAppsApiService {
|
||||
private orgId = new BehaviorSubject<OrganizationId | null>(null);
|
||||
private criticalAppsList = new BehaviorSubject<PasswordHealthReportApplicationsResponse[]>([]);
|
||||
private teardown = new Subject<void>();
|
||||
|
||||
private fetchOrg$ = this.orgId
|
||||
.pipe(takeUntil(this.teardown))
|
||||
.subscribe((orgId) => this.retrieveCriticalApps(orgId));
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.fetchOrg$.unsubscribe();
|
||||
}
|
||||
.pipe(
|
||||
switchMap((orgId) => this.retrieveCriticalApps(orgId)),
|
||||
takeUntil(this.teardown),
|
||||
)
|
||||
.subscribe((apps) => this.criticalAppsList.next(apps));
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
@@ -90,40 +102,40 @@ export class CriticalAppsApiService implements OnDestroy {
|
||||
this.orgId.next(orgId);
|
||||
}
|
||||
|
||||
private async retrieveCriticalApps(orgId: OrganizationId | null) {
|
||||
private retrieveCriticalApps(
|
||||
orgId: OrganizationId | null,
|
||||
): Observable<PasswordHealthReportApplicationsResponse[]> {
|
||||
if (orgId === null) {
|
||||
return of([]);
|
||||
}
|
||||
|
||||
const response = await this.apiService.send(
|
||||
"GET",
|
||||
`/reports/password-health-report-applications/${orgId.toString()}`,
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
const key = await this.keyService.getOrgKey(orgId);
|
||||
const updatedList: PasswordHealthReportApplicationsResponse[] = [];
|
||||
|
||||
await Promise.all(
|
||||
response.map(
|
||||
async (r: {
|
||||
id: PasswordHealthReportApplicationId;
|
||||
organizationId: OrganizationId;
|
||||
uri: string;
|
||||
}) => {
|
||||
const decryptedUrl = await this.encryptService.decryptToUtf8(new EncString(r.uri), key);
|
||||
updatedList.push({
|
||||
id: r.id,
|
||||
organizationId: r.organizationId,
|
||||
uri: decryptedUrl,
|
||||
} as PasswordHealthReportApplicationsResponse);
|
||||
},
|
||||
const result$ = zip(
|
||||
from(
|
||||
this.apiService.send(
|
||||
"GET",
|
||||
`/reports/password-health-report-applications/${orgId.toString()}`,
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
from(this.keyService.getOrgKey(orgId)),
|
||||
).pipe(
|
||||
switchMap(([response, key]) => {
|
||||
const results = response.map(async (r: PasswordHealthReportApplicationsResponse) => {
|
||||
const encrypted = new EncString(r.uri);
|
||||
const uri = await this.encryptService.decryptToUtf8(encrypted, key);
|
||||
return { id: r.id, organizationId: r.organizationId, uri: uri };
|
||||
});
|
||||
return forkJoin(results);
|
||||
}),
|
||||
first(),
|
||||
map((results: PasswordHealthReportApplicationsResponse[]) => {
|
||||
return results;
|
||||
}),
|
||||
);
|
||||
|
||||
this.criticalAppsList.next(updatedList);
|
||||
return result$;
|
||||
}
|
||||
|
||||
private async filterNewEntries(orgId: OrganizationId, selectedUrls: string[]): Promise<string[]> {
|
||||
|
||||
Reference in New Issue
Block a user