added some test for DecryptingAttachmentManager

pull/2242/head
Audric Ackermann 3 years ago
parent b76797d264
commit e5c54cc45e
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -12,11 +12,11 @@ import { makeObjectUrl, urlToBlob } from '../../types/attachments/VisualAttachme
import { getAttachmentPath } from '../../types/MessageAttachment';
import { decryptAttachmentBufferRenderer } from '../../util/local_attachments_encrypter';
const urlToDecryptedBlobMap = new Map<
export const urlToDecryptedBlobMap = new Map<
string,
{ decrypted: string; lastAccessTimestamp: number; forceRetain: boolean }
>();
const urlToDecryptingPromise = new Map<string, Promise<string>>();
export const urlToDecryptingPromise = new Map<string, Promise<string>>();
export const cleanUpOldDecryptedMedias = () => {
const currentTimestamp = Date.now();
@ -47,6 +47,14 @@ export const cleanUpOldDecryptedMedias = () => {
);
};
export const getLocalAttachmentPath = () => {
return getAttachmentPath();
};
export const readFileContent = async (url: string) => {
return fse.readFile(url);
};
export const getDecryptedMediaUrl = async (
url: string,
contentType: string,
@ -57,7 +65,7 @@ export const getDecryptedMediaUrl = async (
}
if (url.startsWith('blob:')) {
return url;
} else if (getAttachmentPath() && url.startsWith(getAttachmentPath())) {
} else if (exports.getLocalAttachmentPath && url.startsWith(exports.getLocalAttachmentPath())) {
// this is a file encoded by session on our current attachments path.
// we consider the file is encrypted.
// if it's not, the hook caller has to fallback to setting the img src as an url to the file instead and load it
@ -84,7 +92,7 @@ export const getDecryptedMediaUrl = async (
new Promise(async resolve => {
window.log.info('about to read and decrypt file :', url);
try {
const encryptedFileContent = await fse.readFile(url);
const encryptedFileContent = await readFileContent(url);
const decryptedContent = await decryptAttachmentBufferRenderer(
encryptedFileContent.buffer
);
@ -137,7 +145,7 @@ export const getAlreadyDecryptedMediaUrl = (url: string): string | null => {
}
if (url.startsWith('blob:')) {
return url;
} else if (getAttachmentPath() && url.startsWith(getAttachmentPath())) {
} else if (exports.getLocalAttachmentPath() && url.startsWith(exports.getLocalAttachmentPath())) {
if (urlToDecryptedBlobMap.has(url)) {
const existingObjUrl = urlToDecryptedBlobMap.get(url)?.decrypted as string;
return existingObjUrl;
@ -150,3 +158,11 @@ export const getDecryptedBlob = async (url: string, contentType: string): Promis
const decryptedUrl = await getDecryptedMediaUrl(url, contentType, false);
return urlToBlob(decryptedUrl);
};
/**
* This function should only be used for testing purpose
*/
export const resetDecryptedUrlForTesting = () => {
urlToDecryptedBlobMap.clear();
urlToDecryptingPromise.clear();
};

@ -0,0 +1,140 @@
import { expect } from 'chai';
import { beforeEach } from 'mocha';
import Sinon from 'sinon';
import * as DecryptedAttachmentsManager from '../../../../session/crypto/DecryptedAttachmentsManager';
import { TestUtils } from '../../../test-utils';
describe('DecryptedAttachmentsManager', () => {
// tslint:disable-next-line: no-empty
beforeEach(() => {
DecryptedAttachmentsManager.resetDecryptedUrlForTesting();
TestUtils.stubWindowLog();
Sinon.stub(DecryptedAttachmentsManager, 'getLocalAttachmentPath').returns('/local/attachment');
});
afterEach(() => {
Sinon.restore();
});
describe('getAlreadyDecryptedMediaUrl', () => {
describe('invalid url', () => {
it('url is null', () => {
expect(DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl(null as any)).to.be.null;
});
it('url is undefined', () => {
expect(DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl(undefined as any)).to.be
.null;
});
it('url is empty string', () => {
expect(DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl('')).to.be.null;
});
it('url starts with something not being the attachment path', () => {
expect(DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl('/local/notvalid')).to.be
.null;
});
});
it('url starts with "blob:" => returns the already decrypted url right away', () => {
expect(DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl('blob:whatever')).to.be.eq(
'blob:whatever'
);
});
describe('url starts with attachmentPath', () => {
let readFileContent: Sinon.SinonStub;
let getItemById: Sinon.SinonStub;
let decryptAttachmentBufferNode: Sinon.SinonStub;
beforeEach(() => {
readFileContent = Sinon.stub(DecryptedAttachmentsManager, 'readFileContent').resolves(
Buffer.from(new String('this is a test'))
);
getItemById = TestUtils.stubDataItem('getItemById')
.withArgs('local_attachment_encrypted_key')
.callsFake(async () => {
return { value: 'dfdf' };
});
decryptAttachmentBufferNode = TestUtils.stubUtilWorker(
'decryptAttachmentBufferNode',
new Uint8Array(5)
);
TestUtils.stubCreateObjectUrl();
});
it('url starts with attachment path but is not already decrypted', () => {
expect(
DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl('/local/attachment/attachment1')
).to.be.eq(null);
});
it('url starts with attachment path but is not already decrypted', async () => {
expect(
DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl('/local/attachment/attachment1')
).to.be.eq(null);
expect(readFileContent.callCount).to.be.eq(0);
expect(decryptAttachmentBufferNode.callCount).to.be.eq(0);
expect(getItemById.callCount).to.be.eq(0);
const resolved = await DecryptedAttachmentsManager.getDecryptedMediaUrl(
'/local/attachment/attachment1',
'image/jpeg',
false
);
expect(readFileContent.callCount).to.be.eq(1);
expect(decryptAttachmentBufferNode.callCount).to.be.eq(1);
expect(getItemById.callCount).to.be.eq(1);
const now = `${Date.now()}`;
expect(resolved).to.be.not.empty;
expect(resolved.startsWith(now.slice(0, 9))).to.be.true;
});
it('url starts with attachment path and is already decrypted', async () => {
expect(
DecryptedAttachmentsManager.getAlreadyDecryptedMediaUrl('/local/attachment/attachment1')
).to.be.eq(null);
expect(readFileContent.callCount).to.be.eq(0);
expect(decryptAttachmentBufferNode.callCount).to.be.eq(0);
expect(getItemById.callCount).to.be.eq(0);
const resolved = await DecryptedAttachmentsManager.getDecryptedMediaUrl(
'/local/attachment/attachment1',
'image/jpeg',
false
);
expect(readFileContent.callCount).to.be.eq(1);
expect(decryptAttachmentBufferNode.callCount).to.be.eq(1);
expect(getItemById.callCount).to.be.eq(1);
const now = `${Date.now()}`;
expect(resolved).to.be.not.empty;
expect(resolved.startsWith(now.slice(0, 9))).to.be.true;
const resolved2 = await DecryptedAttachmentsManager.getDecryptedMediaUrl(
'/local/attachment/attachment1',
'image/jpeg',
false
);
// should not try to decrypt nor read from file again
expect(readFileContent.callCount).to.be.eq(1);
expect(decryptAttachmentBufferNode.callCount).to.be.eq(1);
expect(getItemById.callCount).to.be.eq(1);
const now2 = `${Date.now()}`;
expect(resolved2).to.be.not.empty;
expect(resolved2.startsWith(now2.slice(0, 9))).to.be.true;
});
});
});
it.skip('cleanUpOldDecryptedMedias', () => {});
it.skip('getDecryptedBlob', () => {});
});

@ -4,7 +4,7 @@ import { ipcRenderer } from 'electron';
let utilWorkerInterface: WorkerInterface | undefined;
export const callUtilsWorker = async (fnName: string, ...args: any): Promise<any> => {
export const internalCallUtilsWorker = async (fnName: string, ...args: any): Promise<any> => {
if (!utilWorkerInterface) {
const apDataPath = await ipcRenderer.invoke('get-data-path');
const utilWorkerPath = join(apDataPath, 'ts', 'webworker', 'workers', 'util.worker.js');
@ -12,3 +12,7 @@ export const callUtilsWorker = async (fnName: string, ...args: any): Promise<any
}
return utilWorkerInterface?.callWorker(fnName, ...args);
};
export const callUtilsWorker = async (fnName: string, ...args: any): Promise<any> => {
return internalCallUtilsWorker(fnName, ...args);
};

Loading…
Cancel
Save