1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-11 10:10:25 +01:00

[PM-12067] Add sorting to exposed passwords report (#11029)

* Add sorting to exposed passwords report

- Create new type to represent a row within the report
- Add types and remove usage of any
- Include the exposed number of times within the data passed to the datasource/table instead of looking it up via the `exposedPasswordMap`
- Enable sorting via bitSortable
- Set default sort to order by exposed number of times in descending order

* Show headers and sort also within AC version of exposed-passwords report but hide the Owner column

---------

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
Daniel James Smith 2024-09-18 18:53:04 +02:00 committed by GitHub
parent c9bcdd60ac
commit a674f698a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 12 deletions

View File

@ -27,12 +27,14 @@
</ng-container> </ng-container>
</bit-toggle-group> </bit-toggle-group>
<bit-table [dataSource]="dataSource"> <bit-table [dataSource]="dataSource">
<ng-container header *ngIf="!isAdminConsoleActive"> <ng-container header>
<tr bitRow> <tr bitRow>
<th bitCell></th> <th bitCell></th>
<th bitCell>{{ "name" | i18n }}</th> <th bitCell bitSortable="name">{{ "name" | i18n }}</th>
<th bitCell>{{ "owner" | i18n }}</th> <th bitCell bitSortable="organizationId" *ngIf="!isAdminConsoleActive">
<th bitCell></th> {{ "owner" | i18n }}
</th>
<th bitCell class="tw-text-right" bitSortable="exposedXTimes"></th>
</tr> </tr>
</ng-container> </ng-container>
<ng-template body let-rows$> <ng-template body let-rows$>
@ -74,7 +76,7 @@
<br /> <br />
<small>{{ r.subTitle }}</small> <small>{{ r.subTitle }}</small>
</td> </td>
<td bitCell> <td bitCell *ngIf="!isAdminConsoleActive">
<app-org-badge <app-org-badge
*ngIf="!organization" *ngIf="!organization"
[disabled]="disabled" [disabled]="disabled"
@ -86,7 +88,7 @@
</td> </td>
<td bitCell class="tw-text-right"> <td bitCell class="tw-text-right">
<span bitBadge variant="warning"> <span bitBadge variant="warning">
{{ "exposedXTimes" | i18n: (exposedPasswordMap.get(r.id) | number) }} {{ "exposedXTimes" | i18n: (r.exposedXTimes | number) }}
</span> </span>
</td> </td>
</tr> </tr>

View File

@ -11,12 +11,14 @@ 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";
type ReportResult = CipherView & { exposedXTimes: number };
@Component({ @Component({
selector: "app-exposed-passwords-report", selector: "app-exposed-passwords-report",
templateUrl: "exposed-passwords-report.component.html", templateUrl: "exposed-passwords-report.component.html",
}) })
export class ExposedPasswordsReportComponent extends CipherReportComponent implements OnInit { export class ExposedPasswordsReportComponent extends CipherReportComponent implements OnInit {
exposedPasswordMap = new Map<string, number>();
disabled = true; disabled = true;
constructor( constructor(
@ -44,12 +46,12 @@ export class ExposedPasswordsReportComponent extends CipherReportComponent imple
async setCiphers() { async setCiphers() {
const allCiphers = await this.getAllCiphers(); const allCiphers = await this.getAllCiphers();
const exposedPasswordCiphers: CipherView[] = []; const exposedPasswordCiphers: ReportResult[] = [];
const promises: Promise<void>[] = []; const promises: Promise<void>[] = [];
this.filterStatus = [0]; this.filterStatus = [0];
allCiphers.forEach((ciph: any) => { allCiphers.forEach((ciph) => {
const { type, login, isDeleted, edit, viewPassword, id } = ciph; const { type, login, isDeleted, edit, viewPassword } = ciph;
if ( if (
type !== CipherType.Login || type !== CipherType.Login ||
login.password == null || login.password == null ||
@ -63,8 +65,8 @@ export class ExposedPasswordsReportComponent extends CipherReportComponent imple
const promise = this.auditService.passwordLeaked(login.password).then((exposedCount) => { const promise = this.auditService.passwordLeaked(login.password).then((exposedCount) => {
if (exposedCount > 0) { if (exposedCount > 0) {
exposedPasswordCiphers.push(ciph); const row = { ...ciph, exposedXTimes: exposedCount } as ReportResult;
this.exposedPasswordMap.set(id, exposedCount); exposedPasswordCiphers.push(row);
} }
}); });
promises.push(promise); promises.push(promise);
@ -72,6 +74,7 @@ export class ExposedPasswordsReportComponent extends CipherReportComponent imple
await Promise.all(promises); await Promise.all(promises);
this.filterCiphersByOrg(exposedPasswordCiphers); this.filterCiphersByOrg(exposedPasswordCiphers);
this.dataSource.sort = { column: "exposedXTimes", direction: "desc" };
} }
protected canManageCipher(c: CipherView): boolean { protected canManageCipher(c: CipherView): boolean {