mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 14:34:02 +00:00
display translated content for attachments that cannot be downloaded
This commit is contained in:
@@ -5858,6 +5858,9 @@
|
||||
"cardNumberLabel": {
|
||||
"message": "Card number"
|
||||
},
|
||||
"errorCannotDecrypt": {
|
||||
"message": "Error: Cannot decrypt"
|
||||
},
|
||||
"sessionTimeoutSettingsAction": {
|
||||
"message": "Timeout action"
|
||||
}
|
||||
|
||||
@@ -4235,6 +4235,9 @@
|
||||
"sessionTimeoutSettingsAction": {
|
||||
"message": "Timeout action"
|
||||
},
|
||||
"errorCannotDecrypt": {
|
||||
"message": "Error: Cannot decrypt"
|
||||
},
|
||||
"sessionTimeoutHeader": {
|
||||
"message": "Session timeout"
|
||||
}
|
||||
|
||||
@@ -12185,6 +12185,9 @@
|
||||
"confirmNoSelectedCriticalApplicationsDesc": {
|
||||
"message": "Are you sure you want to continue?"
|
||||
},
|
||||
"errorCannotDecrypt": {
|
||||
"message": "Error: Cannot decrypt"
|
||||
},
|
||||
"userVerificationFailed": {
|
||||
"message": "User verification failed."
|
||||
}
|
||||
|
||||
@@ -50,6 +50,12 @@ export class Attachment extends Domain {
|
||||
if (this.key != null) {
|
||||
view.key = await this.decryptAttachmentKey(orgId, encKey);
|
||||
view.encryptedKey = this.key; // Keep the encrypted key for the view
|
||||
|
||||
// When the attachment key couldn't be decrypted, mark a decryption error
|
||||
// The file won't be able to be downloaded in these cases
|
||||
if (!view.key) {
|
||||
view.hasDecryptionError = true;
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { AttachmentView as SdkAttachmentView } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { EncString } from "../../../key-management/crypto/models/enc-string";
|
||||
import { DECRYPT_ERROR, EncString } from "../../../key-management/crypto/models/enc-string";
|
||||
import { View } from "../../../models/view/view";
|
||||
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { Attachment } from "../domain/attachment";
|
||||
@@ -18,6 +18,7 @@ export class AttachmentView implements View {
|
||||
* The SDK returns an encrypted key for the attachment.
|
||||
*/
|
||||
encryptedKey: EncString | undefined;
|
||||
private _hasDecryptionError?: boolean;
|
||||
|
||||
constructor(a?: Attachment) {
|
||||
if (!a) {
|
||||
@@ -41,6 +42,14 @@ export class AttachmentView implements View {
|
||||
return 0;
|
||||
}
|
||||
|
||||
get hasDecryptionError(): boolean {
|
||||
return this._hasDecryptionError || this.fileName === DECRYPT_ERROR;
|
||||
}
|
||||
|
||||
set hasDecryptionError(value: boolean) {
|
||||
this._hasDecryptionError = value;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Partial<Jsonify<AttachmentView>>): AttachmentView {
|
||||
const key = obj.key == null ? null : SymmetricCryptoKey.fromJSON(obj.key);
|
||||
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
<li *ngFor="let attachment of cipher.attachments">
|
||||
<bit-item>
|
||||
<bit-item-content>
|
||||
<span data-testid="file-name" [title]="attachment.fileName">{{ attachment.fileName }}</span>
|
||||
<span slot="secondary" data-testid="file-size">{{ attachment.sizeName }}</span>
|
||||
<span data-testid="file-name" [title]="getAttachmentFileName(attachment)">
|
||||
{{ getAttachmentFileName(attachment) }}
|
||||
</span>
|
||||
@if (!attachment.hasDecryptionError) {
|
||||
<span slot="secondary" data-testid="file-size">{{ attachment.sizeName }}</span>
|
||||
}
|
||||
</bit-item-content>
|
||||
<ng-container slot="end">
|
||||
<bit-item-action>
|
||||
|
||||
@@ -154,8 +154,8 @@ describe("CipherAttachmentsComponent", () => {
|
||||
const fileName = fixture.debugElement.query(By.css('[data-testid="file-name"]'));
|
||||
const fileSize = fixture.debugElement.query(By.css('[data-testid="file-size"]'));
|
||||
|
||||
expect(fileName.nativeElement.textContent).toEqual(attachment.fileName);
|
||||
expect(fileSize.nativeElement.textContent).toEqual(attachment.sizeName);
|
||||
expect(fileName.nativeElement.textContent.trim()).toEqual(attachment.fileName);
|
||||
expect(fileSize.nativeElement.textContent.trim()).toEqual(attachment.sizeName);
|
||||
});
|
||||
|
||||
describe("bitSubmit", () => {
|
||||
|
||||
@@ -204,6 +204,14 @@ export class CipherAttachmentsComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
}
|
||||
|
||||
getAttachmentFileName(attachment: AttachmentView): string {
|
||||
if (attachment.hasDecryptionError) {
|
||||
return this.i18nService.t("errorCannotDecrypt");
|
||||
}
|
||||
|
||||
return attachment.fileName ?? "";
|
||||
}
|
||||
|
||||
/** Save the attachments to the cipher */
|
||||
submit = async () => {
|
||||
this.onUploadStarted.emit();
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
<bit-item-group>
|
||||
<bit-item *ngFor="let attachment of cipher.attachments">
|
||||
<bit-item-content>
|
||||
<span data-testid="file-name" [title]="attachment.fileName">{{ attachment.fileName }}</span>
|
||||
<span slot="secondary" data-testid="file-size">{{ attachment.sizeName }}</span>
|
||||
<span data-testid="file-name" [title]="getAttachmentFileName(attachment)">
|
||||
{{ getAttachmentFileName(attachment) }}
|
||||
</span>
|
||||
@if (!attachment.hasDecryptionError) {
|
||||
<span slot="secondary" data-testid="file-size">{{ attachment.sizeName }}</span>
|
||||
}
|
||||
</bit-item-content>
|
||||
<ng-container slot="end">
|
||||
<bit-item-action>
|
||||
|
||||
@@ -8,9 +8,11 @@ import { NEVER, switchMap } from "rxjs";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { EmergencyAccessId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { OrgKey } from "@bitwarden/common/types/key";
|
||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import {
|
||||
ItemModule,
|
||||
@@ -59,6 +61,7 @@ export class AttachmentsV2ViewComponent {
|
||||
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
private stateProvider: StateProvider,
|
||||
private accountService: AccountService,
|
||||
private i18nService: I18nService,
|
||||
) {
|
||||
this.subscribeToHasPremiumCheck();
|
||||
this.subscribeToOrgKey();
|
||||
@@ -89,4 +92,12 @@ export class AttachmentsV2ViewComponent {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getAttachmentFileName(attachment: AttachmentView): string {
|
||||
if (attachment.hasDecryptionError) {
|
||||
return this.i18nService.t("errorCannotDecrypt");
|
||||
}
|
||||
|
||||
return attachment.fileName ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,12 +36,11 @@ describe("DownloadAttachmentComponent", () => {
|
||||
.mockResolvedValue({ url: "https://www.downloadattachement.com" });
|
||||
const download = jest.fn();
|
||||
|
||||
const attachment = {
|
||||
id: "222-3333-4444",
|
||||
url: "https://www.attachment.com",
|
||||
fileName: "attachment-filename",
|
||||
size: "1234",
|
||||
} as AttachmentView;
|
||||
const attachment = new AttachmentView();
|
||||
attachment.id = "222-3333-4444";
|
||||
attachment.url = "https://www.attachment.com";
|
||||
attachment.fileName = "attachment-filename";
|
||||
attachment.size = "1234";
|
||||
|
||||
const cipherView = {
|
||||
id: "5555-444-3333",
|
||||
|
||||
@@ -6,7 +6,6 @@ import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { DECRYPT_ERROR } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -60,7 +59,7 @@ export class DownloadAttachmentComponent {
|
||||
) {}
|
||||
|
||||
protected get isDecryptionFailure(): boolean {
|
||||
return this.attachment.fileName === DECRYPT_ERROR;
|
||||
return this.attachment.hasDecryptionError;
|
||||
}
|
||||
|
||||
/** Download the attachment */
|
||||
|
||||
Reference in New Issue
Block a user