mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
Add initial "Reporting" tab
This commit is contained in:
@@ -55,6 +55,8 @@ import { ResetPasswordPolicyComponent } from "../organizations/policies/reset-pa
|
|||||||
import { SendOptionsPolicyComponent } from "../organizations/policies/send-options.component";
|
import { SendOptionsPolicyComponent } from "../organizations/policies/send-options.component";
|
||||||
import { SingleOrgPolicyComponent } from "../organizations/policies/single-org.component";
|
import { SingleOrgPolicyComponent } from "../organizations/policies/single-org.component";
|
||||||
import { TwoFactorAuthenticationPolicyComponent } from "../organizations/policies/two-factor-authentication.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 { AccountComponent as OrgAccountComponent } from "../organizations/settings/account.component";
|
||||||
import { AdjustSubscription } from "../organizations/settings/adjust-subscription.component";
|
import { AdjustSubscription } from "../organizations/settings/adjust-subscription.component";
|
||||||
import { BillingSyncApiKeyComponent } from "../organizations/settings/billing-sync-api-key.component";
|
import { BillingSyncApiKeyComponent } from "../organizations/settings/billing-sync-api-key.component";
|
||||||
@@ -267,6 +269,8 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
|||||||
OrgUserConfirmComponent,
|
OrgUserConfirmComponent,
|
||||||
OrgUserGroupsComponent,
|
OrgUserGroupsComponent,
|
||||||
OrgWeakPasswordsReportComponent,
|
OrgWeakPasswordsReportComponent,
|
||||||
|
OrgReportingComponent,
|
||||||
|
OrgReportListComponent,
|
||||||
GeneratorComponent,
|
GeneratorComponent,
|
||||||
PasswordGeneratorHistoryComponent,
|
PasswordGeneratorHistoryComponent,
|
||||||
PasswordGeneratorPolicyComponent,
|
PasswordGeneratorPolicyComponent,
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
<bit-tab-item *ngIf="showGroupsTab" [route]="['groups']">{{
|
<bit-tab-item *ngIf="showGroupsTab" [route]="['groups']">{{
|
||||||
"groups" | i18n
|
"groups" | i18n
|
||||||
}}</bit-tab-item>
|
}}</bit-tab-item>
|
||||||
<bit-tab-item *ngIf="showReportsTab" [route]="['reports']">{{
|
<bit-tab-item *ngIf="showReportsTab" [route]="['reporting']">{{
|
||||||
"reports" | i18n
|
"reporting" | i18n
|
||||||
}}</bit-tab-item>
|
}}</bit-tab-item>
|
||||||
<bit-tab-item *ngIf="showBillingTab" [route]="['billing']">{{
|
<bit-tab-item *ngIf="showBillingTab" [route]="['billing']">{{
|
||||||
"billing" | i18n
|
"billing" | i18n
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { EventsComponent } from "./manage/events.component";
|
|||||||
import { ManageComponent } from "./manage/manage.component";
|
import { ManageComponent } from "./manage/manage.component";
|
||||||
import { PoliciesComponent } from "./manage/policies.component";
|
import { PoliciesComponent } from "./manage/policies.component";
|
||||||
import { MembersComponent } from "./members/members.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 { NavigationPermissionsService } from "./services/navigation-permissions.service";
|
||||||
import { AccountComponent } from "./settings/account.component";
|
import { AccountComponent } from "./settings/account.component";
|
||||||
import { OrganizationBillingComponent } from "./settings/organization-billing.component";
|
import { OrganizationBillingComponent } from "./settings/organization-billing.component";
|
||||||
@@ -198,6 +200,82 @@ const routes: Routes = [
|
|||||||
permissions: [Permissions.ManageGroups],
|
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],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<a
|
<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"
|
[routerLink]="route"
|
||||||
(click)="click()"
|
(click)="click()"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1478,6 +1478,10 @@
|
|||||||
"message": "Identify and close security gaps in your online accounts by clicking the reports below.",
|
"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."
|
"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": {
|
"unsecuredWebsitesReport": {
|
||||||
"message": "Unsecure Websites"
|
"message": "Unsecure Websites"
|
||||||
},
|
},
|
||||||
@@ -5213,5 +5217,8 @@
|
|||||||
},
|
},
|
||||||
"members": {
|
"members": {
|
||||||
"message": "Members"
|
"message": "Members"
|
||||||
|
},
|
||||||
|
"reporting": {
|
||||||
|
"message": "Reporting"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user