1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-17 20:31:50 +01:00

[PM-14462] - Update "Access Intelligence" to "Risk Insights" (#11853)

* rename acess intelligence to risk insights

* keep branch name

* replace all instances of AccessIntelligence. strip raw data + members to just the table

* revert change to feature flag name
This commit is contained in:
Jordan Aasen 2024-11-06 06:47:29 -08:00 committed by GitHub
parent 52c7d21e5f
commit b877624ce3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 103 additions and 159 deletions

View File

@ -40,9 +40,9 @@
></bit-nav-item>
</bit-nav-group>
<bit-nav-item
*ngIf="isAccessIntelligenceFeatureEnabled"
[text]="'accessIntelligence' | i18n"
route="access-intelligence"
*ngIf="isRiskInsightsFeatureEnabled"
[text]="'riskInsights' | i18n"
route="risk-insights"
></bit-nav-item>
<bit-nav-group
icon="bwi-billing"

View File

@ -51,7 +51,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
showPaymentAndHistory$: Observable<boolean>;
hideNewOrgButton$: Observable<boolean>;
organizationIsUnmanaged$: Observable<boolean>;
isAccessIntelligenceFeatureEnabled = false;
isRiskInsightsFeatureEnabled = false;
private _destroy = new Subject<void>();
@ -71,7 +71,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
async ngOnInit() {
document.body.classList.remove("layout_frontend");
this.isAccessIntelligenceFeatureEnabled = await this.configService.getFeatureFlag(
this.isRiskInsightsFeatureEnabled = await this.configService.getFeatureFlag(
FeatureFlag.AccessIntelligence,
);

View File

@ -63,10 +63,10 @@ const routes: Routes = [
),
},
{
path: "access-intelligence",
path: "risk-insights",
loadChildren: () =>
import("../../tools/access-intelligence/access-intelligence.module").then(
(m) => m.AccessIntelligenceModule,
import("../../tools/risk-insights/risk-insights.module").then(
(m) => m.RiskInsightsModule,
),
},
{

View File

@ -1,9 +0,0 @@
import { NgModule } from "@angular/core";
import { AccessIntelligenceRoutingModule } from "./access-intelligence-routing.module";
import { AccessIntelligenceComponent } from "./access-intelligence.component";
@NgModule({
imports: [AccessIntelligenceComponent, AccessIntelligenceRoutingModule],
})
export class AccessIntelligenceModule {}

View File

@ -1,120 +0,0 @@
<p>{{ "passwordsReportDesc" | i18n }}</p>
<div *ngIf="loading">
<i
class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</div>
<div class="tw-mt-4 tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
<div class="tw-flex tw-gap-6">
<tools-card
class="tw-flex-1"
[title]="'atRiskMembers' | i18n"
[value]="totalMembersMap.size - 3"
[maxValue]="totalMembersMap.size"
>
</tools-card>
<tools-card
class="tw-flex-1"
[title]="'atRiskApplications' | i18n"
[value]="totalMembersMap.size - 1"
[maxValue]="totalMembersMap.size"
>
</tools-card>
</div>
<div class="tw-flex tw-mt-8 tw-mb-4 tw-gap-4">
<bit-search class="tw-grow" [formControl]="searchControl"></bit-search>
<button class="tw-rounded-lg" type="button" buttonType="secondary" bitButton>
<i class="bwi bwi-star-f tw-mr-2"></i>
{{ "markAppAsCritical" | i18n }}
</button>
</div>
<div class="tw-mt-4 tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
<div class="tw-flex tw-gap-6">
<tools-card
class="tw-flex-1"
[title]="'atRiskMembers' | i18n"
[value]="totalMembersMap.size - 3"
[maxValue]="totalMembersMap.size"
>
</tools-card>
<tools-card
class="tw-flex-1"
[title]="'atRiskApplications' | i18n"
[value]="totalMembersMap.size - 1"
[maxValue]="totalMembersMap.size"
>
</tools-card>
</div>
<div class="tw-flex tw-mt-8 tw-mb-4 tw-gap-4">
<bit-search class="tw-grow" [formControl]="searchControl"></bit-search>
<button
class="tw-rounded-lg"
type="button"
buttonType="secondary"
[disabled]="!selectedIds.size"
bitButton
[bitAction]="markAppsAsCritical"
appA11yTitle="{{ 'markAppAsCritical' | i18n }}"
>
<i class="bwi bwi-star-f tw-mr-2"></i>
{{ "markAppAsCritical" | i18n }}
</button>
</div>
<bit-table [dataSource]="dataSource">
<ng-container header>
<tr bitRow>
<th bitCell></th>
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
</tr>
</ng-container>
<ng-template body let-rows$>
<tr bitRow *ngFor="let r of rows$ | async; trackBy: trackByFunction">
<td bitCell>
<input
bitCheckbox
type="checkbox"
[checked]="selectedIds.has(r.id)"
(change)="onCheckboxChange(r.id, $event)"
/>
</td>
<td bitCell>
<ng-container>
<span>{{ r.name }}</span>
</ng-container>
<br />
<small>{{ r.subTitle }}</small>
</td>
<td bitCell class="tw-text-right">
<span
bitBadge
*ngIf="passwordStrengthMap.has(r.id)"
[variant]="passwordStrengthMap.get(r.id)[1]"
>
{{ passwordStrengthMap.get(r.id)[0] | i18n }}
</span>
</td>
<td bitCell class="tw-text-right">
<span bitBadge *ngIf="passwordUseMap.has(r.login.password)" variant="warning">
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
</span>
</td>
<td bitCell class="tw-text-right">
<span bitBadge *ngIf="exposedPasswordMap.has(r.id)" variant="warning">
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(r.id) }}
</span>
</td>
<td bitCell class="tw-text-right" data-testid="total-membership">
{{ totalMembersMap.get(r.id) || 0 }}
</td>
</tr>
</ng-template>
</bit-table>
</div>
</div>

View File

@ -12,8 +12,8 @@ import { HeaderModule } from "../../layouts/header/header.module";
import { SharedModule } from "../../shared";
import { PipesModule } from "../../vault/individual-vault/pipes/pipes.module";
import { AccessIntelligenceTabType } from "./access-intelligence.component";
import { applicationTableMockData } from "./application-table.mock";
import { RiskInsightsTabType } from "./risk-insights.component";
@Component({
standalone: true,
@ -49,8 +49,8 @@ export class CriticalApplicationsComponent implements OnInit {
}
goToAllAppsTab = async () => {
await this.router.navigate([`organizations/${this.organizationId}/access-intelligence`], {
queryParams: { tabIndex: AccessIntelligenceTabType.AllApps },
await this.router.navigate([`organizations/${this.organizationId}/risk-insights`], {
queryParams: { tabIndex: RiskInsightsTabType.AllApps },
queryParamsHandling: "merge",
});
};

View File

@ -4,7 +4,7 @@ import { mock, MockProxy } from "jest-mock-extended";
import { of } from "rxjs";
// eslint-disable-next-line no-restricted-imports
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/risk-insights";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";

View File

@ -6,7 +6,7 @@ import { map } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
// eslint-disable-next-line no-restricted-imports
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/risk-insights";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";

View File

@ -0,0 +1,64 @@
<p>{{ "passwordsReportDesc" | i18n }}</p>
<div *ngIf="loading">
<i
class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
</div>
<div class="tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length">
<bit-table [dataSource]="dataSource">
<ng-container header>
<tr bitRow>
<th bitCell></th>
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th>
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th>
</tr>
</ng-container>
<ng-template body let-rows$>
<tr bitRow *ngFor="let r of rows$ | async; trackBy: trackByFunction">
<td bitCell>
<input
bitCheckbox
type="checkbox"
[checked]="selectedIds.has(r.id)"
(change)="onCheckboxChange(r.id, $event)"
/>
</td>
<td bitCell>
<ng-container>
<span>{{ r.name }}</span>
</ng-container>
<br />
<small>{{ r.subTitle }}</small>
</td>
<td bitCell class="tw-text-right">
<span
bitBadge
*ngIf="passwordStrengthMap.has(r.id)"
[variant]="passwordStrengthMap.get(r.id)[1]"
>
{{ passwordStrengthMap.get(r.id)[0] | i18n }}
</span>
</td>
<td bitCell class="tw-text-right">
<span bitBadge *ngIf="passwordUseMap.has(r.login.password)" variant="warning">
{{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
</span>
</td>
<td bitCell class="tw-text-right">
<span bitBadge *ngIf="exposedPasswordMap.has(r.id)" variant="warning">
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(r.id) }}
</span>
</td>
<td bitCell class="tw-text-right" data-testid="total-membership">
{{ totalMembersMap.get(r.id) || 0 }}
</td>
</tr>
</ng-template>
</bit-table>
</div>

View File

@ -5,7 +5,7 @@ import { ActivatedRoute } from "@angular/router";
import { debounceTime, map } from "rxjs";
// eslint-disable-next-line no-restricted-imports
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/risk-insights";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";

View File

@ -4,7 +4,7 @@ import { mock } from "jest-mock-extended";
import { of } from "rxjs";
// eslint-disable-next-line no-restricted-imports
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/risk-insights";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";

View File

@ -6,7 +6,7 @@ import { map } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
// eslint-disable-next-line no-restricted-imports
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/access-intelligence";
import { PasswordHealthService } from "@bitwarden/bit-common/tools/reports/risk-insights";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";

View File

@ -4,15 +4,15 @@ import { RouterModule, Routes } from "@angular/router";
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { AccessIntelligenceComponent } from "./access-intelligence.component";
import { RiskInsightsComponent } from "./risk-insights.component";
const routes: Routes = [
{
path: "",
component: AccessIntelligenceComponent,
component: RiskInsightsComponent,
canActivate: [canAccessFeature(FeatureFlag.AccessIntelligence)],
data: {
titleId: "accessIntelligence",
titleId: "RiskInsights",
},
},
];
@ -21,4 +21,4 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class AccessIntelligenceRoutingModule {}
export class RiskInsightsRoutingModule {}

View File

@ -1,4 +1,4 @@
<div class="tw-mb-1 text-primary" bitTypography="body1">{{ "accessIntelligence" | i18n }}</div>
<div class="tw-mb-1 text-primary" bitTypography="body1">{{ "riskInsights" | i18n }}</div>
<h1 bitTypography="h1">{{ "passwordRisk" | i18n }}</h1>
<div class="tw-text-muted">{{ "discoverAtRiskPasswords" | i18n }}</div>
<div class="tw-bg-primary-100 tw-rounded-lg tw-w-full tw-px-8 tw-py-2 tw-my-4">

View File

@ -15,7 +15,7 @@ import { PasswordHealthMembersURIComponent } from "./password-health-members-uri
import { PasswordHealthMembersComponent } from "./password-health-members.component";
import { PasswordHealthComponent } from "./password-health.component";
export enum AccessIntelligenceTabType {
export enum RiskInsightsTabType {
AllApps = 0,
CriticalApps = 1,
NotifiedMembers = 2,
@ -23,7 +23,7 @@ export enum AccessIntelligenceTabType {
@Component({
standalone: true,
templateUrl: "./access-intelligence.component.html",
templateUrl: "./risk-insights.component.html",
imports: [
AllApplicationsComponent,
AsyncActionsModule,
@ -39,8 +39,8 @@ export enum AccessIntelligenceTabType {
TabsModule,
],
})
export class AccessIntelligenceComponent {
tabIndex: AccessIntelligenceTabType;
export class RiskInsightsComponent {
tabIndex: RiskInsightsTabType;
dataLastUpdated = new Date();
apps: any[] = [];
@ -70,7 +70,7 @@ export class AccessIntelligenceComponent {
private router: Router,
) {
route.queryParams.pipe(takeUntilDestroyed()).subscribe(({ tabIndex }) => {
this.tabIndex = !isNaN(tabIndex) ? tabIndex : AccessIntelligenceTabType.AllApps;
this.tabIndex = !isNaN(tabIndex) ? tabIndex : RiskInsightsTabType.AllApps;
});
}
}

View File

@ -0,0 +1,9 @@
import { NgModule } from "@angular/core";
import { RiskInsightsRoutingModule } from "./risk-insights-routing.module";
import { RiskInsightsComponent } from "./risk-insights.component";
@NgModule({
imports: [RiskInsightsComponent, RiskInsightsRoutingModule],
})
export class RiskInsightsModule {}

View File

@ -5,8 +5,8 @@
"criticalApplications": {
"message": "Critical applications"
},
"accessIntelligence": {
"message": "Access Intelligence"
"riskInsights": {
"message": "Risk Insights"
},
"passwordRisk": {
"message": "Password Risk"

View File

@ -1,9 +1,9 @@
import { Inject, Injectable } from "@angular/core";
// eslint-disable-next-line no-restricted-imports
import { mockCiphers } from "@bitwarden/bit-common/tools/reports/access-intelligence/services/ciphers.mock";
import { mockCiphers } from "@bitwarden/bit-common/tools/reports/risk-insights/services/ciphers.mock";
// eslint-disable-next-line no-restricted-imports
import { mockMemberCipherDetailsResponse } from "@bitwarden/bit-common/tools/reports/access-intelligence/services/member-cipher-details-response.mock";
import { mockMemberCipherDetailsResponse } from "@bitwarden/bit-common/tools/reports/risk-insights/services/member-cipher-details-response.mock";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";