mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
[PM-21644] Cannot retrieve attachment from bw serve (#14806)
* Modified saveAttachmenttofIle to implement callback attachment content decryption * renamed parameter
This commit is contained in:
@@ -2,8 +2,6 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
import { EncryptService } from "@bitwarden/common/key-management/crypto/abstractions/encrypt.service";
|
||||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
|
||||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
|
||||||
|
|
||||||
import { Response } from "../models/response";
|
import { Response } from "../models/response";
|
||||||
import { FileResponse } from "../models/response/file.response";
|
import { FileResponse } from "../models/response/file.response";
|
||||||
@@ -25,15 +23,15 @@ export abstract class DownloadCommand {
|
|||||||
/**
|
/**
|
||||||
* Fetches an attachment via the url, decrypts it's content and saves it to a file
|
* Fetches an attachment via the url, decrypts it's content and saves it to a file
|
||||||
* @param url - url used to retrieve the attachment
|
* @param url - url used to retrieve the attachment
|
||||||
* @param key - SymmetricCryptoKey to decrypt the file contents
|
|
||||||
* @param fileName - filename used when written to disk
|
* @param fileName - filename used when written to disk
|
||||||
|
* @param decrypt - Function used to decrypt the response
|
||||||
* @param output - If output is empty or `--raw` was passed to the initial command the content is output onto stdout
|
* @param output - If output is empty or `--raw` was passed to the initial command the content is output onto stdout
|
||||||
* @returns Promise<FileResponse>
|
* @returns Promise<FileResponse>
|
||||||
*/
|
*/
|
||||||
protected async saveAttachmentToFile(
|
protected async saveAttachmentToFile(
|
||||||
url: string,
|
url: string,
|
||||||
key: SymmetricCryptoKey,
|
|
||||||
fileName: string,
|
fileName: string,
|
||||||
|
decrypt: (resp: globalThis.Response) => Promise<Uint8Array>,
|
||||||
output?: string,
|
output?: string,
|
||||||
) {
|
) {
|
||||||
const response = await this.apiService.nativeFetch(
|
const response = await this.apiService.nativeFetch(
|
||||||
@@ -46,8 +44,7 @@ export abstract class DownloadCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
const decBuf = await decrypt(response);
|
||||||
const decBuf = await this.encryptService.decryptFileData(encBuf, key);
|
|
||||||
if (process.env.BW_SERVE === "true") {
|
if (process.env.BW_SERVE === "true") {
|
||||||
const res = new FileResponse(Buffer.from(decBuf), fileName);
|
const res = new FileResponse(Buffer.from(decBuf), fileName);
|
||||||
return Response.success(res);
|
return Response.success(res);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { ErrorResponse } from "@bitwarden/common/models/response/error.response"
|
|||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
import { CipherId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||||
@@ -345,12 +345,11 @@ export class GetCommand extends DownloadCommand {
|
|||||||
return Response.multipleResults(attachments.map((a) => a.id));
|
return Response.multipleResults(attachments.map((a) => a.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
const account = await firstValueFrom(this.accountService.activeAccount$);
|
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||||
const canAccessPremium = await firstValueFrom(
|
const canAccessPremium = await firstValueFrom(
|
||||||
this.accountProfileService.hasPremiumFromAnySource$(account.id),
|
this.accountProfileService.hasPremiumFromAnySource$(activeUserId),
|
||||||
);
|
);
|
||||||
if (!canAccessPremium) {
|
if (!canAccessPremium) {
|
||||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
|
||||||
const originalCipher = await this.cipherService.get(cipher.id, activeUserId);
|
const originalCipher = await this.cipherService.get(cipher.id, activeUserId);
|
||||||
if (originalCipher == null || originalCipher.organizationId == null) {
|
if (originalCipher == null || originalCipher.organizationId == null) {
|
||||||
return Response.error("Premium status is required to use this feature.");
|
return Response.error("Premium status is required to use this feature.");
|
||||||
@@ -374,11 +373,20 @@ export class GetCommand extends DownloadCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const key =
|
const decryptBufferFn = (resp: globalThis.Response) =>
|
||||||
attachments[0].key != null
|
this.cipherService.getDecryptedAttachmentBuffer(
|
||||||
? attachments[0].key
|
cipher.id as CipherId,
|
||||||
: await this.keyService.getOrgKey(cipher.organizationId);
|
attachments[0],
|
||||||
return await this.saveAttachmentToFile(url, key, attachments[0].fileName, options.output);
|
resp,
|
||||||
|
activeUserId,
|
||||||
|
);
|
||||||
|
|
||||||
|
return await this.saveAttachmentToFile(
|
||||||
|
url,
|
||||||
|
attachments[0].fileName,
|
||||||
|
decryptBufferFn,
|
||||||
|
options.output,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getFolder(id: string) {
|
private async getFolder(id: string) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { ErrorResponse } from "@bitwarden/common/models/response/error.response"
|
|||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||||
import { SendAccess } from "@bitwarden/common/tools/send/models/domain/send-access";
|
import { SendAccess } from "@bitwarden/common/tools/send/models/domain/send-access";
|
||||||
@@ -98,10 +99,16 @@ export class SendReceiveCommand extends DownloadCommand {
|
|||||||
this.sendAccessRequest,
|
this.sendAccessRequest,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const decryptBufferFn = async (resp: globalThis.Response) => {
|
||||||
|
const encBuf = await EncArrayBuffer.fromResponse(resp);
|
||||||
|
return this.encryptService.decryptFileData(encBuf, this.decKey);
|
||||||
|
};
|
||||||
|
|
||||||
return await this.saveAttachmentToFile(
|
return await this.saveAttachmentToFile(
|
||||||
downloadData.url,
|
downloadData.url,
|
||||||
this.decKey,
|
|
||||||
response?.file?.fileName,
|
response?.file?.fileName,
|
||||||
|
decryptBufferFn,
|
||||||
options.output,
|
options.output,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user