mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 05:43:41 +00:00
[PM-25607] Separate Models and account for legacy (#16448)
* organize password-health.ts contents into new model files * revert naming * revert to state of use save service pr draft * LEGACY_MemberDetailsFlat * legacy updates to password health file * update imports * fix import errors * - revert unnecessary encrypteddatamodel changes -add it back to password-health.ts - revert the type changes of variables in EncryptedDataWithKey * quick fix
This commit is contained in:
@@ -2,16 +2,16 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
|
||||
import {
|
||||
MemberDetailsFlat,
|
||||
CipherHealthReportDetail,
|
||||
CipherHealthReportUriDetail,
|
||||
ApplicationHealthReportDetail,
|
||||
LEGACY_MemberDetailsFlat,
|
||||
LEGACY_CipherHealthReportDetail,
|
||||
LEGACY_CipherHealthReportUriDetail,
|
||||
} from "../models/password-health";
|
||||
import { ApplicationHealthReportDetail } from "../models/report-models";
|
||||
import { MemberCipherDetailsResponse } from "../response/member-cipher-details.response";
|
||||
|
||||
export function flattenMemberDetails(
|
||||
memberCiphers: MemberCipherDetailsResponse[],
|
||||
): MemberDetailsFlat[] {
|
||||
): LEGACY_MemberDetailsFlat[] {
|
||||
return memberCiphers.flatMap((member) =>
|
||||
member.cipherIds.map((cipherId) => ({
|
||||
userGuid: member.userGuid,
|
||||
@@ -44,7 +44,9 @@ export function getTrimmedCipherUris(cipher: CipherView): string[] {
|
||||
}
|
||||
|
||||
// Returns a deduplicated array of members by email
|
||||
export function getUniqueMembers(orgMembers: MemberDetailsFlat[]): MemberDetailsFlat[] {
|
||||
export function getUniqueMembers(
|
||||
orgMembers: LEGACY_MemberDetailsFlat[],
|
||||
): LEGACY_MemberDetailsFlat[] {
|
||||
const existingEmails = new Set<string>();
|
||||
return orgMembers.filter((member) => {
|
||||
if (existingEmails.has(member.email)) {
|
||||
@@ -68,7 +70,7 @@ export function getMemberDetailsFlat(
|
||||
userName: string,
|
||||
email: string,
|
||||
cipherId: string,
|
||||
): MemberDetailsFlat {
|
||||
): LEGACY_MemberDetailsFlat {
|
||||
return {
|
||||
userGuid: userGuid,
|
||||
userName: userName,
|
||||
@@ -84,9 +86,9 @@ export function getMemberDetailsFlat(
|
||||
* @returns Flattened cipher health details to URI
|
||||
*/
|
||||
export function getFlattenedCipherDetails(
|
||||
detail: CipherHealthReportDetail,
|
||||
detail: LEGACY_CipherHealthReportDetail,
|
||||
uri: string,
|
||||
): CipherHealthReportUriDetail {
|
||||
): LEGACY_CipherHealthReportUriDetail {
|
||||
return {
|
||||
cipherId: detail.id,
|
||||
reusedPasswordCount: detail.reusedPasswordCount,
|
||||
@@ -107,7 +109,7 @@ export function getFlattenedCipherDetails(
|
||||
* @returns The new or updated application health report detail
|
||||
*/
|
||||
export function getApplicationReportDetail(
|
||||
newUriDetail: CipherHealthReportUriDetail,
|
||||
newUriDetail: LEGACY_CipherHealthReportUriDetail,
|
||||
isAtRisk: boolean,
|
||||
existingUriDetail?: ApplicationHealthReportDetail,
|
||||
): ApplicationHealthReportDetail {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { EncryptedString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { PasswordHealthReportApplicationId, RiskInsightsReport } from "./report-models";
|
||||
|
||||
// -------------------- Password Health Report Models --------------------
|
||||
/**
|
||||
* Request to drop a password health report application
|
||||
* Model is expected by the API endpoint
|
||||
*/
|
||||
export interface PasswordHealthReportApplicationDropRequest {
|
||||
organizationId: OrganizationId;
|
||||
passwordHealthReportApplicationIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Response from the API after marking an app as critical
|
||||
*/
|
||||
export interface PasswordHealthReportApplicationsResponse {
|
||||
id: PasswordHealthReportApplicationId;
|
||||
organizationId: OrganizationId;
|
||||
uri: string;
|
||||
}
|
||||
/*
|
||||
* Request to save a password health report application
|
||||
* Model is expected by the API endpoint
|
||||
*/
|
||||
export interface PasswordHealthReportApplicationsRequest {
|
||||
organizationId: OrganizationId;
|
||||
url: string;
|
||||
}
|
||||
|
||||
// -------------------- Risk Insights Report Models --------------------
|
||||
export interface SaveRiskInsightsReportRequest {
|
||||
data: RiskInsightsReport;
|
||||
}
|
||||
|
||||
export interface SaveRiskInsightsReportResponse {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface GetRiskInsightsReportResponse {
|
||||
id: string;
|
||||
organizationId: OrganizationId;
|
||||
// TODO Update to use creationDate from server
|
||||
date: string;
|
||||
reportData: EncryptedString;
|
||||
contentEncryptionKey: EncryptedString;
|
||||
}
|
||||
@@ -1,75 +1,11 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Opaque } from "type-fest";
|
||||
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { BadgeVariant } from "@bitwarden/components";
|
||||
import { EncString } from "@bitwarden/sdk-internal";
|
||||
|
||||
/**
|
||||
* All applications report summary. The total members,
|
||||
* total at risk members, application, and at risk application
|
||||
* counts. Aggregated from all calculated applications
|
||||
*/
|
||||
export type ApplicationHealthReportSummary = {
|
||||
totalMemberCount: number;
|
||||
totalAtRiskMemberCount: number;
|
||||
totalApplicationCount: number;
|
||||
totalAtRiskApplicationCount: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* All applications report detail. Application is the cipher
|
||||
* uri. Has the at risk, password, and member information
|
||||
*/
|
||||
export type ApplicationHealthReportDetail = {
|
||||
applicationName: string;
|
||||
passwordCount: number;
|
||||
atRiskPasswordCount: number;
|
||||
atRiskCipherIds: string[];
|
||||
memberCount: number;
|
||||
atRiskMemberCount: number;
|
||||
memberDetails: MemberDetailsFlat[];
|
||||
atRiskMemberDetails: MemberDetailsFlat[];
|
||||
cipherIds: string[];
|
||||
};
|
||||
|
||||
export type ApplicationHealthReportDetailWithCriticalFlag = ApplicationHealthReportDetail & {
|
||||
isMarkedAsCritical: boolean;
|
||||
};
|
||||
|
||||
export type ApplicationHealthReportDetailWithCriticalFlagAndCipher =
|
||||
ApplicationHealthReportDetailWithCriticalFlag & {
|
||||
ciphers: CipherView[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Breaks the cipher health info out by uri and passes
|
||||
* along the password health and member info
|
||||
*/
|
||||
export type CipherHealthReportUriDetail = {
|
||||
cipherId: string;
|
||||
reusedPasswordCount: number;
|
||||
weakPasswordDetail: WeakPasswordDetail;
|
||||
exposedPasswordDetail: ExposedPasswordDetail;
|
||||
cipherMembers: MemberDetailsFlat[];
|
||||
trimmedUri: string;
|
||||
cipher: CipherView;
|
||||
};
|
||||
|
||||
/**
|
||||
* Associates a cipher with it's essential information.
|
||||
* Gets the password health details, cipher members, and
|
||||
* the trimmed uris for the cipher
|
||||
*/
|
||||
export type CipherHealthReportDetail = CipherView & {
|
||||
reusedPasswordCount: number;
|
||||
weakPasswordDetail: WeakPasswordDetail;
|
||||
exposedPasswordDetail: ExposedPasswordDetail;
|
||||
cipherMembers: MemberDetailsFlat[];
|
||||
trimmedUris: string[];
|
||||
};
|
||||
import { ApplicationHealthReportDetail } from "./report-models";
|
||||
|
||||
/**
|
||||
* Weak password details containing the score
|
||||
@@ -97,41 +33,6 @@ export type ExposedPasswordDetail = {
|
||||
exposedXTimes: number;
|
||||
} | null;
|
||||
|
||||
/**
|
||||
* Flattened member details that associates an
|
||||
* organization member to a cipher
|
||||
*/
|
||||
export type MemberDetailsFlat = {
|
||||
userGuid: string;
|
||||
userName: string;
|
||||
email: string;
|
||||
cipherId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Member email with the number of at risk passwords
|
||||
* At risk member detail that contains the email
|
||||
* and the count of at risk ciphers
|
||||
*/
|
||||
export type AtRiskMemberDetail = {
|
||||
email: string;
|
||||
atRiskPasswordCount: number;
|
||||
};
|
||||
|
||||
/*
|
||||
* A list of applications and the count of
|
||||
* at risk passwords for each application
|
||||
*/
|
||||
export type AtRiskApplicationDetail = {
|
||||
applicationName: string;
|
||||
atRiskPasswordCount: number;
|
||||
};
|
||||
|
||||
export type AppAtRiskMembersDialogParams = {
|
||||
members: MemberDetailsFlat[];
|
||||
applicationName: string;
|
||||
};
|
||||
|
||||
/*
|
||||
* After data is encrypted, it is returned with the
|
||||
* encryption key used to encrypt the data.
|
||||
@@ -142,31 +43,39 @@ export interface EncryptedDataWithKey {
|
||||
encryptionKey: EncString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to drop a password health report application
|
||||
* Model is expected by the API endpoint
|
||||
*/
|
||||
export interface PasswordHealthReportApplicationDropRequest {
|
||||
organizationId: OrganizationId;
|
||||
passwordHealthReportApplicationIds: string[];
|
||||
}
|
||||
export type LEGACY_MemberDetailsFlat = {
|
||||
userGuid: string;
|
||||
userName: string;
|
||||
email: string;
|
||||
cipherId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Response from the API after marking an app as critical
|
||||
*/
|
||||
export interface PasswordHealthReportApplicationsResponse {
|
||||
id: PasswordHealthReportApplicationId;
|
||||
organizationId: OrganizationId;
|
||||
uri: string;
|
||||
}
|
||||
/*
|
||||
* Request to save a password health report application
|
||||
* Model is expected by the API endpoint
|
||||
*/
|
||||
export interface PasswordHealthReportApplicationsRequest {
|
||||
organizationId: OrganizationId;
|
||||
url: string;
|
||||
}
|
||||
export type LEGACY_ApplicationHealthReportDetailWithCriticalFlag = ApplicationHealthReportDetail & {
|
||||
isMarkedAsCritical: boolean;
|
||||
};
|
||||
|
||||
export type LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher =
|
||||
LEGACY_ApplicationHealthReportDetailWithCriticalFlag & {
|
||||
ciphers: CipherView[];
|
||||
};
|
||||
|
||||
export type LEGACY_CipherHealthReportDetail = CipherView & {
|
||||
reusedPasswordCount: number;
|
||||
weakPasswordDetail: WeakPasswordDetail;
|
||||
exposedPasswordDetail: ExposedPasswordDetail;
|
||||
cipherMembers: LEGACY_MemberDetailsFlat[];
|
||||
trimmedUris: string[];
|
||||
};
|
||||
|
||||
export type LEGACY_CipherHealthReportUriDetail = {
|
||||
cipherId: string;
|
||||
reusedPasswordCount: number;
|
||||
weakPasswordDetail: WeakPasswordDetail;
|
||||
exposedPasswordDetail: ExposedPasswordDetail;
|
||||
cipherMembers: LEGACY_MemberDetailsFlat[];
|
||||
trimmedUri: string;
|
||||
cipher: CipherView;
|
||||
};
|
||||
|
||||
export interface EncryptedDataModel {
|
||||
organizationId: OrganizationId;
|
||||
@@ -174,42 +83,3 @@ export interface EncryptedDataModel {
|
||||
encryptionKey: string;
|
||||
date: Date;
|
||||
}
|
||||
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum DrawerType {
|
||||
None = 0,
|
||||
AppAtRiskMembers = 1,
|
||||
OrgAtRiskMembers = 2,
|
||||
OrgAtRiskApps = 3,
|
||||
}
|
||||
|
||||
export interface RiskInsightsReport {
|
||||
organizationId: OrganizationId;
|
||||
date: string;
|
||||
reportData: string;
|
||||
reportKey: string;
|
||||
}
|
||||
|
||||
export interface ReportInsightsReportData {
|
||||
data: ApplicationHealthReportDetail[];
|
||||
summary: ApplicationHealthReportSummary;
|
||||
}
|
||||
|
||||
export interface SaveRiskInsightsReportRequest {
|
||||
data: RiskInsightsReport;
|
||||
}
|
||||
|
||||
export interface SaveRiskInsightsReportResponse {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface GetRiskInsightsReportResponse {
|
||||
id: string;
|
||||
organizationId: OrganizationId;
|
||||
date: string;
|
||||
reportData: EncString;
|
||||
reportKey: EncString;
|
||||
}
|
||||
|
||||
export type PasswordHealthReportApplicationId = Opaque<string, "PasswordHealthReportApplicationId">;
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import { Opaque } from "type-fest";
|
||||
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { BadgeVariant } from "@bitwarden/components";
|
||||
|
||||
import { ExposedPasswordDetail, WeakPasswordDetail } from "./password-health";
|
||||
|
||||
// -------------------- Drawer and UI Models --------------------
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum DrawerType {
|
||||
None = 0,
|
||||
AppAtRiskMembers = 1,
|
||||
OrgAtRiskMembers = 2,
|
||||
OrgAtRiskApps = 3,
|
||||
}
|
||||
|
||||
export type DrawerDetails = {
|
||||
open: boolean;
|
||||
invokerId: string;
|
||||
activeDrawerType: DrawerType;
|
||||
atRiskMemberDetails?: AtRiskMemberDetail[];
|
||||
appAtRiskMembers?: AppAtRiskMembersDialogParams | null;
|
||||
atRiskAppDetails?: AtRiskApplicationDetail[] | null;
|
||||
};
|
||||
|
||||
export type AppAtRiskMembersDialogParams = {
|
||||
members: MemberDetails[];
|
||||
applicationName: string;
|
||||
};
|
||||
|
||||
// -------------------- Member Models --------------------
|
||||
/**
|
||||
* Member email with the number of at risk passwords
|
||||
* At risk member detail that contains the email
|
||||
* and the count of at risk ciphers
|
||||
*/
|
||||
export type AtRiskMemberDetail = {
|
||||
email: string;
|
||||
atRiskPasswordCount: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Flattened member details that associates an
|
||||
* organization member to a cipher
|
||||
*/
|
||||
export type MemberDetails = {
|
||||
userGuid: string;
|
||||
userName: string;
|
||||
email: string;
|
||||
cipherId: string;
|
||||
};
|
||||
|
||||
// -------------------- Cipher Models --------------------
|
||||
|
||||
export type PasswordHealthData = {
|
||||
reusedPasswordCount: number;
|
||||
weakPasswordDetail: WeakPasswordDetail;
|
||||
exposedPasswordDetail: ExposedPasswordDetail;
|
||||
};
|
||||
|
||||
/**
|
||||
* Associates a cipher with it's essential information.
|
||||
* Gets the password health details, cipher members, and
|
||||
* the trimmed uris for the cipher
|
||||
*/
|
||||
export type CipherHealthReport = {
|
||||
applications: string[];
|
||||
cipherMembers: MemberDetails[];
|
||||
healthData: PasswordHealthData;
|
||||
cipher: CipherView;
|
||||
};
|
||||
|
||||
/**
|
||||
* Breaks the cipher health info out by uri and passes
|
||||
* along the password health and member info
|
||||
*/
|
||||
export type CipherApplicationView = {
|
||||
cipherId: string;
|
||||
cipher: CipherView;
|
||||
cipherMembers: MemberDetails[];
|
||||
application: string;
|
||||
healthData: PasswordHealthData;
|
||||
};
|
||||
|
||||
// -------------------- Application Health Report Models --------------------
|
||||
/**
|
||||
* All applications report summary. The total members,
|
||||
* total at risk members, application, and at risk application
|
||||
* counts. Aggregated from all calculated applications
|
||||
*/
|
||||
export type ApplicationHealthReportSummary = {
|
||||
totalMemberCount: number;
|
||||
totalAtRiskMemberCount: number;
|
||||
totalApplicationCount: number;
|
||||
totalAtRiskApplicationCount: number;
|
||||
};
|
||||
|
||||
export type CriticalSummaryDetails = {
|
||||
totalCriticalMembersCount: number;
|
||||
totalCriticalApplicationsCount: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* All applications report detail. Application is the cipher
|
||||
* uri. Has the at risk, password, and member information
|
||||
*/
|
||||
export type ApplicationHealthReportDetail = {
|
||||
applicationName: string;
|
||||
passwordCount: number;
|
||||
atRiskPasswordCount: number;
|
||||
atRiskCipherIds: string[];
|
||||
memberCount: number;
|
||||
atRiskMemberCount: number;
|
||||
memberDetails: MemberDetails[];
|
||||
atRiskMemberDetails: MemberDetails[];
|
||||
cipherIds: string[];
|
||||
};
|
||||
|
||||
export type ApplicationHealthReportDetailEnriched = ApplicationHealthReportDetail & {
|
||||
isMarkedAsCritical: boolean;
|
||||
ciphers: CipherView[];
|
||||
};
|
||||
|
||||
/*
|
||||
* A list of applications and the count of
|
||||
* at risk passwords for each application
|
||||
*/
|
||||
export type AtRiskApplicationDetail = {
|
||||
applicationName: string;
|
||||
atRiskPasswordCount: number;
|
||||
};
|
||||
|
||||
// -------------------- Password Health Report Models --------------------
|
||||
export type PasswordHealthReportApplicationId = Opaque<string, "PasswordHealthReportApplicationId">;
|
||||
|
||||
// -------------------- Risk Insights Report Models --------------------
|
||||
export interface RiskInsightsReportData {
|
||||
data: ApplicationHealthReportDetailEnriched[];
|
||||
summary: ApplicationHealthReportSummary;
|
||||
}
|
||||
export interface RiskInsightsReport {
|
||||
organizationId: OrganizationId;
|
||||
date: string;
|
||||
reportData: string;
|
||||
reportKey: string;
|
||||
}
|
||||
|
||||
export type ReportScore = { label: string; badgeVariant: BadgeVariant; sortOrder: number };
|
||||
|
||||
export type ReportResult = CipherView & {
|
||||
score: number;
|
||||
reportValue: ReportScore;
|
||||
scoreKey: number;
|
||||
};
|
||||
|
||||
export type ReportDetailsAndSummary = {
|
||||
data: ApplicationHealthReportDetailEnriched[];
|
||||
summary: ApplicationHealthReportSummary;
|
||||
dateCreated: Date;
|
||||
};
|
||||
@@ -5,10 +5,10 @@ import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import {
|
||||
PasswordHealthReportApplicationDropRequest,
|
||||
PasswordHealthReportApplicationId,
|
||||
PasswordHealthReportApplicationsRequest,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "../models/password-health";
|
||||
} from "../models/api-models.types";
|
||||
import { PasswordHealthReportApplicationId } from "../models/report-models";
|
||||
|
||||
import { CriticalAppsApiService } from "./critical-apps-api.service";
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
PasswordHealthReportApplicationDropRequest,
|
||||
PasswordHealthReportApplicationsRequest,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "../models/password-health";
|
||||
} from "../models/api-models.types";
|
||||
|
||||
export class CriticalAppsApiService {
|
||||
constructor(private apiService: ApiService) {}
|
||||
|
||||
@@ -12,10 +12,10 @@ import { OrgKey } from "@bitwarden/common/types/key";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import {
|
||||
PasswordHealthReportApplicationId,
|
||||
PasswordHealthReportApplicationsRequest,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "../models/password-health";
|
||||
} from "../models/api-models.types";
|
||||
import { PasswordHealthReportApplicationId } from "../models/report-models";
|
||||
|
||||
import { CriticalAppsApiService } from "./critical-apps-api.service";
|
||||
import { CriticalAppsService } from "./critical-apps.service";
|
||||
|
||||
@@ -22,7 +22,7 @@ import { KeyService } from "@bitwarden/key-management";
|
||||
import {
|
||||
PasswordHealthReportApplicationsRequest,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "../models/password-health";
|
||||
} from "../models/api-models.types";
|
||||
|
||||
import { CriticalAppsApiService } from "./critical-apps-api.service";
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { makeEncString } from "@bitwarden/common/spec";
|
||||
import { OrganizationId, OrganizationReportId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { EncryptedDataModel, SaveRiskInsightsReportRequest } from "../models/password-health";
|
||||
import { SaveRiskInsightsReportRequest } from "../models/api-models.types";
|
||||
import { EncryptedDataModel } from "../models/password-health";
|
||||
|
||||
import { RiskInsightsApiService } from "./risk-insights-api.service";
|
||||
|
||||
@@ -200,7 +201,9 @@ describe("RiskInsightsApiService", () => {
|
||||
|
||||
it("Get Applications: should call apiService.send with correct parameters and return an Observable", (done) => {
|
||||
const reportId = "report123" as OrganizationReportId;
|
||||
const mockResponse: EncryptedDataModel | null = { encryptedData: "abc" } as EncryptedDataModel;
|
||||
const mockResponse: EncryptedDataModel | null = {
|
||||
encryptedData: "abc",
|
||||
} as EncryptedDataModel;
|
||||
|
||||
mockApiService.send.mockResolvedValueOnce(mockResponse);
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationId, OrganizationReportId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import {
|
||||
EncryptedDataModel,
|
||||
GetRiskInsightsReportResponse,
|
||||
SaveRiskInsightsReportRequest,
|
||||
SaveRiskInsightsReportResponse,
|
||||
} from "../models/password-health";
|
||||
} from "../models/api-models.types";
|
||||
import { EncryptedDataModel } from "../models/password-health";
|
||||
|
||||
export class RiskInsightsApiService {
|
||||
constructor(private apiService: ApiService) {}
|
||||
|
||||
@@ -5,11 +5,11 @@ import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import {
|
||||
AppAtRiskMembersDialogParams,
|
||||
ApplicationHealthReportDetail,
|
||||
AtRiskApplicationDetail,
|
||||
AtRiskMemberDetail,
|
||||
DrawerType,
|
||||
} from "../models/password-health";
|
||||
ApplicationHealthReportDetail,
|
||||
} from "../models/report-models";
|
||||
|
||||
import { RiskInsightsReportService } from "./risk-insights-report.service";
|
||||
export class RiskInsightsDataService {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/pass
|
||||
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
|
||||
import { GetRiskInsightsReportResponse } from "../models/password-health";
|
||||
import { GetRiskInsightsReportResponse } from "../models/api-models.types";
|
||||
|
||||
import { mockCiphers } from "./ciphers.mock";
|
||||
import { MemberCipherDetailsApiService } from "./member-cipher-details-api.service";
|
||||
@@ -197,7 +197,7 @@ describe("RiskInsightsReportService", () => {
|
||||
date: new Date().toISOString(),
|
||||
organizationId: "orgId",
|
||||
reportData: "encryptedReportData",
|
||||
reportKey: "encryptionKey",
|
||||
contentEncryptionKey: "encryptionKey",
|
||||
} as GetRiskInsightsReportResponse;
|
||||
|
||||
const organizationId = "orgId" as OrganizationId;
|
||||
@@ -227,7 +227,7 @@ describe("RiskInsightsReportService", () => {
|
||||
date: new Date().toISOString(),
|
||||
organizationId: organizationId as OrganizationId,
|
||||
reportData: "encryptedReportData",
|
||||
reportKey: "encryptionKey",
|
||||
contentEncryptionKey: "encryptionKey",
|
||||
} as GetRiskInsightsReportResponse;
|
||||
|
||||
const decryptedReport = {
|
||||
|
||||
@@ -29,20 +29,22 @@ import {
|
||||
getTrimmedCipherUris,
|
||||
getUniqueMembers,
|
||||
} from "../helpers/risk-insights-data-mappers";
|
||||
import {
|
||||
LEGACY_CipherHealthReportDetail,
|
||||
LEGACY_CipherHealthReportUriDetail,
|
||||
ExposedPasswordDetail,
|
||||
LEGACY_MemberDetailsFlat,
|
||||
WeakPasswordDetail,
|
||||
WeakPasswordScore,
|
||||
LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
} from "../models/password-health";
|
||||
import {
|
||||
ApplicationHealthReportDetail,
|
||||
ApplicationHealthReportSummary,
|
||||
AtRiskMemberDetail,
|
||||
AtRiskApplicationDetail,
|
||||
CipherHealthReportDetail,
|
||||
CipherHealthReportUriDetail,
|
||||
ExposedPasswordDetail,
|
||||
MemberDetailsFlat,
|
||||
WeakPasswordDetail,
|
||||
WeakPasswordScore,
|
||||
ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
ReportInsightsReportData,
|
||||
} from "../models/password-health";
|
||||
RiskInsightsReportData,
|
||||
} from "../models/report-models";
|
||||
|
||||
import { MemberCipherDetailsApiService } from "./member-cipher-details-api.service";
|
||||
import { RiskInsightsApiService } from "./risk-insights-api.service";
|
||||
@@ -76,7 +78,9 @@ export class RiskInsightsReportService {
|
||||
* @param organizationId
|
||||
* @returns Cipher health report data with members and trimmed uris
|
||||
*/
|
||||
generateRawDataReport$(organizationId: OrganizationId): Observable<CipherHealthReportDetail[]> {
|
||||
generateRawDataReport$(
|
||||
organizationId: OrganizationId,
|
||||
): Observable<LEGACY_CipherHealthReportDetail[]> {
|
||||
const allCiphers$ = from(this.cipherService.getAllFromApiForOrganization(organizationId));
|
||||
const memberCiphers$ = from(
|
||||
this.memberCipherDetailsApiService.getMemberCipherDetails(organizationId),
|
||||
@@ -84,7 +88,7 @@ export class RiskInsightsReportService {
|
||||
|
||||
const results$ = zip(allCiphers$, memberCiphers$).pipe(
|
||||
map(([allCiphers, memberCiphers]) => {
|
||||
const details: MemberDetailsFlat[] = memberCiphers.flatMap((dtl) =>
|
||||
const details: LEGACY_MemberDetailsFlat[] = memberCiphers.flatMap((dtl) =>
|
||||
dtl.cipherIds.map((c) => getMemberDetailsFlat(dtl.userGuid, dtl.userName, dtl.email, c)),
|
||||
);
|
||||
return [allCiphers, details] as const;
|
||||
@@ -104,7 +108,7 @@ export class RiskInsightsReportService {
|
||||
*/
|
||||
generateRawDataUriReport$(
|
||||
organizationId: OrganizationId,
|
||||
): Observable<CipherHealthReportUriDetail[]> {
|
||||
): Observable<LEGACY_CipherHealthReportUriDetail[]> {
|
||||
const cipherHealthDetails$ = this.generateRawDataReport$(organizationId);
|
||||
const results$ = cipherHealthDetails$.pipe(
|
||||
map((healthDetails) => this.getCipherUriDetails(healthDetails)),
|
||||
@@ -206,7 +210,7 @@ export class RiskInsightsReportService {
|
||||
async identifyCiphers(
|
||||
data: ApplicationHealthReportDetail[],
|
||||
organizationId: OrganizationId,
|
||||
): Promise<ApplicationHealthReportDetailWithCriticalFlagAndCipher[]> {
|
||||
): Promise<LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher[]> {
|
||||
const cipherViews = await this.cipherService.getAllFromApiForOrganization(organizationId);
|
||||
|
||||
const dataWithCiphers = data.map(
|
||||
@@ -214,7 +218,7 @@ export class RiskInsightsReportService {
|
||||
({
|
||||
...app,
|
||||
ciphers: cipherViews.filter((c) => app.cipherIds.some((a) => a === c.id)),
|
||||
}) as ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
}) as LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
);
|
||||
return dataWithCiphers;
|
||||
}
|
||||
@@ -226,7 +230,7 @@ export class RiskInsightsReportService {
|
||||
switchMap((response) => {
|
||||
if (!response) {
|
||||
// Return an empty report and summary if response is falsy
|
||||
return of<ReportInsightsReportData>({
|
||||
return of<RiskInsightsReportData>({
|
||||
data: [],
|
||||
summary: {
|
||||
totalMemberCount: 0,
|
||||
@@ -237,12 +241,12 @@ export class RiskInsightsReportService {
|
||||
});
|
||||
}
|
||||
return from(
|
||||
this.riskInsightsEncryptionService.decryptRiskInsightsReport<ReportInsightsReportData>(
|
||||
this.riskInsightsEncryptionService.decryptRiskInsightsReport<RiskInsightsReportData>(
|
||||
organizationId,
|
||||
userId,
|
||||
new EncString(response.reportData),
|
||||
new EncString(response.reportKey),
|
||||
(data) => data as ReportInsightsReportData,
|
||||
new EncString(response.contentEncryptionKey),
|
||||
(data) => data as RiskInsightsReportData,
|
||||
),
|
||||
);
|
||||
}),
|
||||
@@ -297,9 +301,9 @@ export class RiskInsightsReportService {
|
||||
*/
|
||||
private async getCipherDetails(
|
||||
ciphers: CipherView[],
|
||||
memberDetails: MemberDetailsFlat[],
|
||||
): Promise<CipherHealthReportDetail[]> {
|
||||
const cipherHealthReports: CipherHealthReportDetail[] = [];
|
||||
memberDetails: LEGACY_MemberDetailsFlat[],
|
||||
): Promise<LEGACY_CipherHealthReportDetail[]> {
|
||||
const cipherHealthReports: LEGACY_CipherHealthReportDetail[] = [];
|
||||
const passwordUseMap = new Map<string, number>();
|
||||
const exposedDetails = await this.findExposedPasswords(ciphers);
|
||||
for (const cipher of ciphers) {
|
||||
@@ -329,7 +333,7 @@ export class RiskInsightsReportService {
|
||||
exposedPasswordDetail: exposedPassword,
|
||||
cipherMembers: cipherMembers,
|
||||
trimmedUris: cipherTrimmedUris,
|
||||
} as CipherHealthReportDetail;
|
||||
} as LEGACY_CipherHealthReportDetail;
|
||||
|
||||
cipherHealthReports.push(cipherHealth);
|
||||
}
|
||||
@@ -348,8 +352,8 @@ export class RiskInsightsReportService {
|
||||
* @returns Flattened cipher health details to uri
|
||||
*/
|
||||
private getCipherUriDetails(
|
||||
cipherHealthReport: CipherHealthReportDetail[],
|
||||
): CipherHealthReportUriDetail[] {
|
||||
cipherHealthReport: LEGACY_CipherHealthReportDetail[],
|
||||
): LEGACY_CipherHealthReportUriDetail[] {
|
||||
return cipherHealthReport.flatMap((rpt) =>
|
||||
rpt.trimmedUris.map((u) => getFlattenedCipherDetails(rpt, u)),
|
||||
);
|
||||
@@ -362,7 +366,7 @@ export class RiskInsightsReportService {
|
||||
* @returns Application health reports
|
||||
*/
|
||||
private getApplicationHealthReport(
|
||||
cipherHealthUriReport: CipherHealthReportUriDetail[],
|
||||
cipherHealthUriReport: LEGACY_CipherHealthReportUriDetail[],
|
||||
): ApplicationHealthReportDetail[] {
|
||||
const appReports: ApplicationHealthReportDetail[] = [];
|
||||
cipherHealthUriReport.forEach((uri) => {
|
||||
|
||||
@@ -11,11 +11,13 @@ import {
|
||||
RiskInsightsReportService,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
||||
import {
|
||||
ApplicationHealthReportDetail,
|
||||
ApplicationHealthReportDetailWithCriticalFlag,
|
||||
ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
ApplicationHealthReportSummary,
|
||||
LEGACY_ApplicationHealthReportDetailWithCriticalFlag,
|
||||
LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
|
||||
import {
|
||||
ApplicationHealthReportDetail,
|
||||
ApplicationHealthReportSummary,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/report-models";
|
||||
import { RiskInsightsEncryptionService } from "@bitwarden/bit-common/dirt/reports/risk-insights/services/risk-insights-encryption.service";
|
||||
import {
|
||||
getOrganizationById,
|
||||
@@ -60,7 +62,7 @@ import { ApplicationsLoadingComponent } from "./risk-insights-loading.component"
|
||||
})
|
||||
export class AllApplicationsComponent implements OnInit {
|
||||
protected dataSource =
|
||||
new TableDataSource<ApplicationHealthReportDetailWithCriticalFlagAndCipher>();
|
||||
new TableDataSource<LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher>();
|
||||
protected selectedUrls: Set<string> = new Set<string>();
|
||||
protected searchControl = new FormControl("", { nonNullable: true });
|
||||
protected loading = true;
|
||||
@@ -99,7 +101,7 @@ export class AllApplicationsComponent implements OnInit {
|
||||
const data = applications?.map((app) => ({
|
||||
...app,
|
||||
isMarkedAsCritical: criticalUrls.includes(app.applicationName),
|
||||
})) as ApplicationHealthReportDetailWithCriticalFlag[];
|
||||
})) as LEGACY_ApplicationHealthReportDetailWithCriticalFlag[];
|
||||
return { data, organization };
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CommonModule } from "@angular/common";
|
||||
import { Component, Input } from "@angular/core";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { ApplicationHealthReportDetailWithCriticalFlagAndCipher } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
|
||||
import { LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
|
||||
import { MenuModule, TableDataSource, TableModule } from "@bitwarden/components";
|
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module";
|
||||
@@ -13,7 +13,8 @@ import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pip
|
||||
templateUrl: "./app-table-row-scrollable.component.html",
|
||||
})
|
||||
export class AppTableRowScrollableComponent {
|
||||
@Input() dataSource!: TableDataSource<ApplicationHealthReportDetailWithCriticalFlagAndCipher>;
|
||||
@Input()
|
||||
dataSource!: TableDataSource<LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher>;
|
||||
@Input() showRowMenuForCriticalApps: boolean = false;
|
||||
@Input() showRowCheckBox: boolean = false;
|
||||
@Input() selectedUrls: Set<string> = new Set<string>();
|
||||
|
||||
@@ -13,10 +13,10 @@ import {
|
||||
RiskInsightsReportService,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
||||
import {
|
||||
ApplicationHealthReportDetailWithCriticalFlag,
|
||||
ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
ApplicationHealthReportSummary,
|
||||
LEGACY_ApplicationHealthReportDetailWithCriticalFlag,
|
||||
LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
|
||||
import { ApplicationHealthReportSummary } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/report-models";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
@@ -51,7 +51,7 @@ import { RiskInsightsTabType } from "./risk-insights.component";
|
||||
})
|
||||
export class CriticalApplicationsComponent implements OnInit {
|
||||
protected dataSource =
|
||||
new TableDataSource<ApplicationHealthReportDetailWithCriticalFlagAndCipher>();
|
||||
new TableDataSource<LEGACY_ApplicationHealthReportDetailWithCriticalFlagAndCipher>();
|
||||
protected selectedIds: Set<number> = new Set<number>();
|
||||
protected searchControl = new FormControl("", { nonNullable: true });
|
||||
private destroyRef = inject(DestroyRef);
|
||||
@@ -79,7 +79,7 @@ export class CriticalApplicationsComponent implements OnInit {
|
||||
const data = applications?.map((app) => ({
|
||||
...app,
|
||||
isMarkedAsCritical: criticalUrls.includes(app.applicationName),
|
||||
})) as ApplicationHealthReportDetailWithCriticalFlag[];
|
||||
})) as LEGACY_ApplicationHealthReportDetailWithCriticalFlag[];
|
||||
return data?.filter((app) => app.isMarkedAsCritical);
|
||||
}),
|
||||
switchMap(async (data) => {
|
||||
@@ -200,7 +200,7 @@ export class CriticalApplicationsComponent implements OnInit {
|
||||
this.dataService.setDrawerForOrgAtRiskApps(data, invokerId);
|
||||
};
|
||||
|
||||
trackByFunction(_: number, item: ApplicationHealthReportDetailWithCriticalFlag) {
|
||||
trackByFunction(_: number, item: LEGACY_ApplicationHealthReportDetailWithCriticalFlag) {
|
||||
return item.applicationName;
|
||||
}
|
||||
isDrawerOpenForTableRow = (applicationName: string) => {
|
||||
|
||||
@@ -10,11 +10,11 @@ import {
|
||||
CriticalAppsService,
|
||||
RiskInsightsDataService,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights";
|
||||
import { PasswordHealthReportApplicationsResponse } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/api-models.types";
|
||||
import {
|
||||
ApplicationHealthReportDetail,
|
||||
DrawerType,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/report-models";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
Reference in New Issue
Block a user