1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 08:43:33 +00:00

[PM-22134] Migrate list views to CipherListView from the SDK (#15174)

* add `CipherViewLike` and utilities to handle `CipherView` and `CipherViewLike`

* migrate libs needed for web vault to support `CipherViewLike`

* migrate web vault components to support

* add  for CipherView.  will have to be later

* fetch full CipherView for copying a password

* have only the cipher service utilize SDK migration flag

- This keeps feature flag logic away from the component
- Also cuts down on what is needed for other platforms

* strongly type CipherView for AC vault

- Probably temporary before migration of the AC vault to `CipherListView` SDK

* fix build icon tests by being more gracious with the uri structure

* migrate desktop components to CipherListViews$

* consume card from sdk

* add browser implementation for `CipherListView`

* update copy message for single copiable items

* refactor `getCipherViewLikeLogin` to `getLogin`

* refactor `getCipherViewLikeCard` to `getCard`

* add `hasFido2Credentials` helper

* add decryption failure to cipher like utils

* add todo with ticket

* fix decryption failure typing

* fix copy card messages

* fix addition of organizations and collections for `PopupCipherViewLike`

- accessors were being lost

* refactor to getters to fix re-rendering bug

* fix decryption failure helper

* fix sorting functions for `CipherViewLike`

* formatting

* add `CipherViewLikeUtils` tests

* refactor "copiable" to "copyable" to match SDK

* use `hasOldAttachments` from cipherlistview

* fix typing

* update SDK version

* add feature flag for cipher list view work

* use `CipherViewLikeUtils` for copyable values rather than referring to the cipher directly

* update restricted item type to support CipherViewLike

* add cipher support to `CipherViewLikeUtils`

* update `isCipherListView` check

* refactor CipherLike to a separate type

* refactor `getFullCipherView` into the cipher service

* add optional chaining for `uriChecksum`

* set empty array for decrypted CipherListView

* migrate nudge service to use `cipherListViews`

* update web vault to not depend on `cipherViews$`

* update popup list filters to use `CipherListView`

* fix storybook

* fix tests

* accept undefined as a MY VAULT filter value for cipher list views

* use `LoginUriView` for uri logic (#15530)

* filter out null ciphers from the `_allDecryptedCiphers$` (#15539)

* use `launchUri` to avoid any unexpected behavior in URIs - this appends `http://` when missing
This commit is contained in:
Nick Krantz
2025-07-17 14:55:32 -05:00
committed by GitHub
parent 00b6b0224e
commit b4120e0e3f
54 changed files with 1907 additions and 514 deletions

View File

@@ -6,7 +6,10 @@ import { CollectionView } from "@bitwarden/admin-console/common";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import {
CipherViewLike,
CipherViewLikeUtils,
} from "@bitwarden/common/vault/utils/cipher-view-like-utils";
import {
convertToPermission,
@@ -20,11 +23,11 @@ import { RowHeightClass } from "./vault-items.component";
templateUrl: "vault-cipher-row.component.html",
standalone: false,
})
export class VaultCipherRowComponent implements OnInit {
export class VaultCipherRowComponent<C extends CipherViewLike> implements OnInit {
protected RowHeightClass = RowHeightClass;
@Input() disabled: boolean;
@Input() cipher: CipherView;
@Input() cipher: C;
@Input() showOwner: boolean;
@Input() showCollections: boolean;
@Input() showGroups: boolean;
@@ -46,7 +49,7 @@ export class VaultCipherRowComponent implements OnInit {
*/
@Input() canRestoreCipher: boolean;
@Output() onEvent = new EventEmitter<VaultItemEvent>();
@Output() onEvent = new EventEmitter<VaultItemEvent<C>>();
@Input() checked: boolean;
@Output() checkedToggled = new EventEmitter<void>();
@@ -74,33 +77,63 @@ export class VaultCipherRowComponent implements OnInit {
}
protected get clickAction() {
if (this.cipher.decryptionFailure) {
if (this.decryptionFailure) {
return "showFailedToDecrypt";
}
return "view";
}
protected get showTotpCopyButton() {
return (
(this.cipher.login?.hasTotp ?? false) &&
(this.cipher.organizationUseTotp || this.showPremiumFeatures)
);
const login = CipherViewLikeUtils.getLogin(this.cipher);
const hasTotp = login?.totp ?? false;
return hasTotp && (this.cipher.organizationUseTotp || this.showPremiumFeatures);
}
protected get showFixOldAttachments() {
return this.cipher.hasOldAttachments && this.cipher.organizationId == null;
}
protected get hasAttachments() {
return CipherViewLikeUtils.hasAttachments(this.cipher);
}
protected get showAttachments() {
return this.canEditCipher || this.cipher.attachments?.length > 0;
return this.canEditCipher || this.hasAttachments;
}
protected get canLaunch() {
return CipherViewLikeUtils.canLaunch(this.cipher);
}
protected get launchUri() {
return CipherViewLikeUtils.getLaunchUri(this.cipher);
}
protected get subtitle() {
return CipherViewLikeUtils.subtitle(this.cipher);
}
protected get isDeleted() {
return CipherViewLikeUtils.isDeleted(this.cipher);
}
protected get decryptionFailure() {
return CipherViewLikeUtils.decryptionFailure(this.cipher);
}
protected get showAssignToCollections() {
return this.organizations?.length && this.canAssignCollections && !this.cipher.isDeleted;
return (
this.organizations?.length &&
this.canAssignCollections &&
!CipherViewLikeUtils.isDeleted(this.cipher)
);
}
protected get showClone() {
return this.cloneable && !this.cipher.isDeleted;
return this.cloneable && !CipherViewLikeUtils.isDeleted(this.cipher);
}
protected get showEventLogs() {
@@ -108,7 +141,18 @@ export class VaultCipherRowComponent implements OnInit {
}
protected get isNotDeletedLoginCipher() {
return this.cipher.type === this.CipherType.Login && !this.cipher.isDeleted;
return (
CipherViewLikeUtils.getType(this.cipher) === this.CipherType.Login &&
!CipherViewLikeUtils.isDeleted(this.cipher)
);
}
protected get hasPasswordToCopy() {
return CipherViewLikeUtils.hasCopyableValue(this.cipher, "password");
}
protected get hasUsernameToCopy() {
return CipherViewLikeUtils.hasCopyableValue(this.cipher, "username");
}
protected get permissionText() {
@@ -154,7 +198,7 @@ export class VaultCipherRowComponent implements OnInit {
}
protected get showLaunchUri(): boolean {
return this.isNotDeletedLoginCipher && this.cipher.login.canLaunch;
return this.isNotDeletedLoginCipher && this.canLaunch;
}
protected get disableMenu() {
@@ -166,7 +210,7 @@ export class VaultCipherRowComponent implements OnInit {
this.showAttachments ||
this.showClone ||
this.canEditCipher ||
(this.cipher.isDeleted && this.canRestoreCipher)
(CipherViewLikeUtils.isDeleted(this.cipher) && this.canRestoreCipher)
);
}