1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-31 00:33:33 +00:00

Merge branch 'main' into PM-29919-Add-dropdown-to-select-email-verification-and-emails-field-to-Send-when-creating-or-editing-a-Send

This commit is contained in:
bmbitwarden
2026-01-14 08:24:31 -05:00
committed by GitHub
10 changed files with 147 additions and 70 deletions

View File

@@ -1,5 +1,3 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { CommonModule } from "@angular/common";
import { Component, EventEmitter, Input, Output, ChangeDetectionStrategy } from "@angular/core";
@@ -33,13 +31,10 @@ export class Fido2CipherRowComponent {
@Output() onSelected = new EventEmitter<CipherView>();
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() cipher: CipherView;
@Input({ required: true }) cipher!: CipherView;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() last: boolean;
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input() title: string;
@Input({ required: true }) title!: string;
protected selectCipher(c: CipherView) {
this.onSelected.emit(c);

View File

@@ -1,17 +1,17 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, ChangeDetectionStrategy } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { ReactiveFormsModule } from "@angular/forms";
import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BreachAccountResponse } from "@bitwarden/common/dirt/models/response/breach-account.response";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { mockAccountInfoWith } from "@bitwarden/common/spec";
import { UserId } from "@bitwarden/common/types/guid";
import { AsyncActionsModule, ButtonModule, FormFieldModule } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { BreachReportComponent } from "./breach-report.component";
@@ -32,6 +32,21 @@ const breachedAccounts = [
}),
];
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-header",
template: "<div></div>",
standalone: false,
})
class MockHeaderComponent {}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "bit-container",
template: "<div></div>",
standalone: false,
})
class MockBitContainerComponent {}
describe("BreachReportComponent", () => {
let component: BreachReportComponent;
let fixture: ComponentFixture<BreachReportComponent>;
@@ -51,8 +66,8 @@ describe("BreachReportComponent", () => {
accountService.activeAccount$ = activeAccountSubject;
await TestBed.configureTestingModule({
declarations: [BreachReportComponent, I18nPipe],
imports: [ReactiveFormsModule],
declarations: [BreachReportComponent, MockHeaderComponent, MockBitContainerComponent],
imports: [ReactiveFormsModule, I18nPipe, AsyncActionsModule, ButtonModule, FormFieldModule],
providers: [
{
provide: AuditService,
@@ -67,9 +82,7 @@ describe("BreachReportComponent", () => {
useValue: mock<I18nService>(),
},
],
// FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports
errorOnUnknownElements: false,
errorOnUnknownProperties: false,
schemas: [],
}).compileComponents();
});

View File

@@ -1,8 +1,8 @@
import { Component, ChangeDetectionStrategy } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { mock, MockProxy } from "jest-mock-extended";
import { of } from "rxjs";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
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";
@@ -12,7 +12,13 @@ import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/sp
import { UserId } 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 { DialogService } from "@bitwarden/components";
import {
DialogService,
AsyncActionsModule,
ButtonModule,
FormFieldModule,
} from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
@@ -20,6 +26,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se
import { ExposedPasswordsReportComponent } from "./exposed-passwords-report.component";
import { cipherData } from "./reports-ciphers.mock";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-header",
template: "<div></div>",
standalone: false,
})
class MockHeaderComponent {}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "bit-container",
template: "<div></div>",
standalone: false,
})
class MockBitContainerComponent {}
describe("ExposedPasswordsReportComponent", () => {
let component: ExposedPasswordsReportComponent;
let fixture: ComponentFixture<ExposedPasswordsReportComponent>;
@@ -30,16 +52,19 @@ describe("ExposedPasswordsReportComponent", () => {
const userId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(userId);
beforeEach(() => {
beforeEach(async () => {
let cipherFormConfigServiceMock: MockProxy<CipherFormConfigService>;
syncServiceMock = mock<SyncService>();
auditService = mock<AuditService>();
organizationService = mock<OrganizationService>();
organizationService.organizations$.mockReturnValue(of([]));
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.configureTestingModule({
declarations: [ExposedPasswordsReportComponent, I18nPipe],
await TestBed.configureTestingModule({
declarations: [
ExposedPasswordsReportComponent,
MockHeaderComponent,
MockBitContainerComponent,
],
imports: [I18nPipe, AsyncActionsModule, ButtonModule, FormFieldModule],
providers: [
{
provide: CipherService,
@@ -83,9 +108,6 @@ describe("ExposedPasswordsReportComponent", () => {
},
],
schemas: [],
// FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports
errorOnUnknownElements: false,
errorOnUnknownProperties: false,
}).compileComponents();
});

View File

@@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from "@angular/core/testing";
import { MockProxy, mock } from "jest-mock-extended";
import { of } from "rxjs";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
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";
@@ -14,6 +13,7 @@ import { UserId } 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 { DialogService } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
@@ -37,7 +37,8 @@ describe("InactiveTwoFactorReportComponent", () => {
syncServiceMock = mock<SyncService>();
await TestBed.configureTestingModule({
declarations: [InactiveTwoFactorReportComponent, I18nPipe],
declarations: [InactiveTwoFactorReportComponent],
imports: [I18nPipe],
providers: [
{
provide: CipherService,

View File

@@ -1,8 +1,8 @@
import { ChangeDetectionStrategy, Component } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { MockProxy, mock } from "jest-mock-extended";
import { of } from "rxjs";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
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";
@@ -12,6 +12,7 @@ import { UserId } 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 { DialogService } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
@@ -19,6 +20,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se
import { cipherData } from "./reports-ciphers.mock";
import { ReusedPasswordsReportComponent } from "./reused-passwords-report.component";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-header",
template: "<div></div>",
standalone: false,
})
class MockHeaderComponent {}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "bit-container",
template: "<div></div>",
standalone: false,
})
class MockBitContainerComponent {}
describe("ReusedPasswordsReportComponent", () => {
let component: ReusedPasswordsReportComponent;
let fixture: ComponentFixture<ReusedPasswordsReportComponent>;
@@ -28,15 +45,18 @@ describe("ReusedPasswordsReportComponent", () => {
const userId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(userId);
beforeEach(() => {
beforeEach(async () => {
let cipherFormConfigServiceMock: MockProxy<CipherFormConfigService>;
organizationService = mock<OrganizationService>();
organizationService.organizations$.mockReturnValue(of([]));
syncServiceMock = mock<SyncService>();
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.configureTestingModule({
declarations: [ReusedPasswordsReportComponent, I18nPipe],
await TestBed.configureTestingModule({
declarations: [
ReusedPasswordsReportComponent,
MockHeaderComponent,
MockBitContainerComponent,
],
imports: [I18nPipe],
providers: [
{
provide: CipherService,
@@ -76,8 +96,6 @@ describe("ReusedPasswordsReportComponent", () => {
},
],
schemas: [],
// FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports
errorOnUnknownElements: false,
}).compileComponents();
});

View File

@@ -1,9 +1,9 @@
import { ChangeDetectionStrategy, Component } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { MockProxy, mock } from "jest-mock-extended";
import { of } from "rxjs";
import { CollectionService } from "@bitwarden/admin-console/common";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
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";
@@ -13,6 +13,7 @@ import { UserId } 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 { DialogService } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
@@ -20,6 +21,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se
import { cipherData } from "./reports-ciphers.mock";
import { UnsecuredWebsitesReportComponent } from "./unsecured-websites-report.component";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-header",
template: "<div></div>",
standalone: false,
})
class MockHeaderComponent {}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "bit-container",
template: "<div></div>",
standalone: false,
})
class MockBitContainerComponent {}
describe("UnsecuredWebsitesReportComponent", () => {
let component: UnsecuredWebsitesReportComponent;
let fixture: ComponentFixture<UnsecuredWebsitesReportComponent>;
@@ -30,7 +47,7 @@ describe("UnsecuredWebsitesReportComponent", () => {
const userId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(userId);
beforeEach(() => {
beforeEach(async () => {
let cipherFormConfigServiceMock: MockProxy<CipherFormConfigService>;
organizationService = mock<OrganizationService>();
organizationService.organizations$.mockReturnValue(of([]));
@@ -38,10 +55,13 @@ describe("UnsecuredWebsitesReportComponent", () => {
collectionService = mock<CollectionService>();
adminConsoleCipherFormConfigService = mock<AdminConsoleCipherFormConfigService>();
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.configureTestingModule({
declarations: [UnsecuredWebsitesReportComponent, I18nPipe],
await TestBed.configureTestingModule({
declarations: [
UnsecuredWebsitesReportComponent,
MockHeaderComponent,
MockBitContainerComponent,
],
imports: [I18nPipe],
providers: [
{
provide: CipherService,
@@ -85,8 +105,6 @@ describe("UnsecuredWebsitesReportComponent", () => {
},
],
schemas: [],
// FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports
errorOnUnknownElements: false,
}).compileComponents();
});

View File

@@ -1,8 +1,8 @@
import { ChangeDetectionStrategy, Component } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { mock, MockProxy } from "jest-mock-extended";
import { of } from "rxjs";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
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";
@@ -13,6 +13,7 @@ import { UserId } 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 { DialogService } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/services/admin-console-cipher-form-config.service";
@@ -20,6 +21,22 @@ import { AdminConsoleCipherFormConfigService } from "../../../vault/org-vault/se
import { cipherData } from "./reports-ciphers.mock";
import { WeakPasswordsReportComponent } from "./weak-passwords-report.component";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-header",
template: "<div></div>",
standalone: false,
})
class MockHeaderComponent {}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "bit-container",
template: "<div></div>",
standalone: false,
})
class MockBitContainerComponent {}
describe("WeakPasswordsReportComponent", () => {
let component: WeakPasswordsReportComponent;
let fixture: ComponentFixture<WeakPasswordsReportComponent>;
@@ -30,16 +47,16 @@ describe("WeakPasswordsReportComponent", () => {
const userId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(userId);
beforeEach(() => {
beforeEach(async () => {
let cipherFormConfigServiceMock: MockProxy<CipherFormConfigService>;
syncServiceMock = mock<SyncService>();
passwordStrengthService = mock<PasswordStrengthServiceAbstraction>();
organizationService = mock<OrganizationService>();
organizationService.organizations$.mockReturnValue(of([]));
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.configureTestingModule({
declarations: [WeakPasswordsReportComponent, I18nPipe],
await TestBed.configureTestingModule({
declarations: [WeakPasswordsReportComponent, MockHeaderComponent, MockBitContainerComponent],
imports: [I18nPipe],
providers: [
{
provide: CipherService,
@@ -84,8 +101,6 @@ describe("WeakPasswordsReportComponent", () => {
},
],
schemas: [],
// FIXME(PM-18598): Replace unknownElements and unknownProperties with actual imports
errorOnUnknownElements: false,
}).compileComponents();
});

View File

@@ -106,15 +106,17 @@
></button>
}
}
<button
bitIconButton="bwi-trash"
type="button"
buttonType="danger"
[label]="'delete' | i18n"
[bitAction]="delete"
[disabled]="!canDelete"
data-testid="delete-cipher-btn"
></button>
@if (cipher) {
<button
bitIconButton="bwi-trash"
type="button"
buttonType="danger"
[label]="'delete' | i18n"
[bitAction]="delete"
[disabled]="!canDelete"
data-testid="delete-cipher-btn"
></button>
}
</div>
}
</ng-container>

View File

@@ -121,13 +121,13 @@ export class CollectionAdminView extends CollectionView {
try {
view.name = await encryptService.decryptString(new EncString(view.name), orgKey);
} catch (e) {
view.name = "[error: cannot decrypt]";
// Note: This should be replaced by the owning team with appropriate, domain-specific behavior.
// eslint-disable-next-line no-console
console.error(
"[CollectionAdminView/fromCollectionAccessDetails] Error decrypting collection name",
e,
);
throw e;
}
view.assigned = collection.assigned;
view.readOnly = collection.readOnly;

View File

@@ -126,14 +126,7 @@ export class CollectionView implements View, ITreeNodeObject {
): Promise<CollectionView> {
const view = new CollectionView({ ...collection, name: "" });
try {
view.name = await encryptService.decryptString(collection.name, key);
} catch (e) {
view.name = "[error: cannot decrypt]";
// eslint-disable-next-line no-console
console.error("[CollectionView] Error decrypting collection name", e);
}
view.name = await encryptService.decryptString(collection.name, key);
view.assigned = true;
view.externalId = collection.externalId;
view.readOnly = collection.readOnly;
@@ -154,10 +147,10 @@ export class CollectionView implements View, ITreeNodeObject {
try {
view.name = await encryptService.decryptString(new EncString(collection.name), orgKey);
} catch (e) {
view.name = "[error: cannot decrypt]";
// Note: This should be replaced by the owning team with appropriate, domain-specific behavior.
// eslint-disable-next-line no-console
console.error("[CollectionView] Error decrypting collection name", e);
throw e;
}
view.externalId = collection.externalId;