10 changed files with 0 additions and 612 deletions
@ -1,51 +0,0 @@
@@ -1,51 +0,0 @@
|
||||
<bit-container> |
||||
<p>{{ "passwordsReportDesc" | i18n }}</p> |
||||
<div *ngIf="loading"> |
||||
<i |
||||
class="bwi bwi-spinner bwi-spin tw-text-muted" |
||||
title="{{ 'loading' | i18n }}" |
||||
aria-hidden="true" |
||||
></i> |
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span> |
||||
</div> |
||||
<div class="tw-mt-4" *ngIf="!loading"> |
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="53"> |
||||
<ng-container header> |
||||
<th bitCell bitSortable="hostURI">{{ "application" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th> |
||||
</ng-container> |
||||
<ng-template bitRowDef let-row> |
||||
<td bitCell> |
||||
<ng-container> |
||||
<span>{{ row.hostURI }}</span> |
||||
</ng-container> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span |
||||
bitBadge |
||||
*ngIf="passwordStrengthMap.has(row.id)" |
||||
[variant]="passwordStrengthMap.get(row.id)[1]" |
||||
> |
||||
{{ passwordStrengthMap.get(row.id)[0] | i18n }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span bitBadge *ngIf="passwordUseMap.has(row.login.password)" variant="warning"> |
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span bitBadge *ngIf="exposedPasswordMap.has(row.id)" variant="warning"> |
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(row.id) }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right" data-testid="total-membership"> |
||||
{{ totalMembersMap.get(row.id) || 0 }} |
||||
</td> |
||||
</ng-template> |
||||
</bit-table-scroll> |
||||
</div> |
||||
</bit-container> |
||||
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing"; |
||||
import { ActivatedRoute, convertToParamMap } from "@angular/router"; |
||||
import { mock, MockProxy } from "jest-mock-extended"; |
||||
import { of } from "rxjs"; |
||||
|
||||
import { |
||||
MemberCipherDetailsApiService, |
||||
PasswordHealthService, |
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights"; |
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service"; |
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service"; |
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; |
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; |
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; |
||||
import { Utils } from "@bitwarden/common/platform/misc/utils"; |
||||
import { mockAccountServiceWith } from "@bitwarden/common/spec"; |
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; |
||||
import { UserId } from "@bitwarden/common/types/guid"; |
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; |
||||
import { TableModule } from "@bitwarden/components"; |
||||
import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared"; |
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; |
||||
|
||||
import { PasswordHealthMembersURIComponent } from "./password-health-members-uri.component"; |
||||
|
||||
describe("PasswordHealthMembersUriComponent", () => { |
||||
let component: PasswordHealthMembersURIComponent; |
||||
let fixture: ComponentFixture<PasswordHealthMembersURIComponent>; |
||||
let cipherServiceMock: MockProxy<CipherService>; |
||||
const passwordHealthServiceMock = mock<PasswordHealthService>(); |
||||
const userId = Utils.newGuid() as UserId; |
||||
|
||||
const activeRouteParams = convertToParamMap({ organizationId: "orgId" }); |
||||
|
||||
beforeEach(async () => { |
||||
cipherServiceMock = mock<CipherService>(); |
||||
await TestBed.configureTestingModule({ |
||||
imports: [PasswordHealthMembersURIComponent, PipesModule, TableModule, LooseComponentsModule], |
||||
providers: [ |
||||
{ provide: CipherService, useValue: cipherServiceMock }, |
||||
{ provide: I18nService, useValue: mock<I18nService>() }, |
||||
{ provide: AuditService, useValue: mock<AuditService>() }, |
||||
{ provide: OrganizationService, useValue: mock<OrganizationService>() }, |
||||
{ provide: AccountService, useValue: mockAccountServiceWith(userId) }, |
||||
{ |
||||
provide: PasswordStrengthServiceAbstraction, |
||||
useValue: mock<PasswordStrengthServiceAbstraction>(), |
||||
}, |
||||
{ provide: PasswordHealthService, useValue: passwordHealthServiceMock }, |
||||
{ |
||||
provide: ActivatedRoute, |
||||
useValue: { |
||||
paramMap: of(activeRouteParams), |
||||
url: of([]), |
||||
}, |
||||
}, |
||||
{ |
||||
provide: MemberCipherDetailsApiService, |
||||
useValue: mock<MemberCipherDetailsApiService>(), |
||||
}, |
||||
{ |
||||
provide: ApiService, |
||||
useValue: mock<ApiService>(), |
||||
}, |
||||
], |
||||
}).compileComponents(); |
||||
}); |
||||
|
||||
beforeEach(() => { |
||||
fixture = TestBed.createComponent(PasswordHealthMembersURIComponent); |
||||
component = fixture.componentInstance; |
||||
}); |
||||
|
||||
it("should initialize component", () => { |
||||
expect(component).toBeTruthy(); |
||||
}); |
||||
}); |
||||
@ -1,107 +0,0 @@
@@ -1,107 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { CommonModule } from "@angular/common"; |
||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core"; |
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; |
||||
import { ActivatedRoute } from "@angular/router"; |
||||
import { map } from "rxjs"; |
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module"; |
||||
import { |
||||
MemberCipherDetailsApiService, |
||||
PasswordHealthService, |
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights"; |
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service"; |
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; |
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; |
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; |
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; |
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; |
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; |
||||
import { |
||||
BadgeModule, |
||||
BadgeVariant, |
||||
ContainerComponent, |
||||
TableDataSource, |
||||
TableModule, |
||||
} from "@bitwarden/components"; |
||||
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; |
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; |
||||
|
||||
@Component({ |
||||
selector: "tools-password-health-members-uri", |
||||
templateUrl: "password-health-members-uri.component.html", |
||||
imports: [ |
||||
BadgeModule, |
||||
CommonModule, |
||||
ContainerComponent, |
||||
PipesModule, |
||||
JslibModule, |
||||
HeaderModule, |
||||
TableModule, |
||||
], |
||||
providers: [PasswordHealthService, MemberCipherDetailsApiService], |
||||
}) |
||||
export class PasswordHealthMembersURIComponent implements OnInit { |
||||
passwordStrengthMap = new Map<string, [string, BadgeVariant]>(); |
||||
|
||||
weakPasswordCiphers: CipherView[] = []; |
||||
|
||||
passwordUseMap = new Map<string, number>(); |
||||
|
||||
exposedPasswordMap = new Map<string, number>(); |
||||
|
||||
totalMembersMap = new Map<string, number>(); |
||||
|
||||
dataSource = new TableDataSource<CipherView>(); |
||||
|
||||
reportCiphers: (CipherView & { hostURI: string })[] = []; |
||||
reportCipherURIs: string[] = []; |
||||
|
||||
organization: Organization; |
||||
|
||||
loading = true; |
||||
|
||||
private destroyRef = inject(DestroyRef); |
||||
|
||||
constructor( |
||||
protected cipherService: CipherService, |
||||
protected passwordStrengthService: PasswordStrengthServiceAbstraction, |
||||
protected organizationService: OrganizationService, |
||||
protected auditService: AuditService, |
||||
protected i18nService: I18nService, |
||||
protected activatedRoute: ActivatedRoute, |
||||
protected memberCipherDetailsApiService: MemberCipherDetailsApiService, |
||||
) {} |
||||
|
||||
ngOnInit() { |
||||
this.activatedRoute.paramMap |
||||
.pipe( |
||||
takeUntilDestroyed(this.destroyRef), |
||||
map(async (params) => { |
||||
const organizationId = params.get("organizationId"); |
||||
await this.setCiphers(organizationId); |
||||
}), |
||||
) |
||||
.subscribe(); |
||||
} |
||||
|
||||
async setCiphers(organizationId: string) { |
||||
const passwordHealthService = new PasswordHealthService( |
||||
this.passwordStrengthService, |
||||
this.auditService, |
||||
this.cipherService, |
||||
this.memberCipherDetailsApiService, |
||||
organizationId, |
||||
); |
||||
|
||||
await passwordHealthService.generateReport(); |
||||
|
||||
this.dataSource.data = passwordHealthService.groupCiphersByLoginUri(); |
||||
this.exposedPasswordMap = passwordHealthService.exposedPasswordMap; |
||||
this.passwordStrengthMap = passwordHealthService.passwordStrengthMap; |
||||
this.passwordUseMap = passwordHealthService.passwordUseMap; |
||||
this.totalMembersMap = passwordHealthService.totalMembersMap; |
||||
this.loading = false; |
||||
} |
||||
} |
||||
@ -1,60 +0,0 @@
@@ -1,60 +0,0 @@
|
||||
<p>{{ "passwordsReportDesc" | i18n }}</p> |
||||
<div *ngIf="loading"> |
||||
<i |
||||
class="bwi bwi-spinner bwi-spin tw-text-muted" |
||||
title="{{ 'loading' | i18n }}" |
||||
aria-hidden="true" |
||||
></i> |
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span> |
||||
</div> |
||||
<div class="tw-flex tw-flex-col" *ngIf="!loading && dataSource.data.length"> |
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="74"> |
||||
<ng-container header> |
||||
<th bitCell></th> |
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "totalMembers" | i18n }}</th> |
||||
</ng-container> |
||||
<ng-template bitRowDef let-row> |
||||
<td bitCell> |
||||
<input |
||||
bitCheckbox |
||||
type="checkbox" |
||||
[checked]="selectedIds.has(row.id)" |
||||
(change)="onCheckboxChange(row.id, $event)" |
||||
/> |
||||
</td> |
||||
<td bitCell> |
||||
<ng-container> |
||||
<span>{{ row.name }}</span> |
||||
</ng-container> |
||||
<br /> |
||||
<small>{{ row.subTitle }}</small> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span |
||||
bitBadge |
||||
*ngIf="passwordStrengthMap.has(row.id)" |
||||
[variant]="passwordStrengthMap.get(row.id)[1]" |
||||
> |
||||
{{ passwordStrengthMap.get(row.id)[0] | i18n }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span bitBadge *ngIf="passwordUseMap.has(row.login.password)" variant="warning"> |
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span bitBadge *ngIf="exposedPasswordMap.has(row.id)" variant="warning"> |
||||
{{ "exposedXTimes" | i18n: exposedPasswordMap.get(row.id) }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right" data-testid="total-membership"> |
||||
{{ totalMembersMap.get(row.id) || 0 }} |
||||
</td> |
||||
</ng-template> |
||||
</bit-table-scroll> |
||||
</div> |
||||
@ -1,127 +0,0 @@
@@ -1,127 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core"; |
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; |
||||
import { FormControl, FormsModule } from "@angular/forms"; |
||||
import { ActivatedRoute } from "@angular/router"; |
||||
import { debounceTime, map } from "rxjs"; |
||||
|
||||
import { |
||||
MemberCipherDetailsApiService, |
||||
PasswordHealthService, |
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights"; |
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service"; |
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; |
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength"; |
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; |
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; |
||||
import { |
||||
BadgeVariant, |
||||
SearchModule, |
||||
TableDataSource, |
||||
TableModule, |
||||
ToastService, |
||||
} from "@bitwarden/components"; |
||||
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; |
||||
import { SharedModule } from "@bitwarden/web-vault/app/shared"; |
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; |
||||
|
||||
@Component({ |
||||
selector: "tools-password-health-members", |
||||
templateUrl: "password-health-members.component.html", |
||||
imports: [PipesModule, HeaderModule, SearchModule, FormsModule, SharedModule, TableModule], |
||||
providers: [PasswordHealthService, MemberCipherDetailsApiService], |
||||
}) |
||||
export class PasswordHealthMembersComponent implements OnInit { |
||||
passwordStrengthMap = new Map<string, [string, BadgeVariant]>(); |
||||
|
||||
passwordUseMap = new Map<string, number>(); |
||||
|
||||
exposedPasswordMap = new Map<string, number>(); |
||||
|
||||
totalMembersMap = new Map<string, number>(); |
||||
|
||||
dataSource = new TableDataSource<CipherView>(); |
||||
|
||||
loading = true; |
||||
|
||||
selectedIds: Set<number> = new Set<number>(); |
||||
|
||||
protected searchControl = new FormControl("", { nonNullable: true }); |
||||
|
||||
private destroyRef = inject(DestroyRef); |
||||
|
||||
constructor( |
||||
protected cipherService: CipherService, |
||||
protected passwordStrengthService: PasswordStrengthServiceAbstraction, |
||||
protected auditService: AuditService, |
||||
protected i18nService: I18nService, |
||||
protected activatedRoute: ActivatedRoute, |
||||
protected toastService: ToastService, |
||||
protected memberCipherDetailsApiService: MemberCipherDetailsApiService, |
||||
) { |
||||
this.searchControl.valueChanges |
||||
.pipe(debounceTime(200), takeUntilDestroyed()) |
||||
.subscribe((v) => (this.dataSource.filter = v)); |
||||
} |
||||
|
||||
ngOnInit() { |
||||
this.activatedRoute.paramMap |
||||
.pipe( |
||||
takeUntilDestroyed(this.destroyRef), |
||||
map(async (params) => { |
||||
const organizationId = params.get("organizationId"); |
||||
await this.setCiphers(organizationId); |
||||
}), |
||||
) |
||||
.subscribe(); |
||||
} |
||||
|
||||
async setCiphers(organizationId: string) { |
||||
const passwordHealthService = new PasswordHealthService( |
||||
this.passwordStrengthService, |
||||
this.auditService, |
||||
this.cipherService, |
||||
this.memberCipherDetailsApiService, |
||||
organizationId, |
||||
); |
||||
|
||||
await passwordHealthService.generateReport(); |
||||
|
||||
this.dataSource.data = passwordHealthService.reportCiphers; |
||||
|
||||
this.exposedPasswordMap = passwordHealthService.exposedPasswordMap; |
||||
this.passwordStrengthMap = passwordHealthService.passwordStrengthMap; |
||||
this.passwordUseMap = passwordHealthService.passwordUseMap; |
||||
this.totalMembersMap = passwordHealthService.totalMembersMap; |
||||
this.loading = false; |
||||
} |
||||
|
||||
markAppsAsCritical = async () => { |
||||
// TODO: Send to API once implemented
|
||||
return new Promise((resolve) => { |
||||
setTimeout(() => { |
||||
this.selectedIds.clear(); |
||||
this.toastService.showToast({ |
||||
variant: "success", |
||||
title: null, |
||||
message: this.i18nService.t("appsMarkedAsCritical"), |
||||
}); |
||||
resolve(true); |
||||
}, 1000); |
||||
}); |
||||
}; |
||||
|
||||
trackByFunction(_: number, item: CipherView) { |
||||
return item.id; |
||||
} |
||||
|
||||
onCheckboxChange(id: number, event: Event) { |
||||
const isChecked = (event.target as HTMLInputElement).checked; |
||||
if (isChecked) { |
||||
this.selectedIds.add(id); |
||||
} else { |
||||
this.selectedIds.delete(id); |
||||
} |
||||
} |
||||
} |
||||
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
<bit-container> |
||||
<p>{{ "passwordsReportDesc" | i18n }}</p> |
||||
<div *ngIf="loading"> |
||||
<i |
||||
class="bwi bwi-spinner bwi-spin tw-text-muted" |
||||
title="{{ 'loading' | i18n }}" |
||||
aria-hidden="true" |
||||
></i> |
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span> |
||||
</div> |
||||
<div class="tw-mt-4" *ngIf="!loading && dataSource.data.length"> |
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="53"> |
||||
<ng-container header> |
||||
<th bitCell></th> |
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "weakness" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "timesReused" | i18n }}</th> |
||||
<th bitCell class="tw-text-right">{{ "timesExposed" | i18n }}</th> |
||||
</ng-container> |
||||
<ng-template bitRowDef let-row> |
||||
<td bitCell> |
||||
<app-vault-icon [cipher]="row"></app-vault-icon> |
||||
</td> |
||||
<td bitCell> |
||||
<ng-container> |
||||
<span>{{ row.name }}</span> |
||||
</ng-container> |
||||
<br /> |
||||
<small>{{ row.subTitle }}</small> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span |
||||
bitBadge |
||||
*ngIf="row.weakPasswordDetail" |
||||
[variant]="row.weakPasswordDetail?.detailValue.badgeVariant" |
||||
> |
||||
{{ row.weakPasswordDetail?.detailValue.label | i18n }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span bitBadge *ngIf="passwordUseMap.has(row.login.password)" variant="warning"> |
||||
{{ "reusedXTimes" | i18n: passwordUseMap.get(row.login.password) }} |
||||
</span> |
||||
</td> |
||||
<td bitCell class="tw-text-right"> |
||||
<span bitBadge variant="warning" *ngIf="row.exposedPasswordDetail"> |
||||
{{ "exposedXTimes" | i18n: row.exposedPasswordDetail?.exposedXTimes }} |
||||
</span> |
||||
</td> |
||||
</ng-template> |
||||
</bit-table-scroll> |
||||
</div> |
||||
</bit-container> |
||||
@ -1,49 +0,0 @@
@@ -1,49 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing"; |
||||
import { ActivatedRoute, convertToParamMap } from "@angular/router"; |
||||
import { mock } from "jest-mock-extended"; |
||||
import { of } from "rxjs"; |
||||
|
||||
import { RiskInsightsReportService } from "@bitwarden/bit-common/dirt/reports/risk-insights"; |
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; |
||||
import { TableModule } from "@bitwarden/components"; |
||||
import { LooseComponentsModule } from "@bitwarden/web-vault/app/shared"; |
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; |
||||
|
||||
import { PasswordHealthComponent } from "./password-health.component"; |
||||
|
||||
describe("PasswordHealthComponent", () => { |
||||
let component: PasswordHealthComponent; |
||||
let fixture: ComponentFixture<PasswordHealthComponent>; |
||||
const activeRouteParams = convertToParamMap({ organizationId: "orgId" }); |
||||
|
||||
beforeEach(async () => { |
||||
await TestBed.configureTestingModule({ |
||||
imports: [PasswordHealthComponent, PipesModule, TableModule, LooseComponentsModule], |
||||
declarations: [], |
||||
providers: [ |
||||
{ provide: RiskInsightsReportService, useValue: mock<RiskInsightsReportService>() }, |
||||
{ provide: I18nService, useValue: mock<I18nService>() }, |
||||
{ |
||||
provide: ActivatedRoute, |
||||
useValue: { |
||||
paramMap: of(activeRouteParams), |
||||
url: of([]), |
||||
}, |
||||
}, |
||||
], |
||||
}).compileComponents(); |
||||
}); |
||||
|
||||
beforeEach(() => { |
||||
fixture = TestBed.createComponent(PasswordHealthComponent); |
||||
component = fixture.componentInstance; |
||||
|
||||
fixture.detectChanges(); |
||||
}); |
||||
|
||||
it("should initialize component", () => { |
||||
expect(component).toBeTruthy(); |
||||
}); |
||||
|
||||
it("should call generateReport on init", () => {}); |
||||
}); |
||||
@ -1,69 +0,0 @@
@@ -1,69 +0,0 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { CommonModule } from "@angular/common"; |
||||
import { Component, DestroyRef, inject, OnInit } from "@angular/core"; |
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; |
||||
import { ActivatedRoute } from "@angular/router"; |
||||
import { firstValueFrom, map } from "rxjs"; |
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module"; |
||||
import { RiskInsightsReportService } from "@bitwarden/bit-common/dirt/reports/risk-insights"; |
||||
import { CipherHealthReportDetail } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health"; |
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; |
||||
import { |
||||
BadgeModule, |
||||
ContainerComponent, |
||||
TableDataSource, |
||||
TableModule, |
||||
} from "@bitwarden/components"; |
||||
import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.module"; |
||||
import { OrganizationBadgeModule } from "@bitwarden/web-vault/app/vault/individual-vault/organization-badge/organization-badge.module"; |
||||
import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; |
||||
|
||||
@Component({ |
||||
selector: "tools-password-health", |
||||
templateUrl: "password-health.component.html", |
||||
imports: [ |
||||
BadgeModule, |
||||
OrganizationBadgeModule, |
||||
CommonModule, |
||||
ContainerComponent, |
||||
PipesModule, |
||||
JslibModule, |
||||
HeaderModule, |
||||
TableModule, |
||||
], |
||||
}) |
||||
export class PasswordHealthComponent implements OnInit { |
||||
passwordUseMap = new Map<string, number>(); |
||||
dataSource = new TableDataSource<CipherHealthReportDetail>(); |
||||
|
||||
loading = true; |
||||
|
||||
private destroyRef = inject(DestroyRef); |
||||
|
||||
constructor( |
||||
protected riskInsightsReportService: RiskInsightsReportService, |
||||
protected i18nService: I18nService, |
||||
protected activatedRoute: ActivatedRoute, |
||||
) {} |
||||
|
||||
ngOnInit() { |
||||
this.activatedRoute.paramMap |
||||
.pipe( |
||||
takeUntilDestroyed(this.destroyRef), |
||||
map(async (params) => { |
||||
const organizationId = params.get("organizationId"); |
||||
await this.setCiphers(organizationId); |
||||
}), |
||||
) |
||||
.subscribe(); |
||||
} |
||||
|
||||
async setCiphers(organizationId: string) { |
||||
this.dataSource.data = await firstValueFrom( |
||||
this.riskInsightsReportService.generateRawDataReport$(organizationId), |
||||
); |
||||
this.loading = false; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue