1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 09:43:23 +00:00

[PM-4964] migrate exposed passwords report components (#9952)

* WIP - migrate exposed passwords report components

* lint fix

* migrate components in reports

* migrate breach and unsecured websites reports

* undo change routing

* revert changes to reports

* revert changes

* fix icon and padding in exposed passwords report

* fix icon and padding in exposed passwords report

* fix exposed passwords report cipher state

* [PM-4965] Migrate inactive two factor report (#10043)

* migrate inactive two factor report

* fix icon and padding in inactive two factor report

* [PM-4967] Migrate reused passwords report components (#10044)

* migrate components in reused passwords report

* fix icon and padding in reused passwords report

* [PM-4969] Migrate weak passwords report components (#10048)

* migrate weak passwords report component

* migrate weak passwords report component

* Revert "migrate weak passwords report component"

This reverts commit 0e453aafc1.

* Revert "migrate weak passwords report component"

This reverts commit e8e9b01997.

* Revert "Revert "migrate weak passwords report component""

This reverts commit 8cd2421cb0.

* fix padding and icon size in weak passwords report

---------

Co-authored-by: jordan-bite <jordan@bite-interactive.com>
This commit is contained in:
Jordan Aasen
2024-07-15 03:26:11 -07:00
committed by GitHub
parent 739cd8d25b
commit fb311bfb4b
6 changed files with 139 additions and 141 deletions

View File

@@ -9,6 +9,7 @@ import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.servi
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type"; import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { TableDataSource } from "@bitwarden/components";
import { PasswordRepromptService } from "@bitwarden/vault"; import { PasswordRepromptService } from "@bitwarden/vault";
import { AddEditComponent } from "../../../vault/individual-vault/add-edit.component"; import { AddEditComponent } from "../../../vault/individual-vault/add-edit.component";
@@ -24,6 +25,7 @@ export class CipherReportComponent implements OnDestroy {
hasLoaded = false; hasLoaded = false;
ciphers: CipherView[] = []; ciphers: CipherView[] = [];
allCiphers: CipherView[] = []; allCiphers: CipherView[] = [];
dataSource = new TableDataSource<CipherView>();
organization: Organization; organization: Organization;
organizations: Organization[]; organizations: Organization[];
organizations$: Observable<Organization[]>; organizations$: Observable<Organization[]>;
@@ -104,6 +106,7 @@ export class CipherReportComponent implements OnDestroy {
} else { } else {
this.ciphers = this.ciphers.filter((c: any) => c.orgFilterStatus === status); this.ciphers = this.ciphers.filter((c: any) => c.orgFilterStatus === status);
} }
this.dataSource.data = this.ciphers;
} }
async load() { async load() {
@@ -193,6 +196,8 @@ export class CipherReportComponent implements OnDestroy {
return ciph; return ciph;
}); });
this.dataSource.data = this.ciphers;
if (this.filterStatus.length > 2) { if (this.filterStatus.length > 2) {
this.showFilterToggle = true; this.showFilterToggle = true;
this.vaultMsg = "vaults"; this.vaultMsg = "vaults";

View File

@@ -6,13 +6,13 @@
{{ "checkExposedPasswords" | i18n }} {{ "checkExposedPasswords" | i18n }}
</button> </button>
<div class="mt-4" *ngIf="hasLoaded"> <div class="mt-4" *ngIf="hasLoaded">
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length"> <bit-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
{{ "noExposedPasswords" | i18n }} {{ "noExposedPasswords" | i18n }}
</app-callout> </bit-callout>
<ng-container *ngIf="ciphers.length"> <ng-container *ngIf="ciphers.length">
<app-callout type="danger" title="{{ 'exposedPasswordsFound' | i18n }}" [useAlertRole]="true"> <bit-callout type="danger" title="{{ 'exposedPasswordsFound' | i18n }}" [useAlertRole]="true">
{{ "exposedPasswordsFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }} {{ "exposedPasswordsFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }}
</app-callout> </bit-callout>
<bit-toggle-group <bit-toggle-group
*ngIf="showFilterToggle && !isAdminConsoleActive" *ngIf="showFilterToggle && !isAdminConsoleActive"
[selected]="filterOrgStatus$ | async" [selected]="filterOrgStatus$ | async"
@@ -26,36 +26,33 @@
</bit-toggle> </bit-toggle>
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<table class="table table-hover table-list table-ciphers"> <bit-table [dataSource]="dataSource" class="table">
<thead <ng-container header *ngIf="!isAdminConsoleActive">
class="tw-border-0 tw-border-b-2 tw-border-solid tw-border-secondary-300 tw-font-bold tw-text-muted"
*ngIf="!isAdminConsoleActive"
>
<tr> <tr>
<th></th> <th></th>
<th>{{ "name" | i18n }}</th> <th>{{ "name" | i18n }}</th>
<th>{{ "owner" | i18n }}</th> <th>{{ "owner" | i18n }}</th>
</tr> </tr>
</thead> </ng-container>
<tbody> <ng-template body let-rows$>
<tr *ngFor="let c of ciphers"> <tr bitRow *ngFor="let r of rows$ | async">
<td class="table-list-icon"> <td class="table-list-icon">
<app-vault-icon [cipher]="c"></app-vault-icon> <app-vault-icon [cipher]="r"></app-vault-icon>
</td> </td>
<td class="reduced-lh wrap"> <td>
<ng-container *ngIf="!organization || canManageCipher(c); else cantManage"> <ng-container *ngIf="!organization || canManageCipher(r); else cantManage">
<a <a
href="#" href="#"
appStopClick appStopClick
(click)="selectCipher(c)" (click)="selectCipher(r)"
title="{{ 'editItem' | i18n }}" title="{{ 'editItem' | i18n }}"
>{{ c.name }}</a >{{ r.name }}</a
> >
</ng-container> </ng-container>
<ng-template #cantManage> <ng-template #cantManage>
<span>{{ c.name }}</span> <span>{{ r.name }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="!organization && c.organizationId"> <ng-container *ngIf="!organization && r.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -64,7 +61,7 @@
></i> ></i>
<span class="sr-only">{{ "shared" | i18n }}</span> <span class="sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="c.hasAttachments"> <ng-container *ngIf="r.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -74,26 +71,26 @@
<span class="sr-only">{{ "attachments" | i18n }}</span> <span class="sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ c.subTitle }}</small> <small>{{ r.subTitle }}</small>
</td> </td>
<td> <td>
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="c.organizationId" [organizationId]="r.organizationId"
[organizationName]="c.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
</td> </td>
<td class="text-right"> <td class="text-right">
<span bitBadge variant="warning"> <span bitBadge variant="warning">
{{ "exposedXTimes" | i18n: (exposedPasswordMap.get(c.id) | number) }} {{ "exposedXTimes" | i18n: (exposedPasswordMap.get(r.id) | number) }}
</span> </span>
</td> </td>
</tr> </tr>
</tbody> </ng-template>
</table> </bit-table>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>

View File

@@ -11,7 +11,6 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { PasswordRepromptService } from "@bitwarden/vault"; import { PasswordRepromptService } from "@bitwarden/vault";
import { CipherReportComponent } from "./cipher-report.component"; import { CipherReportComponent } from "./cipher-report.component";
@Component({ @Component({
selector: "app-exposed-passwords-report", selector: "app-exposed-passwords-report",
templateUrl: "exposed-passwords-report.component.html", templateUrl: "exposed-passwords-report.component.html",

View File

@@ -11,13 +11,13 @@
<span class="sr-only">{{ "loading" | i18n }}</span> <span class="sr-only">{{ "loading" | i18n }}</span>
</div> </div>
<div class="mt-4" *ngIf="hasLoaded"> <div class="mt-4" *ngIf="hasLoaded">
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length"> <bit-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
{{ "noInactive2fa" | i18n }} {{ "noInactive2fa" | i18n }}
</app-callout> </bit-callout>
<ng-container *ngIf="ciphers.length"> <ng-container *ngIf="ciphers.length">
<app-callout type="danger" title="{{ 'inactive2faFound' | i18n }}"> <bit-callout type="danger" title="{{ 'inactive2faFound' | i18n }}">
{{ "inactive2faFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }} {{ "inactive2faFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }}
</app-callout> </bit-callout>
<bit-toggle-group <bit-toggle-group
*ngIf="showFilterToggle && !isAdminConsoleActive" *ngIf="showFilterToggle && !isAdminConsoleActive"
[selected]="filterOrgStatus$ | async" [selected]="filterOrgStatus$ | async"
@@ -31,27 +31,29 @@
</bit-toggle> </bit-toggle>
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<table class="table table-hover table-list table-ciphers"> <bit-table [dataSource]="dataSource" class="table">
<thead <ng-container header *ngIf="!isAdminConsoleActive">
class="tw-border-0 tw-border-b-2 tw-border-solid tw-border-secondary-300 tw-font-bold tw-text-muted"
*ngIf="!isAdminConsoleActive"
>
<tr> <tr>
<th></th> <th></th>
<th>{{ "name" | i18n }}</th> <th>{{ "name" | i18n }}</th>
<th>{{ "owner" | i18n }}</th> <th>{{ "owner" | i18n }}</th>
</tr> </tr>
</thead> </ng-container>
<tbody> <tbody>
<tr *ngFor="let c of ciphers"> <ng-template body let-rows$>
<tr bitRow *ngFor="let r of rows$ | async">
<td class="table-list-icon"> <td class="table-list-icon">
<app-vault-icon [cipher]="c"></app-vault-icon> <app-vault-icon [cipher]="r"></app-vault-icon>
</td> </td>
<td class="reduced-lh wrap"> <td class="reduced-lh wrap">
<a href="#" appStopClick (click)="selectCipher(c)" title="{{ 'editItem' | i18n }}">{{ <a
c.name href="#"
}}</a> appStopClick
<ng-container *ngIf="!organization && c.organizationId"> (click)="selectCipher(r)"
title="{{ 'editItem' | i18n }}"
>{{ r.name }}</a
>
<ng-container *ngIf="!organization && r.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -60,7 +62,7 @@
></i> ></i>
<span class="sr-only">{{ "shared" | i18n }}</span> <span class="sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="c.hasAttachments"> <ng-container *ngIf="r.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -70,14 +72,14 @@
<span class="sr-only">{{ "attachments" | i18n }}</span> <span class="sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ c.subTitle }}</small> <small>{{ r.subTitle }}</small>
</td> </td>
<td> <td>
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="c.organizationId" [organizationId]="r.organizationId"
[organizationName]="c.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
@@ -85,17 +87,18 @@
<td class="text-right"> <td class="text-right">
<a <a
bitBadge bitBadge
href="{{ cipherDocs.get(c.id) }}" href="{{ cipherDocs.get(r.id) }}"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
*ngIf="cipherDocs.has(c.id)" *ngIf="cipherDocs.has(r.id)"
> >
{{ "instructions" | i18n }}</a {{ "instructions" | i18n }}</a
> >
</td> </td>
</tr> </tr>
</tbody> </ng-template>
</table> </tbody></bit-table
>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>

View File

@@ -11,13 +11,13 @@
<span class="sr-only">{{ "loading" | i18n }}</span> <span class="sr-only">{{ "loading" | i18n }}</span>
</div> </div>
<div class="mt-4" *ngIf="hasLoaded"> <div class="mt-4" *ngIf="hasLoaded">
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length"> <bit-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
{{ "noReusedPasswords" | i18n }} {{ "noReusedPasswords" | i18n }}
</app-callout> </bit-callout>
<ng-container *ngIf="ciphers.length"> <ng-container *ngIf="ciphers.length">
<app-callout type="danger" title="{{ 'reusedPasswordsFound' | i18n }}"> <bit-callout type="danger" title="{{ 'reusedPasswordsFound' | i18n }}">
{{ "reusedPasswordsFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }} {{ "reusedPasswordsFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }}
</app-callout> </bit-callout>
<bit-toggle-group <bit-toggle-group
*ngIf="showFilterToggle && !isAdminConsoleActive" *ngIf="showFilterToggle && !isAdminConsoleActive"
@@ -33,36 +33,33 @@
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<table class="table table-hover table-list table-ciphers"> <bit-table [dataSource]="dataSource" class="table">
<thead <ng-container header *ngIf="!isAdminConsoleActive">
class="tw-border-0 tw-border-b-2 tw-border-solid tw-border-secondary-300 tw-font-bold tw-text-muted"
*ngIf="!isAdminConsoleActive"
>
<tr> <tr>
<th></th> <th></th>
<th>{{ "name" | i18n }}</th> <th>{{ "name" | i18n }}</th>
<th>{{ "owner" | i18n }}</th> <th>{{ "owner" | i18n }}</th>
</tr> </tr>
</thead> </ng-container>
<tbody> <ng-template body let-rows$>
<tr *ngFor="let c of ciphers"> <tr bitRow *ngFor="let r of rows$ | async">
<td class="table-list-icon"> <td class="table-list-icon">
<app-vault-icon [cipher]="c"></app-vault-icon> <app-vault-icon [cipher]="r"></app-vault-icon>
</td> </td>
<td class="reduced-lh wrap"> <td>
<ng-container *ngIf="!organization || canManageCipher(c); else cantManage"> <ng-container *ngIf="!organization || canManageCipher(r); else cantManage">
<a <a
href="#" href="#"
appStopClick appStopClick
(click)="selectCipher(c)" (click)="selectCipher(r)"
title="{{ 'editItem' | i18n }}" title="{{ 'editItem' | i18n }}"
>{{ c.name }}</a >{{ r.name }}</a
> >
</ng-container> </ng-container>
<ng-template #cantManage> <ng-template #cantManage>
<span>{{ c.name }}</span> <span>{{ r.name }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="!organization && c.organizationId"> <ng-container *ngIf="!organization && r.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -71,7 +68,7 @@
></i> ></i>
<span class="sr-only">{{ "shared" | i18n }}</span> <span class="sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="c.hasAttachments"> <ng-container *ngIf="r.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -81,26 +78,26 @@
<span class="sr-only">{{ "attachments" | i18n }}</span> <span class="sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ c.subTitle }}</small> <small>{{ r.subTitle }}</small>
</td> </td>
<td> <td>
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="c.organizationId" [organizationId]="r.organizationId"
[organizationName]="c.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
</td> </td>
<td class="text-right"> <td class="text-right">
<span bitBadge variant="warning"> <span bitBadge variant="warning">
{{ "reusedXTimes" | i18n: passwordUseMap.get(c.login.password) }} {{ "reusedXTimes" | i18n: passwordUseMap.get(r.login.password) }}
</span> </span>
</td> </td>
</tr> </tr>
</tbody> </ng-template>
</table> </bit-table>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>

View File

@@ -11,13 +11,13 @@
<span class="sr-only">{{ "loading" | i18n }}</span> <span class="sr-only">{{ "loading" | i18n }}</span>
</div> </div>
<div class="mt-4" *ngIf="hasLoaded"> <div class="mt-4" *ngIf="hasLoaded">
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length"> <bit-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
{{ "noWeakPasswords" | i18n }} {{ "noWeakPasswords" | i18n }}
</app-callout> </bit-callout>
<ng-container *ngIf="ciphers.length"> <ng-container *ngIf="ciphers.length">
<app-callout type="danger" title="{{ 'weakPasswordsFound' | i18n }}"> <bit-callout type="danger" title="{{ 'weakPasswordsFound' | i18n }}">
{{ "weakPasswordsFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }} {{ "weakPasswordsFoundReportDesc" | i18n: (ciphers.length | number) : vaultMsg }}
</app-callout> </bit-callout>
<bit-toggle-group <bit-toggle-group
*ngIf="showFilterToggle && !isAdminConsoleActive" *ngIf="showFilterToggle && !isAdminConsoleActive"
[selected]="filterOrgStatus$ | async" [selected]="filterOrgStatus$ | async"
@@ -31,36 +31,33 @@
</bit-toggle> </bit-toggle>
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<table class="table table-hover table-list table-ciphers"> <bit-table [dataSource]="dataSource" class="table">
<thead <ng-container header *ngIf="!isAdminConsoleActive">
class="tw-border-0 tw-border-b-2 tw-border-solid tw-border-secondary-300 tw-font-bold tw-text-muted"
*ngIf="!isAdminConsoleActive"
>
<tr> <tr>
<th></th> <th></th>
<th>{{ "name" | i18n }}</th> <th>{{ "name" | i18n }}</th>
<th>{{ "owner" | i18n }}</th> <th>{{ "owner" | i18n }}</th>
</tr> </tr>
</thead> </ng-container>
<tbody> <ng-template body let-rows$>
<tr *ngFor="let c of ciphers"> <tr bitRow *ngFor="let r of rows$ | async">
<td class="table-list-icon"> <td class="table-list-icon">
<app-vault-icon [cipher]="c"></app-vault-icon> <app-vault-icon [cipher]="r"></app-vault-icon>
</td> </td>
<td class="reduced-lh wrap"> <td class="reduced-lh wrap">
<ng-container *ngIf="!organization || canManageCipher(c); else cantManage"> <ng-container *ngIf="!organization || canManageCipher(r); else cantManage">
<a <a
href="#" href="#"
appStopClick appStopClick
(click)="selectCipher(c)" (click)="selectCipher(r)"
title="{{ 'editItem' | i18n }}" title="{{ 'editItem' | i18n }}"
>{{ c.name }}</a >{{ r.name }}</a
> >
</ng-container> </ng-container>
<ng-template #cantManage> <ng-template #cantManage>
<span>{{ c.name }}</span> <span>{{ r.name }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="!organization && c.organizationId"> <ng-container *ngIf="!organization && r.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"
appStopProp appStopProp
@@ -69,7 +66,7 @@
></i> ></i>
<span class="sr-only">{{ "shared" | i18n }}</span> <span class="sr-only">{{ "shared" | i18n }}</span>
</ng-container> </ng-container>
<ng-container *ngIf="c.hasAttachments"> <ng-container *ngIf="r.hasAttachments">
<i <i
class="bwi bwi-paperclip" class="bwi bwi-paperclip"
appStopProp appStopProp
@@ -79,26 +76,26 @@
<span class="sr-only">{{ "attachments" | i18n }}</span> <span class="sr-only">{{ "attachments" | i18n }}</span>
</ng-container> </ng-container>
<br /> <br />
<small>{{ c.subTitle }}</small> <small>{{ r.subTitle }}</small>
</td> </td>
<td> <td>
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
[organizationId]="c.organizationId" [organizationId]="r.organizationId"
[organizationName]="c.organizationId | orgNameFromId: (organizations$ | async)" [organizationName]="r.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp appStopProp
> >
</app-org-badge> </app-org-badge>
</td> </td>
<td class="text-right"> <td class="text-right">
<span bitBadge [variant]="passwordStrengthMap.get(c.id)[1]"> <span bitBadge [variant]="passwordStrengthMap.get(r.id)[1]">
{{ passwordStrengthMap.get(c.id)[0] | i18n }} {{ passwordStrengthMap.get(r.id)[0] | i18n }}
</span> </span>
</td> </td>
</tr> </tr>
</tbody> </ng-template>
</table> </bit-table>
</ng-container> </ng-container>
</div> </div>
<ng-template #cipherAddEdit></ng-template> <ng-template #cipherAddEdit></ng-template>