diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts index 89f120cbded..6855274498a 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts @@ -175,6 +175,65 @@ export class RiskInsightsDataService { } }; + setDrawerForCriticalAtRiskMembers = async (invokerId: string = ""): Promise => { + const { open, activeDrawerType, invokerId: currentInvokerId } = this.drawerDetailsSubject.value; + const shouldClose = + open && activeDrawerType === DrawerType.OrgAtRiskMembers && currentInvokerId === invokerId; + + if (shouldClose) { + this.closeDrawer(); + } else { + const reportResults = await firstValueFrom(this.criticalReportResults$); + if (!reportResults?.reportData) { + return; + } + + // Generate at-risk member list from critical applications + const atRiskMemberDetails = getAtRiskMemberList(reportResults.reportData); + + this.drawerDetailsSubject.next({ + open: true, + invokerId, + activeDrawerType: DrawerType.OrgAtRiskMembers, + atRiskMemberDetails, + appAtRiskMembers: null, + atRiskAppDetails: null, + }); + } + }; + + setDrawerForCriticalAtRiskApps = async (invokerId: string = ""): Promise => { + const { open, activeDrawerType, invokerId: currentInvokerId } = this.drawerDetailsSubject.value; + const shouldClose = + open && activeDrawerType === DrawerType.OrgAtRiskApps && currentInvokerId === invokerId; + + if (shouldClose) { + this.closeDrawer(); + } else { + const reportResults = await firstValueFrom(this.criticalReportResults$); + if (!reportResults?.reportData) { + return; + } + + // Filter critical applications for those with at-risk passwords + const criticalAtRiskApps = reportResults.reportData + .filter((app) => app.atRiskPasswordCount > 0) + .map((app) => ({ + applicationName: app.applicationName, + atRiskPasswordCount: app.atRiskPasswordCount, + })); + + this.drawerDetailsSubject.next({ + open: true, + invokerId, + activeDrawerType: DrawerType.OrgAtRiskApps, + atRiskMemberDetails: [], + appAtRiskMembers: null, + atRiskAppDetails: criticalAtRiskApps, + }); + } + }; + // ------------------------------ Critical application methods -------------- saveCriticalApplications(selectedUrls: string[]) { return this.orchestrator.saveCriticalApplications$(selectedUrls); diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html index 0eb9b30367c..756907d24e6 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.html @@ -23,11 +23,11 @@ } - @if (showNavigationLink && !buttonText) { + @if (showActionLink && !buttonText) { diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts index 7abedb06a7c..84c763841b5 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/activity-card.component.ts @@ -37,25 +37,14 @@ export class ActivityCardComponent { @Input() metricDescription: string = ""; /** - * The link to navigate to for more information + * The text to display for the action link */ - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() navigationLink: string = ""; + @Input() actionText: string = ""; /** - * The text to display for the navigation link + * Show action link */ - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() navigationText: string = ""; - - /** - * Show Navigation link - */ - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() showNavigationLink: boolean = false; + @Input() showActionLink: boolean = false; /** * Icon class to display next to metrics (e.g., "bwi-exclamation-triangle"). @@ -86,13 +75,18 @@ export class ActivityCardComponent { // eslint-disable-next-line @angular-eslint/prefer-output-emitter-ref @Output() buttonClick = new EventEmitter(); - constructor(private router: Router) {} + /** + * Event emitted when action link is clicked + */ + @Output() actionClick = new EventEmitter(); - navigateToLink = async (navigationLink: string) => { - await this.router.navigateByUrl(navigationLink); - }; + constructor(private router: Router) {} onButtonClick = () => { this.buttonClick.emit(); }; + + onActionClick = () => { + this.actionClick.emit(); + }; } diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html index 844b2f92bb3..9fffded215e 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html @@ -13,9 +13,9 @@ [title]="'atRiskMembers' | i18n" [cardMetrics]="'membersAtRiskCount' | i18n: totalCriticalAppsAtRiskMemberCount" [metricDescription]="'membersWithAccessToAtRiskItemsForCriticalApps' | i18n" - navigationText="{{ 'viewAtRiskMembers' | i18n }}" - navigationLink="{{ getLinkForRiskInsightsTab(RiskInsightsTabType.AllApps) }}" - [showNavigationLink]="totalCriticalAppsAtRiskMemberCount > 0" + actionText="{{ 'viewAtRiskMembers' | i18n }}" + [showActionLink]="totalCriticalAppsAtRiskMemberCount > 0" + (actionClick)="onViewAtRiskMembers()" > @@ -35,9 +35,9 @@ : ('criticalApplicationsAreAtRisk' | i18n: totalCriticalAppsAtRiskCount : totalCriticalAppsCount) " - navigationText="{{ 'viewAtRiskApplications' | i18n }}" - navigationLink="{{ getLinkForRiskInsightsTab(RiskInsightsTabType.CriticalApps) }}" - [showNavigationLink]="totalCriticalAppsAtRiskCount > 0" + actionText="{{ 'viewAtRiskApplications' | i18n }}" + [showActionLink]="totalCriticalAppsAtRiskCount > 0" + (actionClick)="onViewAtRiskApplications()" > diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts index 947e2f2fa42..9689110866a 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.ts @@ -15,7 +15,6 @@ import { getById } from "@bitwarden/common/platform/misc"; import { DialogService } from "@bitwarden/components"; import { SharedModule } from "@bitwarden/web-vault/app/shared"; -import { RiskInsightsTabType } from "../models/risk-insights.models"; import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.component"; import { ActivityCardComponent } from "./activity-card.component"; @@ -82,15 +81,6 @@ export class AllActivityComponent implements OnInit { } } - get RiskInsightsTabType() { - return RiskInsightsTabType; - } - - getLinkForRiskInsightsTab(tabIndex: RiskInsightsTabType): string { - const organizationId = this.activatedRoute.snapshot.paramMap.get("organizationId"); - return `/organizations/${organizationId}/access-intelligence/risk-insights?tabIndex=${tabIndex}`; - } - /** * Handles the review new applications button click. * Opens a dialog showing the list of new applications that can be marked as critical. @@ -102,4 +92,20 @@ export class AllActivityComponent implements OnInit { await firstValueFrom(dialogRef.closed); }; + + /** + * Handles the "View at-risk members" link click. + * Opens the at-risk members drawer for critical applications only. + */ + onViewAtRiskMembers = async () => { + await this.dataService.setDrawerForCriticalAtRiskMembers("activityTabAtRiskMembers"); + }; + + /** + * Handles the "View at-risk applications" link click. + * Opens the at-risk applications drawer for critical applications only. + */ + onViewAtRiskApplications = async () => { + await this.dataService.setDrawerForCriticalAtRiskApps("activityTabAtRiskApplications"); + }; }