1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

Add initial "Reporting" tab

This commit is contained in:
Shane Melton
2022-07-12 16:43:55 -07:00
parent 3825bf7b17
commit 4dc9fe178e
9 changed files with 203 additions and 3 deletions

View File

@@ -55,6 +55,8 @@ import { ResetPasswordPolicyComponent } from "../organizations/policies/reset-pa
import { SendOptionsPolicyComponent } from "../organizations/policies/send-options.component";
import { SingleOrgPolicyComponent } from "../organizations/policies/single-org.component";
import { TwoFactorAuthenticationPolicyComponent } from "../organizations/policies/two-factor-authentication.component";
import { ReportListComponent as OrgReportListComponent } from "../organizations/reporting/report-list.component";
import { ReportingComponent as OrgReportingComponent } from "../organizations/reporting/reporting.component";
import { AccountComponent as OrgAccountComponent } from "../organizations/settings/account.component";
import { AdjustSubscription } from "../organizations/settings/adjust-subscription.component";
import { BillingSyncApiKeyComponent } from "../organizations/settings/billing-sync-api-key.component";
@@ -267,6 +269,8 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
OrgUserConfirmComponent,
OrgUserGroupsComponent,
OrgWeakPasswordsReportComponent,
OrgReportingComponent,
OrgReportListComponent,
GeneratorComponent,
PasswordGeneratorHistoryComponent,
PasswordGeneratorPolicyComponent,

View File

@@ -14,8 +14,8 @@
<bit-tab-item *ngIf="showGroupsTab" [route]="['groups']">{{
"groups" | i18n
}}</bit-tab-item>
<bit-tab-item *ngIf="showReportsTab" [route]="['reports']">{{
"reports" | i18n
<bit-tab-item *ngIf="showReportsTab" [route]="['reporting']">{{
"reporting" | i18n
}}</bit-tab-item>
<bit-tab-item *ngIf="showBillingTab" [route]="['billing']">{{
"billing" | i18n

View File

@@ -14,6 +14,8 @@ import { EventsComponent } from "./manage/events.component";
import { ManageComponent } from "./manage/manage.component";
import { PoliciesComponent } from "./manage/policies.component";
import { MembersComponent } from "./members/members.component";
import { ReportListComponent } from "./reporting/report-list.component";
import { ReportingComponent } from "./reporting/reporting.component";
import { NavigationPermissionsService } from "./services/navigation-permissions.service";
import { AccountComponent } from "./settings/account.component";
import { OrganizationBillingComponent } from "./settings/organization-billing.component";
@@ -198,6 +200,82 @@ const routes: Routes = [
permissions: [Permissions.ManageGroups],
},
},
{
path: "reporting",
component: ReportingComponent,
canActivate: [PermissionsGuard],
data: {
permissions: [Permissions.AccessReports],
},
children: [
{ path: "", pathMatch: "full", redirectTo: "reports" },
{
path: "reports",
component: ReportListComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "reports",
permissions: [Permissions.AccessReports],
},
children: [
{
path: "exposed-passwords-report",
component: ExposedPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "exposedPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "inactive-two-factor-report",
component: InactiveTwoFactorReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "inactive2faReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "reused-passwords-report",
component: ReusedPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "reusedPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "unsecured-websites-report",
component: UnsecuredWebsitesReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "unsecuredWebsitesReport",
permissions: [Permissions.AccessReports],
},
},
{
path: "weak-passwords-report",
component: WeakPasswordsReportComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "weakPasswordsReport",
permissions: [Permissions.AccessReports],
},
},
],
},
{
path: "events",
component: EventsComponent,
canActivate: [PermissionsGuard],
data: {
titleId: "eventLogs",
permissions: [Permissions.AccessEventLogs],
},
},
],
},
],
},
];

View File

@@ -0,0 +1,24 @@
<ng-container *ngIf="homepage">
<div class="page-header">
<h1>{{ "reports" | i18n }}</h1>
</div>
<p>{{ "orgsReportsDesc" | i18n }}</p>
<div class="tw-inline-grid tw-grid-cols-3 tw-gap-4">
<div *ngFor="let report of reports">
<app-report-card [type]="report"></app-report-card>
</div>
</div>
</ng-container>
<router-outlet></router-outlet>
<div class="row mt-4">
<div class="col">
<a bitButton routerLink="./" *ngIf="!homepage">
<i class="bwi bwi-angle-left" aria-hidden="true"></i>
{{ "backToReports" | i18n }}
</a>
</div>
</div>

View File

@@ -0,0 +1,34 @@
import { Component } from "@angular/core";
import { NavigationEnd, Router } from "@angular/router";
import { filter, Subscription } from "rxjs";
import { ReportTypes } from "../../reports/report-card.component";
@Component({
selector: "app-org-report-list",
templateUrl: "report-list.component.html",
})
export class ReportListComponent {
reports = [
ReportTypes.exposedPasswords,
ReportTypes.reusedPasswords,
ReportTypes.weakPasswords,
ReportTypes.unsecuredWebsites,
ReportTypes.inactive2fa,
];
homepage = true;
subscription: Subscription;
constructor(router: Router) {
this.subscription = router.events
.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe((event) => {
this.homepage = (event as NavigationEnd).urlAfterRedirects.endsWith("/reports");
});
}
ngOnDestroy(): void {
this.subscription?.unsubscribe();
}
}

View File

@@ -0,0 +1,30 @@
<div class="container page-content">
<div class="row">
<div class="col-3">
<div class="card" *ngIf="organization">
<div class="card-header">{{ "reporting" | i18n }}</div>
<div class="list-group list-group-flush">
<a
routerLink="reports"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canAccessReports"
>
{{ "reports" | i18n }}
</a>
<a
routerLink="events"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canAccessEventLogs && accessEvents"
>
{{ "eventLogs" | i18n }}
</a>
</div>
</div>
</div>
<div class="col-9">
<router-outlet></router-outlet>
</div>
</div>
</div>

View File

@@ -0,0 +1,23 @@
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { Organization } from "@bitwarden/common/models/domain/organization";
@Component({
selector: "app-org-reporting",
templateUrl: "reporting.component.html",
})
export class ReportingComponent implements OnInit {
organization: Organization;
accessEvents = false;
constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {}
ngOnInit() {
this.route.parent.params.subscribe(async (params) => {
this.organization = await this.organizationService.get(params.organizationId);
this.accessEvents = this.organization.useEvents;
});
}
}

View File

@@ -1,5 +1,5 @@
<a
class="tw-border tw-border-solid tw-border-secondary-300 tw-rounded tw-overflow-hidden tw-h-full tw-w-72 tw-block !tw-text-main hover:tw-no-underline hover:tw-scale-105 tw-transition-all focus:tw-outline-none focus:tw-ring focus:tw-ring-offset-2 focus:tw-ring-primary-700"
class="tw-border tw-border-solid tw-border-secondary-300 tw-rounded tw-overflow-hidden tw-h-full tw-max-w-[18rem] tw-block !tw-text-main hover:tw-no-underline hover:tw-scale-105 tw-transition-all focus:tw-outline-none focus:tw-ring focus:tw-ring-offset-2 focus:tw-ring-primary-700"
[routerLink]="route"
(click)="click()"
>

View File

@@ -1478,6 +1478,10 @@
"message": "Identify and close security gaps in your online accounts by clicking the reports below.",
"description": "Vault Health Reports can be used to evaluate the security of your Bitwarden Personal or Organization Vault."
},
"orgsReportsDesc": {
"message": "Identify and close security gaps in your organization's accounts by clicking the reports below.",
"description": "Vault Health Reports can be used to evaluate the security of your Bitwarden Personal or Organization Vault."
},
"unsecuredWebsitesReport": {
"message": "Unsecure Websites"
},
@@ -5213,5 +5217,8 @@
},
"members": {
"message": "Members"
},
"reporting": {
"message": "Reporting"
}
}