1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[PM-20505] Weak-passwords-report: refresh rows after edit (#14401)

This commit is contained in:
Vijay Oommen
2025-05-01 08:03:32 -05:00
committed by GitHub
parent e6530ade01
commit e596584e87
3 changed files with 107 additions and 49 deletions

View File

@@ -67,7 +67,7 @@ export class CipherReportComponent implements OnDestroy {
protected i18nService: I18nService,
private syncService: SyncService,
private cipherFormConfigService: CipherFormConfigService,
private adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService,
protected adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService,
) {
this.organizations$ = this.accountService.activeAccount$.pipe(
getUserId,
@@ -207,7 +207,7 @@ export class CipherReportComponent implements OnDestroy {
// If the dialog was closed by deleting the cipher, refresh the report.
if (result === VaultItemDialogResult.Deleted || result === VaultItemDialogResult.Saved) {
await this.load();
await this.refresh(result, cipher);
}
}
@@ -215,6 +215,10 @@ export class CipherReportComponent implements OnDestroy {
this.allCiphers = [];
}
protected async refresh(result: VaultItemDialogResult, cipher: CipherView) {
await this.load();
}
protected async repromptCipher(c: CipherView) {
return (
c.reprompt === CipherRepromptType.None ||

View File

@@ -1,18 +1,22 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, OnInit } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { CipherId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { BadgeVariant, DialogService } from "@bitwarden/components";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
import { VaultItemDialogResult } from "@bitwarden/web-vault/app/vault/components/vault-item-dialog/vault-item-dialog.component";
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
@@ -40,7 +44,7 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
i18nService: I18nService,
syncService: SyncService,
cipherFormConfigService: CipherFormConfigService,
adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService,
protected adminConsoleCipherFormConfigService: AdminConsoleCipherFormConfigService,
) {
super(
cipherService,
@@ -66,8 +70,59 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
this.findWeakPasswords(allCiphers);
}
protected async refresh(result: VaultItemDialogResult, cipher: CipherView) {
if (result === VaultItemDialogResult.Deleted) {
// remove the cipher from the list
this.weakPasswordCiphers = this.weakPasswordCiphers.filter((c) => c.id !== cipher.id);
this.filterCiphersByOrg(this.weakPasswordCiphers);
return;
}
if (result == VaultItemDialogResult.Saved) {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
let updatedCipher = await this.cipherService.get(cipher.id, activeUserId);
if (this.isAdminConsoleActive) {
updatedCipher = await this.adminConsoleCipherFormConfigService.getCipher(
cipher.id as CipherId,
this.organization,
);
}
const updatedCipherView = await updatedCipher.decrypt(
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher, activeUserId),
);
// update the cipher views
const updatedReportResult = this.determineWeakPasswordScore(updatedCipherView);
const index = this.weakPasswordCiphers.findIndex((c) => c.id === updatedCipherView.id);
if (updatedReportResult == null) {
// the password is no longer weak
// remove the cipher from the list
this.weakPasswordCiphers.splice(index, 1);
this.filterCiphersByOrg(this.weakPasswordCiphers);
return;
}
if (index > -1) {
// update the existing cipher
this.weakPasswordCiphers[index] = updatedReportResult;
this.filterCiphersByOrg(this.weakPasswordCiphers);
}
}
}
protected findWeakPasswords(ciphers: CipherView[]): void {
ciphers.forEach((ciph) => {
const row = this.determineWeakPasswordScore(ciph);
if (row != null) {
this.weakPasswordCiphers.push(row);
}
});
this.filterCiphersByOrg(this.weakPasswordCiphers);
}
protected determineWeakPasswordScore(ciph: CipherView): ReportResult | null {
const { type, login, isDeleted, edit, viewPassword } = ciph;
if (
type !== CipherType.Login ||
@@ -110,16 +165,15 @@ export class WeakPasswordsReportComponent extends CipherReportComponent implemen
if (result.score != null && result.score <= 2) {
const scoreValue = this.scoreKey(result.score);
const row = {
return {
...ciph,
score: result.score,
reportValue: scoreValue,
scoreKey: scoreValue.sortOrder,
} as ReportResult;
this.weakPasswordCiphers.push(row);
}
});
this.filterCiphersByOrg(this.weakPasswordCiphers);
return null;
}
protected canManageCipher(c: CipherView): boolean {

View File

@@ -100,7 +100,7 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ
};
}
private async getCipher(id: CipherId | null, organization: Organization): Promise<Cipher | null> {
async getCipher(id: CipherId | null, organization: Organization): Promise<Cipher | null> {
if (id == null) {
return null;
}